/*――――――――――――――――――――――――――――――――――――――//
    bolyai.c
//――――――――――――――――――――――――――――――――――――――*/

#include <windows.h>

#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <bolalg.h>
#include <bolbas.h>
#include <bolcom.h>
#include <boldbe.h>
#include <bolext.h>
#include <bolfro.h>
#include <bolgui.h>
#include <bolpls.h>
#include "bolyai.h"

#define  MODNAM  PRGNAM
#define  MODVER  PRGVER
#define  PRGTIT  "Bolyai"
#define  PRGDSC  "簡易リレーショナルデータベース"

//――――――――――――――――――――――――――――――――――――――//

  // テキストウィンドウ情報
typedef struct {
  HBLK  xb;
  HBLK  bk;
  HWND  hprn;
} TXWE;
typedef TXWE *pTXWE;

iANY LOCALF TXT_settext(HWND hwnd, HBLK xb)
{ // テキスト情報設定
  pTXWE we;

  we = halloc(sizeof(TXWE), TRUE); if (!we) { return (iANY)ierr(E_MEM);}
  SetWindowLong(hwnd, sizeof(iANY), (iANY)we);
  we->xb = xb;
  we->bk = DuplicateTXT(we->xb);
  return DefBOLTXTProc(hwnd, TXCM_SETTEXT, (uANY)xb, FALSE);
}

void LOCALF cmd_savetxt(HWND hwnd)
{ // 上書保存
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;

  if (SendMessage(hwnd, TXCM_GETMODE, 0, 0) & TXCS_DED) return;
  BusyMsg(hFRM(hwnd), "保存中...");
  reset_error();
  re = SaveTXT(we->xb, WindowText(hwnd));
  MoveTXT(we->bk, DuplicateTXT(we->xb));
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), format("'%s'の保存に失敗しました。", WindowText(hwnd)), NULL);
  }
}

#define  TFILTER  "テキストファイル (*.txt,*.c)\0*.txt;*.c;*.h;*.ini\0" "すべてのファイル (*.*)\0*.*\0"

void LOCALF cmd_saveas(HWND hwnd)
{ // 名前を付けて保存
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;
  STRBUF nam, bak;
  static OFNS ofn = { TFILTER, 1, NULL, OFN_HIDEREADONLY };

  if (SendMessage(hwnd, TXCM_GETMODE, 0, 0) & TXCS_DED) return;
  get_working_path(bak, sizeof(bak));
  (ofn.nam = nam)[0] = '\0';
  if (!SaveFileDlgBox(hwnd, &ofn)) goto _10;
  if (file_exists(nam)) {
    if (YesNoBox(hFRM(hwnd), format("'%s'は既に存在します。上書きしますか？", nam), NULL) != IDYES) goto _10;
  }
  BusyMsg(hFRM(hwnd), "保存中...");
  reset_error();
  re = SaveTXT(we->xb, nam);
  MoveTXT(we->bk, DuplicateTXT(we->xb));
  SetWindowText(hwnd, nam);
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), format("'%s'の保存に失敗しました。", nam), NULL);
  }
 _10:
  set_working_path(bak);
}

BOOL LOCALF frepTXT(HREP rp, I4B msg, I4B pg, U4B pa)
{ // テキスト描画
  I4B i;
  HWND hwnd = (HWND)pa;
  HBLK xb;
  CELL cel;
  static rSTR pt;
  static STRBUF bak;

  xb = (HBLK)SendMessage(hwnd, TXCM_GETTEXT, 0, 0);
  if (msg == REPM_PAGESETUP) {
    BusyMsg(hFRM(hwnd), "処理中...");
    get_working_path(bak, sizeof(bak));
    set_working_path(dirnam(WindowText(hwnd)));
    SetCanvasHDC(rp, NULL, PRNDPI);
    StartFlowText(rp);
    for (pt = Ptr(xb), i = 0; *pt != '\0'; i++) {
      FlowText(rp, &pt, BodyCell(&cel, rp));
    }
    SetNPages(rp, i);
    set_working_path(bak);
    EndBusy(hFRM(hwnd));
  } else if (msg == REPM_STARTPRINT) {
    get_working_path(bak, sizeof(bak));
    set_working_path(dirnam(WindowText(hwnd)));
    StartFlowText(rp);
    pt = Ptr(xb);
  } else if (msg == REPM_DRAWPAGE || msg == REPM_SKIPPAGE) {
    FlowText(rp, &pt, BodyCell(&cel, rp));
  } else if (msg == REPM_ENDPRINT) {
    set_working_path(bak);
  }
  return TRUE;
}

HWND LOCALF CreatePrintPreview(HWND hwnd, pREPI ri);

void LOCALF cmd_printtxt(HWND hwnd)
{ // テキスト印刷
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  static REPI rpi = { NULL, PSZ_A4P, frepTXT, 0 };

  rpi.tit = basnamx(WindowText(hwnd));
  rpi.pa = (U4B)hwnd;
  we->hprn = CreatePrintPreview(hFRM(hwnd), &rpi);
}

void LOCALF cmd_searchtxt(HWND hwnd, BOOL sw)
{ // 文字列検索
  static STXP stx;

  if (sw == 0) {
    if (!SearchTextDlgBox(hwnd, &stx, 0)) return;
  }
  SendMessage(hwnd, TXCM_SEARCH, (uANY)stx.str, stx.flg);
}

void LOCALF cmd_compile1(HWND hwnd)
{ // チェック(テストコンパイル)
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;
  static CPLI cpi = { "BOLYAI_C.H", };

  if (SendMessage(hwnd, TXCM_GETMODE, 0, 0) & TXCS_DED) return;
  cpi.sxb = we->xb;
  BusyMsg(hFRM(hwnd), "処理中...");
  reset_error();
  re = CompileBCD(&cpi);
  EndBusy(hFRM(hwnd));
  OkBox(hFRM(hwnd), re? "エラーは見つかりませんでした。": "エラーが見つかりました。", NULL);
}

  // コンパイル情報
typedef struct {
  I1B   sfn[512];
  I4B   pro;     // -+
  I1B   nam[16]; //  |
  I1B   tit[32]; //  |= PROI
  I1B   dsc[64]; // -+
} CPLP;

BOOL LOCALF compile_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // コンパイルダイアログプロシージャ
  I4B sw;
  CPLP *pa;
  HBLK xb;
  PROI dat;
  STRBUF nam, bak;
  static OFNS ofn = { TFILTER, 1, NULL, OFN_HIDEREADONLY };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (CPLP *)lpa));
    SetESTR(hdlg, 101, pa->sfn);
    SetBSEL(hdlg, 103, pa->pro == PRO_DEF || pa->pro == 0);
    SetBSEL(hdlg, 104, pa->pro == PRO_OPR);
    SetBSEL(hdlg, 105, pa->pro == PRO_REP);
    SetESTR(hdlg, 106, pa->nam);
    SetESTR(hdlg, 107, pa->tit);
    SetESTR(hdlg, 108, pa->dsc);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (CPLP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case MKU4B(101, EN_CHANGE):
      GetESTR(hdlg, 101, nam, sizeof(nam) - 1);
      memset(&dat, 0, sizeof(PROI));
      if (file_exists(nam)) {
        sw = disable_error_reporting();
        xb = LoadTXT(NULL, nam);
        if (sw) { enable_error_reporting();}
        if (xb) { ScanProcInfo(&dat, xb); UnloadTXT(xb);}
      }
      SetBSEL(hdlg, 103, dat.pro == PRO_DEF || dat.pro == 0);
      SetBSEL(hdlg, 104, dat.pro == PRO_OPR);
      SetBSEL(hdlg, 105, dat.pro == PRO_REP);
      SetESTR(hdlg, 106, dat.nam);
      SetESTR(hdlg, 107, dat.tit);
      SetESTR(hdlg, 108, dat.dsc);
      break;
    case 102:
      GetESTR(hdlg, 101, nam, sizeof(nam) - 1);
      get_working_path(bak, sizeof(bak));
      ofn.nam = nam;
      if (OpenFileDlgBox(hdlg, &ofn)) { SetESTR(hdlg, 101, nam);}
      set_working_path(bak);
      SendMessage(hdlg, WM_NEXTDLGCTL, 0, 0);
      break;
    case IDOK:
      GetESTR(hdlg, 101, pa->sfn, sizeof(pa->sfn) - 1);
      pa->pro = GetBSEL(hdlg, 103)? PRO_DEF: GetBSEL(hdlg, 104)? PRO_OPR: PRO_REP;
      GetESTR(hdlg, 106, pa->nam, sizeof(pa->nam) - 1);
      GetESTR(hdlg, 107, pa->tit, sizeof(pa->tit) - 1);
      GetESTR(hdlg, 108, pa->dsc, sizeof(pa->dsc) - 1);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL LOCALF CompileDlgBox(HWND hwnd, CPLP *pa, BOOL sw)
{ // コンパイルダイアログボックス
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8,100,  8,  -1, "ソースコードファイル名(&S):" },
    { C_ESTR|wsT,   8, 18,196, 12, 101, "" },
    { C_BPSH|wsT, 208, 18, 26, 12, 102, "参照..." },
    { C_BGRP|wsG,   6, 36,228, 24,  -1, "プロシージャ種別" },
    { C_BSEL|wsGT, 14, 46, 60, 10, 103, "ＤＢ定義(&F)" },
    { C_BSEL|ws_,  78, 46, 60, 10, 104, "一括処理(&X)" },
    { C_BSEL|ws_, 142, 46, 60, 10, 105, "帳票作成(&R)" },
    { C_SLFT|wsG,   8, 72, 48,  8,  -1, "名　前(&N):" },
    { C_ESTR|wsT,  56, 70, 48, 12, 106, "" },
    { C_SLFT|wsG,   8, 88, 48,  8,  -1, "タイトル(&T):" },
    { C_ESTR|wsT,  56, 86, 96, 12, 107, "" },
    { C_SLFT|wsG,   8,104, 48,  8,  -1, "説　明(&D):" },
    { C_ESTR|wsT,  56,102,162, 12, 108, "" },
    { C_BDEF|wsGT,134,140, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 186,140, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 240, 160, "コンパイル" };

  if (sw == 0) {
    dit[0].sty |= wsD; dit[1].sty |= wsD; dit[2].sty |= wsD;
  } else {
    dit[0].sty &=~wsD; dit[1].sty &=~wsD; dit[2].sty &=~wsD;
  }
  return DlgBoxInput(hwnd, &dlg, compile_DlgProc, (iANY)pa) == IDOK;
}

void LOCALF cmd_compile2(HWND hwnd)
{ // コンパイル
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;
  static CPLP par;
  static CPLI cpi = { "BOLYAI_C.H", NULL, NULL, NULL, IAPP, 0, par.tit, par.dsc, };

  if (SendMessage(hwnd, TXCM_GETMODE, 0, 0) & TXCS_DED) return;
  strcpyn(par.sfn, WindowText(hwnd), sizeof(par.sfn) - 1);
  ScanProcInfo((pPROI)&par.pro, we->xb);
  if (par.nam[0] == '\0') { strcpyn(par.nam, basnamx(par.sfn), sizeof(par.nam) - 1);}
  if (par.tit[0] == '\0') { strcpyn(par.tit, par.nam, sizeof(par.tit) - 1);}
  if (!CompileDlgBox(hwnd, &par, 0)) return;
  if (par.nam[0] == '\0') { strcpyn(par.nam, basnamx(par.sfn), sizeof(par.nam) - 1);}
  if (par.tit[0] == '\0') { strcpyn(par.tit, par.nam, sizeof(par.tit) - 1);}
  cpi.ofn = addext(par.nam, BCDExt(par.pro));
  cpi.mai = BCDMain(par.pro);
  cpi.pro = par.pro;
  cpi.sxb = we->xb;
  BusyMsg(hFRM(hwnd), "処理中...");
  reset_error();
  re = CompileBCD(&cpi);
  EndBusy(hFRM(hwnd));
  ResultBox(hFRM(hwnd), "コンパイル", NULL, re);
}

iANY LOCALF TXT_command(HWND hwnd, uANY wpa, iANY lpa)
{ // コマンド
  switch (LOU2B(wpa)) {
  case IDM_SAVE:
    cmd_savetxt(hwnd); break;
  case IDM_SAVEAS:
    cmd_saveas(hwnd); break;
  case IDM_PRINT:
    cmd_printtxt(hwnd); break;
  case IDM_CUT:
    SendMessage(hwnd, WM_CUT, 0, 0); break;
  case IDM_COPY:
    SendMessage(hwnd, WM_COPY, 0, 0); break;
  case IDM_PASTE:
    SendMessage(hwnd, WM_PASTE, 0, 0); break;
  case IDM_DELETE:
    SendMessage(hwnd, WM_CLEAR, 0, 0); break;
  case IDM_SEARCH:
    cmd_searchtxt(hwnd, 0); break;
  case IDM_NSEARCH:
    cmd_searchtxt(hwnd, 1); break;
  case IDM_CHECK:
    cmd_compile1(hwnd); break;
  case IDM_COMPILE:
    cmd_compile2(hwnd); break;
  }
  return 0;
}

iANY LOCALF TXT_close(HWND hwnd)
{ // テキストウィンドウを閉じる
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B sv, re;

  sv = !(SendMessage(hwnd, TXCM_GETMODE, 0, 0) & TXCS_DED) && !!CompareTXT(we->xb, we->bk);
  if (sv) {
    re = YesNoCanBox(hFRM(hwnd), format("'%s'は変更されています。保存しますか？", WindowText(hwnd)), NULL);
    switch (re) {
    case IDYES: sv = TRUE;  break;
    case IDNO:  sv = FALSE; break;
    default: return 0;
    }
  }
  if (sv) {
    BusyMsg(hFRM(hwnd), "保存中...");
    reset_error();
    re = SaveTXT(we->xb, WindowText(hwnd));
    EndBusy(hFRM(hwnd));
    if (!re) {
      ErrorBox(hFRM(hwnd), format("'%s'の保存に失敗しました。", WindowText(hwnd)), NULL);
    }
  }
  return DefBOLTXTProc(hwnd, WM_CLOSE, 0, 0);
}

iANY LOCALF TXT_destroy(HWND hwnd)
{ // テキストウィンドウ終了処理
  pTXWE we = (pTXWE)GetWindowLong(hwnd, sizeof(iANY));

  if (IsWindow(we->hprn)) { SendMessage(hFRM(hwnd), FRMM_DESTROYCHILD, (uANY)we->hprn, 0);}
  DeleteTXT(we->bk);
  UnloadTXT(we->xb);
  hfree(we);
  return DefBOLTXTProc(hwnd, WM_DESTROY, 0, 0);
}

static I1B  TXT_POS[32];

void LOCALF dispcurpos(HWND hwnd)
{ // カーソル位置表示
  I4B ib = error_message_index_base();
  U4B rc;
  HWND htob;

  htob = GetDlgItem(hFRM(hwnd), IDTOB); if (!htob) return;
  rc = SendMessage(hwnd, TXCM_GETCUR, 0, 0);
  sprintfs(TXT_POS, "%3d 行、%d 列", LOU2B(rc) + ib, HIU2B(rc) + ib);
  SetDlgItemText(htob, IDPOS, TXT_POS);
}

iANY LOCALF TXT_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // ウィンドウプロシージャ
  switch (umsg) {
  case TXCM_SETTEXT:
    return TXT_settext(hwnd, (HBLK)wpa);
  case TXCM_SETCUR:
  case TXCM_SETTOP:
  case TXCM_UPDATE:
  case TXCM_MOVECUR:
    DefBOLTXTProc(hwnd, umsg, wpa, lpa);
    dispcurpos(hwnd);
    return 0;
  case WM_COMMAND:
    return TXT_command(hwnd, wpa, lpa);
  case WM_CLOSE:
    return TXT_close(hwnd);
  case WM_DESTROY:
    return TXT_destroy(hwnd);
  }
  return DefBOLTXTProc(hwnd, umsg, wpa, lpa);
}

I4B  LOCALF TXT_appstatus(HWND hwnd)
{ // テキストウィンドウの状態の取得
  dispcurpos(hwnd);
  return 0;
}

//――――――――――――――――――――――――――――――――――――――//

void LOCALF cmd_prevpage(HWND hwnd)
{ // 前ページ
  I4B ip;

  ip = SendMessage(hwnd, PRCM_GETPAGE, 0, 0);
  if (ip > 0) { SendMessage(hwnd, PRCM_SETPAGE, ip - 1, TRUE);}
}

void LOCALF cmd_nextpage(HWND hwnd)
{ // 次ページ
  I4B ip, np;

  ip = SendMessage(hwnd, PRCM_GETPAGE, 0, 0);
  np = SendMessage(hwnd, PRCM_NPAGES, 0, 0);
  if (ip < np - 1) { SendMessage(hwnd, PRCM_SETPAGE, ip + 1, TRUE);}
}

  // 拡大縮小倍率
static I4B  ZSCL[] = { 25, 50, 75, 100, 125, 150, 200, 300, 400 };

void LOCALF cmd_zoomin(HWND hwnd)
{ // 拡大
  I4B i, s1, s2, xy, x0, y0;
  RECT rct;

  GetClientRect(hwnd, &rct);
  xy = SendMessage(hwnd, PRCM_GETORIGIN, 0, 0);
  s1 = SendMessage(hwnd, PRCM_GETSCALE, 0, 0);
  for (i = 0; i < _countof(ZSCL) - 1; i++) {
    if (s1 < ZSCL[i]) break;
  }
  s2 = ZSCL[i];
  x0 = ((I2B)LOU2B(xy) + rct.rgt / 2) * s2 / s1 - rct.rgt / 2;
  y0 = ((I2B)HIU2B(xy) + rct.btm / 2) * s2 / s1 - rct.btm / 2;
  SendMessage(hwnd, PRCM_SETORIGIN, MKU4B(x0, y0), FALSE);
  SendMessage(hwnd, PRCM_SETSCALE, s2, TRUE);
}

void LOCALF cmd_zoomout(HWND hwnd)
{ // 縮小
  I4B i, s1, s2, xy, x0, y0;
  RECT rct;

  GetClientRect(hwnd, &rct);
  xy = SendMessage(hwnd, PRCM_GETORIGIN, 0, 0);
  s1 = SendMessage(hwnd, PRCM_GETSCALE, 0, 0);
  for (i = _countof(ZSCL) - 1; i > 0; i--) {
    if (s1 > ZSCL[i]) break;
  }
  s2 = ZSCL[i];
  x0 = ((I2B)LOU2B(xy) + rct.rgt / 2) * s2 / s1 - rct.rgt / 2;
  y0 = ((I2B)HIU2B(xy) + rct.btm / 2) * s2 / s1 - rct.btm / 2;
  SendMessage(hwnd, PRCM_SETORIGIN, MKU4B(x0, y0), FALSE);
  SendMessage(hwnd, PRCM_SETSCALE, s2, TRUE);
}

void LOCALF cmd_samescale(HWND hwnd)
{ // 等倍表示
  SendMessage(hwnd, PRCM_SETORIGIN, 0, FALSE);
  SendMessage(hwnd, PRCM_SETSCALE, 100, TRUE);
}

void LOCALF cmd_autoscale(HWND hwnd)
{ // 全体表示
  I4B pw, ph, sc;
  RECT rct;

  GetClientRect(hwnd, &rct);
  pw = SendMessage(hwnd, PRCM_PAPERWIDTH, 0, 0);
  ph = SendMessage(hwnd, PRCM_PAPERHEIGHT, 0, 0);
  if (rct.rgt * ph < rct.btm * pw) {
    sc = rct.rgt * 100 / pw;
  } else {
    sc = rct.btm * 100 / ph;
  }
  if (sc > 100) { sc = 100;}
  SendMessage(hwnd, PRCM_SETSCALE, sc, TRUE);
}

void LOCALF cmd_invert(HWND hwnd)
{ // 拡大縮小(等倍表示/全体表示切替)
  I4B sc;

  sc = SendMessage(hwnd, PRCM_GETSCALE, 0, 0);
  if (sc == 100) { cmd_autoscale(hwnd);} else { cmd_samescale(hwnd);}
}

void LOCALF cmd_setprn(HWND hwnd)
{ // 用紙設定
  HREP rp;

  rp = (HREP)SendMessage(hwnd, PRCM_GETREPORT, 0, 0);
  PageSetup(hwnd, rp);
  SendMessage(hwnd, PRCM_SETREPORT, (uANY)rp, TRUE);
}

void LOCALF cmd_print(HWND hwnd)
{ // 印刷
  HREP rp;

  rp = (HREP)SendMessage(hwnd, PRCM_GETREPORT, 0, 0);
  PrintReport(hwnd, rp);
}

iANY LOCALF PRN_command(HWND hwnd, uANY wpa, iANY lpa)
{ // コマンド
  switch (LOU2B(wpa)) {
  case IDM_PREVPAGE:
    cmd_prevpage(hwnd); break;
  case IDM_NEXTPAGE:
    cmd_nextpage(hwnd); break;
  case IDM_ZOOMIN:
    cmd_zoomin(hwnd); break;
  case IDM_ZOOMOUT:
    cmd_zoomout(hwnd); break;
  case IDM_SAMESCALE:
    cmd_samescale(hwnd); break;
  case IDM_AUTOSCALE:
    cmd_autoscale(hwnd); break;
  case IDM_INVERT:
    cmd_invert(hwnd); break;
  case IDM_SETPRN:
    cmd_setprn(hwnd); break;
  case IDM_PRINT:
    cmd_print(hwnd); break;
  }
  return 0;
}

iANY LOCALF PRN_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // ウィンドウプロシージャ
  switch (umsg) {
  case WM_COMMAND:
    return PRN_command(hwnd, wpa, lpa);
  case WM_DESTROY:
    DeleteReport((HREP)SendMessage(hwnd, PRCM_GETREPORT, 0, 0)); break;
  }
  return DefBOLPRNProc(hwnd, umsg, wpa, lpa);
}

#define  APPS_PREVPAGEAVAILABLE    0x00000010
#define  APPS_NEXTPAGEAVAILABLE    0x00000020
#define  APPS_LOWERLIMITSCALE      0x00000040
#define  APPS_UPPERLIMITSCALE      0x00000080
#define  APPS_SKIPPAGESETUP        0x00000100

#define  APPS_PVP  APPS_PREVPAGEAVAILABLE
#define  APPS_NXP  APPS_NEXTPAGEAVAILABLE
#define  APPS_LSC  APPS_LOWERLIMITSCALE
#define  APPS_USC  APPS_UPPERLIMITSCALE
#define  APPS_SKP  APPS_SKIPPAGESETUP

static I1B  PRN_PAG[32];
static I1B  PRN_SCL[32];

I4B  LOCALF PRN_appstatus(HWND hwnd)
{ // 印刷プレビューウィンドウの状態の取得
  I4B ip, np, sc, sta = 0;
  HREP rp;

  rp = (HREP)SendMessage(hwnd, PRCM_GETREPORT, 0, 0);
  ip = SendMessage(hwnd, PRCM_GETPAGE, 0, 0);
  np = SendMessage(hwnd, PRCM_NPAGES, 0, 0);
  if (ip > 0) { sta |= APPS_PVP;}
  if (ip < np - 1) { sta |= APPS_NXP;}
  if (PageSetupInfo(rp)->adj & RSW_SKP) { sta |= APPS_SKP;}
  sprintfs(PRN_PAG, "%3d / %d", ip + 1, np);
  sc = SendMessage(hwnd, PRCM_GETSCALE, 0, 0);
  if (sc <= ZSCL[0]) { sta |= APPS_LSC;} else if (sc >= ZSCL[_countof(ZSCL) - 1]) { sta |= APPS_USC;}
  sprintfs(PRN_SCL, "%3d ％", sc);
  return sta;
}

HWND LOCALF CreatePrintPreviewX(HWND hwnd, pREPI ri, WNDPROC prc)
{ // 印刷プレビューウィンドウの作成
  HWND hprn;
  HREP rp;
  static CREI cri = { "BOLPRN", wsCHV, "印刷プレビュー", IDPRN, };

  if (IsWindow(hprn = GetDlgItem(hwnd, IDPRN))) { SendMessage(hwnd, FRMM_DESTROYCHILD, (uANY)hprn, 0);}
  rp = CreateReport(ri); if (!rp) return NULL;
  if (!ReportSetup(hwnd, rp)) goto _10;
  if (!PageSetup(hwnd, rp)) goto _10;
  cri.pa = (U4B)rp;
  hprn = (HWND)SendMessage(hwnd, FRMM_CREATECHILD, (uANY)&cri, (iANY)prc); if (!hprn) goto _10;
  return hprn;

 _10:
  DeleteReport(rp);
  return NULL;
}

HWND LOCALF CreatePrintPreview(HWND hwnd, pREPI ri)
{ // 印刷プレビューウィンドウの作成
  return CreatePrintPreviewX(hwnd, ri, PRN_WndProc);
}

//――――――――――――――――――――――――――――――――――――――//

  // ビットマップウィンドウ情報
typedef struct {
  HDIB  bm;
  HDIB  bk;
  HWND  hprn;
} DIWE;
typedef DIWE *pDIWE;

iANY LOCALF DIB_setimage(HWND hwnd, HDIB bm)
{ // ビットマップ情報設定
  pDIWE we;

  we = halloc(sizeof(DIWE), TRUE); if (!we) { return (iANY)ierr(E_MEM);}
  SetWindowLong(hwnd, sizeof(iANY), (iANY)we);
  we->bm = bm;
  return DefBOLDIBProc(hwnd, DICM_SETIMAGE, (uANY)bm, FALSE);
}

BOOL LOCALF frepDIB(HREP rp, I4B msg, I4B pg, U4B pa)
{ // ビットマップ描画
  HDIB bm;
  CELL cel;
  static I4B flg;

  bm = (HDIB)SendMessage((HWND)pa, DICM_GETIMAGE, 0, 0);
  if (msg == REPM_SETUP) {
    flg = DT_FRC|DT_AJW;
  } else if (msg == REPM_DRAWPAGE) {
    CellImage(rp, BodyCell(&cel, rp), bm, flg);
  }
  return TRUE;
}

void LOCALF cmd_printdib(HWND hwnd)
{ // 画像印刷
  pDIWE we = (pDIWE)GetWindowLong(hwnd, sizeof(iANY));
  static REPI rpi = { NULL, PSZ_A4P, frepDIB, 0 };

  rpi.tit = basnamx(WindowText(hwnd));
  rpi.pa = (U4B)hwnd;
  we->hprn = CreatePrintPreview(hFRM(hwnd), &rpi);
}

iANY LOCALF DIB_command(HWND hwnd, uANY wpa, iANY lpa)
{ // コマンド
  switch (LOU2B(wpa)) {
  case IDM_ZOOMIN:
    cmd_zoomin(hwnd); break;
  case IDM_ZOOMOUT:
    cmd_zoomout(hwnd); break;
  case IDM_SAMESCALE:
    cmd_samescale(hwnd); break;
  case IDM_AUTOSCALE:
    cmd_autoscale(hwnd); break;
  case IDM_INVERT:
    cmd_invert(hwnd); break;
  case IDM_PRINT:
    cmd_printdib(hwnd); break;
  }
  return 0;
}

iANY LOCALF DIB_destroy(HWND hwnd)
{ // ビットマップウィンドウ終了処理
  pDIWE we = (pDIWE)GetWindowLong(hwnd, sizeof(iANY));

  if (IsWindow(we->hprn)) { SendMessage(hFRM(hwnd), FRMM_DESTROYCHILD, (uANY)we->hprn, 0);}
  DeleteDIB(we->bm);
  hfree(we);
  return DefBOLDIBProc(hwnd, WM_DESTROY, 0, 0);
}

iANY LOCALF DIB_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // ウィンドウプロシージャ
  switch (umsg) {
  case DICM_SETIMAGE:
    return DIB_setimage(hwnd, (HDIB)wpa);
  case WM_COMMAND:
    return DIB_command(hwnd, wpa, lpa);
  case WM_DESTROY:
    return DIB_destroy(hwnd);
  }
  return DefBOLDIBProc(hwnd, umsg, wpa, lpa);
}

static I1B  DIB_PAG[32] = "  1 / 1";
static I1B  DIB_SCL[32];

I4B  LOCALF DIB_appstatus(HWND hwnd)
{ // ビットマップウィンドウの状態の取得
  I4B sc, sta = 0;

  sc = SendMessage(hwnd, DICM_GETSCALE, 0, 0);
  if (sc <= ZSCL[0]) { sta |= APPS_LSC;} else if (sc >= ZSCL[_countof(ZSCL) - 1]) { sta |= APPS_USC;}
  sprintfs(DIB_SCL, "%3d ％", sc);
  return sta;
}

//――――――――――――――――――――――――――――――――――――――//

static MNUI POPMI[] = {
  { mfP,  0,             ""                        }, // POP0
  { mf_,  IDM_CUT,       "切り取り(&T)\tCtrl+X"    },
  { mf_,  IDM_COPY,      "コピー(&C)\tCtrl+C"      },
  { mf_,  IDM_PASTE,     "貼り付け(&P)\tCtrl+V"    },
  { mf_,  0,             ""                        },
  { mf_,  IDM_CLEAR,     "クリア(&A)\tDel"         },
  { mf_,  0,             ""                        },
  { mfE,  IDM_OPENLINK,  "リンクを開く(&O)"        },
  { mfP,  0,             ""                        }, // POP1
  { mf_,  IDM_CUT,       "切り取り(&T)\tCtrl+X"    },
  { mf_,  IDM_COPY,      "コピー(&C)\tCtrl+C"      },
  { mf_,  IDM_PASTE,     "貼り付け(&P)\tCtrl+V"    },
  { mf_,  0,             ""                        },
  { mfE,  IDM_CLEAR,     "クリア(&A)\tDel"         },
  { mfP,  0,             ""                        }, // POP2
  { mf_,  IDM_CUT,       "切り取り(&T)\tCtrl+X"    },
  { mf_,  IDM_COPY,      "コピー(&C)\tCtrl+C"      },
  { mf_,  IDM_PASTE,     "貼り付け(&P)\tCtrl+V"    },
  { mf_,  0,             ""                        },
  { mf_,  IDM_INSERT,    "挿入(&I)\tCtrl+E"        },
  { mf_,  IDM_DELETE,    "削除(&D)\tCtrl+D"        },
  { mfE,  IDM_CLEAR,     "クリア(&A)\tDel"         },
  { mfPE, 0,             ""                        }, // POP3
  { mf_,  IDM_ARRANGE,   "表示項目(&A)..."         },
  { mf_,  IDM_FILTER,    "絞り込み(&F)..."         },
  { mfE,  IDM_SORT,      "並べ替え(&S)..."         },
};
static MNUS POPMS = { POPMI, _countof(POPMI) };

static HMENU hmnuPop, hmnuPo0, hmnuPo1, hmnuPo2, hmnuPo3;

void LOCALF InitPopupMenus(void)
{ // ポップアップメニュー設定
  hmnuPop = CreateMenuBar(&POPMS);
  hmnuPo0 = GetSubMenu(hmnuPop, 0);
  hmnuPo1 = GetSubMenu(hmnuPop, 1);
  hmnuPo2 = GetSubMenu(hmnuPop, 2);
  hmnuPo3 = GetSubMenu(hmnuPop, 3);
}

void LOCALF TermPopupMenus(void)
{ // ポップアップメニュー削除
  DestroyMenu(hmnuPop);
}

BOOL LOCALF LoadUserVIW(HTBL tvu)
{ // ユーザー定義表示形式セット読込
  I4B re = FALSE;
  STRBUF bak;

  get_working_path(bak, sizeof(bak));
  set_working_path(UserPath());
  if (file_exists(TableFileName(tvu))) {
    re = LoadBTB(tvu);
  }
  set_working_path(bak);
  return re;
}

BOOL LOCALF SaveUserVIW(HTBL tvu)
{ // ユーザー定義表示形式セット保存
  I4B sw, re = FALSE;
  STRBUF bak;

  get_working_path(bak, sizeof(bak));
  set_working_path(UserPath());
  sw = disable_error_reporting();
  if (file_exists(TableFileName(tvu)) || NTableRows(tvu) > 0) {
    re = SaveBTB(tvu);
  }
  if (sw) { enable_error_reporting();}
  set_working_path(bak);
  return re;
}

  // 表ウィンドウ設定情報
typedef struct {
  HOPN  op;
  I4B   flg;
  rSTR  tit;
  rVIWS vs;
  I4B   iv0;
} TBWI;
typedef TBWI *pTBWI;

  // 表ウィンドウ情報
typedef struct {
  HOPN  op;   // -+
  I4B   flg;  //  |
  rSTR  tit;  //  |
  rVIWS vs;   //  |= TBWI
  I4B   iv0;  // -+
  HWND  hprn;
  HWND  hsum;
  HTBL  tvs;
  HTBL  tvu;
  HTBL  tv;
  HBUF  bv;
  HTBL  tg;
  HTBL  tsm;
} TBWE;
typedef TBWE *pTBWE;

rSTR LOCALF defface(void);
I4B  LOCALF defptsz(void);
I4B  LOCALF optflg(void);
HWND LOCALF CreateTableWindow(HWND hwnd, I4B id, pTBWI wi);

iANY LOCALF TBL_settable(HWND hwnd, pTBWI wi)
{ // 表情報設定
  pTBWE we;
  I4B ir, re;
  HTBL tb;
  VIWI viw;

  we = halloc(sizeof(TBWE), TRUE); if (!we) { return (iANY)ierr(E_MEM);}
  SetWindowLong(hwnd, sizeof(iANY), (iANY)we);
  *(pTBWI)we = *wi;
  we->flg |= optflg();
  if (IsReadOnly(we->op)) { we->flg |= (TBCS_DED|TBCS_DSE);}
  SendMessage(hwnd, TBCM_SETMODE, we->flg, FALSE);
  tb = OHTBL(we->op);
  re = DefBOLTBLProc(hwnd, TBCM_SETTABLE, (uANY)tb, TRUE);
  if (!(we->flg & TBCS_DCV)) {
    if (we->vs) {
      we->tvs = CreateVIWTable(0, we->vs); if (!we->tvs) { return re;}
    }
    we->tvu = CreateVIWTable(32, NULL); if (!we->tvu) { return re;}
    SetTableFileName(we->tvu, addext(TableName(tb), ".VIW"));
    we->tv = CreateVIWTable(32, NULL); if (!we->tv) { return re;}
    we->bv = CreateRowBuf(we->tv); if (!we->bv) { return re;}
    LoadUserVIW(we->tvu);
    if (we->tvs) { CopyTable(we->tv, we->tvs);}
    MergeTable(we->tv, we->tvu);
    if (we->tvs && we->iv0 >= 0 && we->iv0 < NTableRows(we->tvs)) {
      GetTableRow(we->bv, we->tv, we->iv0);
    } else if ((ir = GetLastVIW(we->tv)) >= 0) {
      GetTableRow(we->bv, we->tv, ir);
    } else if (we->tvs && NTableRows(we->tvs) > 0) {
      GetTableRow(we->bv, we->tv, 0);
    }
    SendMessage(hwnd, TBCM_CHANGEVIEW, (uANY)SetVIWInfo(&viw, we->bv), TRUE);
  }
  return re;
}

iANY LOCALF TBL_trackpopup(HWND hwnd, rPOSI lc)
{ // ポップアップメニュー
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B s0, s1, s2, sta;
  HVIW vw;
  HMENU hmnu;
  RBLK r;
  POINT pnt;
  STRBUF bf;

  s0 = SendMessage(hwnd, TBCM_GETSEL, (uANY)&r, 0);
  sta = AppStatus(hFRM(hwnd));
  if (lc->ir >= 0 && lc->ic >= 0 && !(s0 && lc->ir >= r.r1 && lc->ir <= r.r2)) {
    vw = (HVIW)SendMessage(hwnd, TBCM_GETVIEW, 0, 0);
    PrintViewCellValueF(bf, vw, lc->ir, lc->ic, 0);
    if ((ViewColumnFlagsF(vw, lc->ic) & CF_LNK) && bf[0] != '\0') {
      hmnu = hmnuPo0;
    } else {
      hmnu = hmnuPo1;
    }
    s1 = (!(we->flg & TBCS_DED));
    s2 = (s1 && (sta & APPS_CFT));
    EnableMenuItem(hmnu, IDM_CUT,    s1? mf_: mfG);
    EnableMenuItem(hmnu, IDM_PASTE,  s2? mf_: mfG);
    EnableMenuItem(hmnu, IDM_CLEAR,  s1? mf_: mfG);
  } else if (lc->ir >= 0) {
    hmnu = hmnuPo2;
    s1 = (!(we->flg & (TBCS_DED|TBCS_DSE)));
    s2 = (s1 && (sta & APPS_CFB));
    EnableMenuItem(hmnu, IDM_CUT,    s1? mf_: mfG);
    EnableMenuItem(hmnu, IDM_PASTE,  s2? mf_: mfG);
    EnableMenuItem(hmnu, IDM_INSERT, s1? mf_: mfG);
    EnableMenuItem(hmnu, IDM_DELETE, s1? mf_: mfG);
    EnableMenuItem(hmnu, IDM_CLEAR,  s1? mf_: mfG);
  } else { // lc->ic < 0
    hmnu = hmnuPo3;
  }
  GetCursorPos(&pnt);
  TrackPopupMenuEx(hmnu, TPM_RIGHTBUTTON, pnt.x, pnt.y, hwnd, NULL);
  return 0;
}

void LOCALF cmd_save(HWND hwnd)
{ // 上書保存
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;

  if (SendMessage(hwnd, TBCM_GETMODE, 0, 0) & TBCS_DED) return;
  BusyMsg(hFRM(hwnd), "処理中...");
  reset_error();
  re = CheckTable(OHTBL(we->op));
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), "エラーが見つかりました。\n保存はキャンセルされます。", NULL); return;
  }
  BusyMsg(hFRM(hwnd), "保存中...");
  reset_error();
  re = SaveTable(we->op);
  if (re) { SendMessage(hwnd, TBCM_UPDATE, FALSE, TRUE);}
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), format("'%s'の保存に失敗しました。", WindowText(hwnd)), NULL);
  }
}

void LOCALF cmd_import(HWND hwnd)
{ // テキスト取込
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;
  HVIW vw;
  STRBUF nam, bak;
  static OFNS ofn = { TFILTER, 1, NULL, OFN_HIDEREADONLY };
  static CSVI csi = { '\t', 0, TSW_NAM };

  if (SendMessage(hwnd, TBCM_GETMODE, 0, 0) & TBCS_DED) return;
  get_working_path(bak, sizeof(bak));
  (ofn.nam = nam)[0] = '\0';
  re = OpenFileDlgBox(hwnd, &ofn);
  set_working_path(bak);
  if (!re) return;
  if (!CSVInfoDlgBox(hwnd, &csi)) return;
  vw = (HVIW)SendMessage(hwnd, TBCM_GETVIEW, 0, 0);
  BusyMsg(hFRM(hwnd), "読込中...");
  reset_error();
  re = ReadCSV(vw, nam, &csi);
  if (re) { SendMessage(hwnd, TBCM_UPDATE, FALSE, TRUE);}
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), format("'%s'の読込に失敗しました。", WindowText(hwnd)), NULL);
  }
}

void LOCALF cmd_export(HWND hwnd)
{ // テキスト書出
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;
  HVIW vw;
  STRBUF nam, bak;
  static OFNS ofn = { TFILTER, 1, NULL, OFN_HIDEREADONLY };
  static CSVI csi = { '\t', 0, TSW_NAM };

  get_working_path(bak, sizeof(bak));
  (ofn.nam = nam)[0] = '\0';
  re = SaveFileDlgBox(hwnd, &ofn);
  set_working_path(bak);
  if (!re) return;
  if (file_exists(nam)) {
    if (YesNoBox(hFRM(hwnd), format("'%s'は既に存在します。上書きしますか？", nam), NULL) != IDYES) return;
  }
  if (!CSVInfoDlgBox(hwnd, &csi)) return;
  vw = (HVIW)SendMessage(hwnd, TBCM_GETVIEW, 0, 0);
  BusyMsg(hFRM(hwnd), "書出中...");
  reset_error();
  re = WriteCSV(vw, nam, &csi);
  if (re) { SendMessage(hwnd, TBCM_UPDATE, FALSE, TRUE);}
  EndBusy(hFRM(hwnd));
  if (!re) {
    ErrorBox(hFRM(hwnd), format("'%s'の書出に失敗しました。", WindowText(hwnd)), NULL);
  }
}

  // 表描画情報
typedef struct {
  I4B   ns;
  F8B   *cw;
  F8B   dcw, drh, daw;
} TBLP;

BOOL LOCALF frepTBL(HREP rp, I4B msg, I4B pg, U4B pa)
{ // 表の描画
  I4B i, j, nr, nc, br, md, op, zr;
  HVIW vw;
  TBLP *px;
  CELL cel;
  GRID grd;
  WHSZ siz;
  STRBUF bf;

  vw = (HVIW)SendMessage((HWND)pa, TBCM_GETVIEW, 0, 0);
  if (msg == REPM_CREATE) {
    nc = NTableColumns(ViewHTBL(vw));
    px = halloc(sizeof(TBLP) + nc * sizeof(F8B), TRUE); if (!px) return FALSE;
    px->cw = (pANY)((pBIN)px + sizeof(TBLP));
    SetReportExtra(rp, (U4B)px);
    return TRUE;
  }
  px = (TBLP *)ReportExtra(rp);
  nr = NViewRows(vw);
  nc = NViewColumns(vw);
  md = SendMessage((HWND)pa, TBCM_GETMODE, 0, 0);
  op = ((md & TBCS_UCN)? PVF_NAM: (md & TBCS_UCI)? PVF_IDX: PVF_TIT) | ((md & TBCS_ZBI)? PVF_ZBI: PVF_OBI);
  zr = (md & TBCS_HCH)? 0: 1;
  if (msg == REPM_SETUP) {
    SetTextFont(rp, defface(), PT2MM(defptsz()), 0, 0);
    AveCharSize(&siz, rp);
    px->dcw = siz.w;
    px->drh = siz.h * 1.2;
    px->daw = 0.0;
    for (j = 0; j < nc; j++) {
      px->cw[j] = px->dcw * ((F8B)ViewColumnWidthF(vw, j) + 0.5);
      px->daw += px->cw[j];
    }
    SetReqBodyWidth(rp, px->daw, 0);
    SetCellMargin(rp, px->dcw / 3, 0.0);
  } else if (msg == REPM_PAGESETUP) {
    px->ns = (I4B)(BodyHeight(rp) / px->drh) - zr;
    SetNPages(rp, ((nr - 1) / px->ns) + 1);
  } else if (msg == REPM_DRAWPAGE) {
    SetTextFont(rp, defface(), PT2MM(defptsz()), 0, 0);
    HeaderCell(&cel, rp);
    CellText(rp, &cel, ReportTitle(rp), DT_LFT);
    CellText(rp, &cel, dformat("yyyy/mm/dd", ReportDate(rp)), DT_RGT);
    SetGrid1(&grd, BodyLeft(rp), BodyTop(rp), nc, px->ns + zr, px->cw, px->drh);
    br = (pg - 1) * px->ns;
    for (i = -zr; i < px->ns; i++) {
      for (j = 0; j < nc; j++) {
        if (px->cw[j] == 0.0) continue;
        PrintViewCellValueF(bf, vw, (i >= 0)? br + i: -1, j, op);
        GridCellText(rp, &grd, i + zr, j, RST_R_M, bf, DT_AUT|((i >= 0)? ViewColumnTextAlignF(vw, j): DT_CEN));
      }
    }
    FooterCell(&cel, rp);
    CellText(rp, &cel, format("- %d -", pg), DT_CEN);
  } else if (msg == REPM_DESTROY) {
    hfree(px);
  }
  return TRUE;
}

void LOCALF cmd_printtbl(HWND hwnd)
{ // 表印刷
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  static REPI rpi = { NULL, PSZ_A4P, frepTBL, 0 };

  if (IsWindow(we->hprn)) { SendMessage(we->hprn, WM_CLOSE, 0, 0);}
  rpi.tit = TableTitle(OHTBL(we->op));
  rpi.pa = (U4B)hwnd;
  we->hprn = CreatePrintPreview(hFRM(hwnd), &rpi);
}

  // 単票描画情報
typedef struct {
  F8B   cw[2];
  F8B   dcw, dch, drh, daw;
} SLPP;

BOOL LOCALF frepSLP(HREP rp, I4B msg, I4B pg, U4B pa)
{ // 単票の描画
  I4B i, nr, nc;
  HVIW vw;
  SLPP *px;
  CELL cel;
  GRID grd;
  WHSZ siz;
  STRBUF bf;

  if (msg == REPM_CREATE) {
    px = halloc(sizeof(SLPP), TRUE); if (!px) return FALSE;
    SetReportExtra(rp, (U4B)px);
    return TRUE;
  }
  px = (SLPP *)ReportExtra(rp);
  vw = (HVIW)SendMessage((HWND)pa, TBCM_GETVIEW, 0, 0);
  nr = NViewRows(vw);
  nc = NViewColumns(vw);
  if (msg == REPM_SETUP) {
    SetTextFont(rp, defface(), PT2MM(defptsz()), 0, 0);
    AveCharSize(&siz, rp);
    px->dcw = siz.w;
    px->drh = siz.h * 1.2;
    px->cw[0] =  48.0;
    px->cw[1] = 122.0;
    px->daw = px->cw[0] + px->cw[1];
    SetReqBodyWidth(rp, px->daw, 0);
    SetCellMargin(rp, px->dcw / 3, 0.0);
  } else if (msg == REPM_PAGESETUP) {
    SetNPages(rp, nr);
  } else if (msg == REPM_DRAWPAGE) {
    SetTextFont(rp, defface(), PT2MM(defptsz()), 0, 0);
    HeaderCell(&cel, rp);
    CellText(rp, &cel, ReportTitle(rp), DT_LFT);
    CellText(rp, &cel, dformat("yyyy/mm/dd", ReportDate(rp)), DT_RGT);
    SetGrid1(&grd, BodyLeft(rp), BodyTop(rp), 2, nc, px->cw, px->drh);
    for (i = 0; i < nc; i++) {
      GridCellText(rp, &grd, i, 0, RST_R_M, ViewColumnDescriptionR(vw, i), DT_AUT);
      PrintViewCellValue(bf, vw, pg - 1, i);
      GridCellText(rp, &grd, i, 1, RST_R_M, bf, DT_AUT);
    }
    FooterCell(&cel, rp);
    CellText(rp, &cel, format("- %d -", pg), DT_CEN);
  } else if (msg == REPM_DESTROY) {
    hfree(px);
  }
  return TRUE;
}

void LOCALF cmd_printslp(HWND hwnd)
{ // 単票印刷
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  static REPI rpi = { NULL, PSZ_A4P, frepSLP, 0 };

  if (IsWindow(we->hprn)) { SendMessage(we->hprn, WM_CLOSE, 0, 0);}
  rpi.tit = TableTitle(OHTBL(we->op));
  rpi.pa = (U4B)hwnd;
  we->hprn = CreatePrintPreview(hFRM(hwnd), &rpi);
}

void LOCALF cmd_search(HWND hwnd, BOOL sw)
{ // 文字列検索
  static STXP stx;

  if (sw == 0) {
    if (!SearchTextDlgBox(hwnd, &stx, 1)) return;
  }
  SendMessage(hwnd, TBCM_SEARCH + sw, (uANY)stx.str, stx.flg);
}

  // 表示形式名
typedef struct {
  I1B   nam[32];
} VNMP;

BOOL LOCALF VNM_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 表示形式名ダイアログプロシージャ
  VNMP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VNMP *)lpa));
    SetESTR(hdlg, 101, pa->nam);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VNMP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetESTR(hdlg, 101, pa->nam, sizeof(pa->nam) - 1);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL LOCALF GetVNM(HWND hwnd, VNMP *pa, BOOL sw)
{ // 表示形式名
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 48,  8,  -1, "名　前(&N):" },
    { C_ESTR|wsT,  56,  8, 48, 12, 101, "" },
    { C_BDEF|wsGT, 54, 60, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 106, 60, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 80, NULL };

  dlg.tit = (sw == 0)? "表示形式登録": "名前変更";
  return DlgBoxInput(hwnd, &dlg, VNM_DlgProc, (iANY)pa) == IDOK;
}

  // 表示形式設定情報
typedef struct {
  HTBL  tv;
  HBUF  bv;
} VIWP;

#define  IDREG  22
#define  IDCHG  23
#define  IDDEL  24

BOOL LOCALF VIW_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 表示形式設定ダイアログプロシージャ
  I4B ir, ix, sw, ud = 0;
  VIWP *pa;
  VNMP dat;
  static TBCI tci = { 10, "nam, ud", NULL, NULL, TTF_ADJ, 1, 0 };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VIWP *)lpa));
    if ((ir = SearchVIWTableRow(pa->tv, pa->bv)) < 0) {
      SetRowBufCellValue(pa->bv, 0, "未登録");
      SetRowBufCellValue(pa->bv, 1, I4BBox(1));
      SetNewTableRow(pa->tv, pa->bv);
      ir = NTableRows(pa->tv) - 1;
    }
    SetTSEL(hdlg, 101, ir, pa->tv, &tci);
    sw = (strcmp(TableRow(pa->tv, ir), "未登録") != 0);
    GetTableCellValue(&ud, pa->tv, ir, 1);
    EnableDlgItem(hdlg, IDREG, ud && !sw);
    EnableDlgItem(hdlg, IDCHG, ud && sw);
    EnableDlgItem(hdlg, IDDEL, ud && sw);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VIWP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case MKU4B(101, APPN_SELCHANGE): _10:
      if (NTableRows(pa->tv) > 0) {
        ir = GetTSEL(hdlg, 101);
        sw = (strcmp(TableRow(pa->tv, ir), "未登録") != 0);
        GetTableCellValue(&ud, pa->tv, ir, 1);
      } else { ud = sw = 0;}
      EnableDlgItem(hdlg, IDREG, ud && !sw);
      EnableDlgItem(hdlg, IDCHG, ud && sw);
      EnableDlgItem(hdlg, IDDEL, ud && sw);
     _20: RedrawWindow(GetDlgItem(hdlg, 101), NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
      SendDlgItemMessage(hdlg, IDREG, BM_SETSTYLE, bsP, TRUE);
      SendDlgItemMessage(hdlg, IDCHG, BM_SETSTYLE, bsP, TRUE);
      SendDlgItemMessage(hdlg, IDDEL, BM_SETSTYLE, bsP, TRUE);
      SendDlgItemMessage(hdlg, IDOK,  BM_SETSTYLE, bsD, TRUE);
      SetFocus(GetDlgItem(hdlg, 101));
      break;
    case IDREG:
    case IDCHG:
      if (NTableRows(pa->tv) > 0) {
        ir = GetTSEL(hdlg, 101);
        sw = (strcmp(GetTableCellValue(dat.nam, pa->tv, ir, 0), "未登録") != 0);
        if (sw == 0) { dat.nam[0] = '\0';}
        if (GetVNM(hdlg, &dat, sw)) {
          if (dat.nam[0] == '\0') { ErrorBox(hdlg, "名前が必要です。", NULL); break;}
          ix = SearchVIWTableRowByName(pa->tv, dat.nam);
          if (ix >= 0) { ErrorBox(hdlg, "既にある名前です。", NULL); break;}
          SetTableCellValue(pa->tv, ir, 0, dat.nam);
          SetTSEL(hdlg, 101, ir, pa->tv, &tci); goto _10;
        }
      }
      goto _20;
    case IDDEL:
      if (NTableRows(pa->tv) > 0) {
        ir = GetTSEL(hdlg, 101);
        DeleteTableRow(pa->tv, ir);
        SetTSEL(hdlg, 101, ir, pa->tv, &tci); goto _10;
      }
      goto _20;
    case MKU4B(101, APPN_LBUTTONDBLCLK): wpa = IDOK;
    case IDOK:
      if (NTableRows(pa->tv) > 0) {
        ir = GetTSEL(hdlg, 101);
        GetTableRow(pa->bv, pa->tv, ir);
      }
      // fall through
    case IDCANCEL:
      if ((ir = SearchVIWTableRowByName(pa->tv, "未登録")) >= 0) {
        DeleteTableRow(pa->tv, ir);
      }
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_view(HWND hwnd)
{ // 表示形式
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  VIWI viw;
  VIWP par;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8, 32,  8,  -1, "表示形式" },
    { C_TSEL|wsT,   8, 18,156,116, 101, "" },
    { C_BPSH|wsGT,170, 18, 48, 14, IDREG, "登録(&R)" },
    { C_BPSH|wsT, 170, 36, 48, 14, IDCHG, "名前変更(&C)" },
    { C_BPSH|wsT, 170, 54, 48, 14, IDDEL, "削除(&D)" },
    { C_BDEF|wsGT,118,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 170,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 224, 176, "表示形式" };

  if (we->flg & TBCS_DCV) return;
  par.tv = DuplicateTable(we->tv);  if (!par.tv) return;
  par.bv = DuplicateRowBuf(we->bv); if (!par.bv) goto _20;
  if (DlgBoxInput(hwnd, &dlg, VIW_DlgProc, (iANY)&par) == IDCANCEL) goto _10;
  CopyTable(we->tv, par.tv);
  CopyRowBuf(we->bv, par.bv);
  SendMessage(hwnd, TBCM_CHANGEVIEW, (uANY)SetVIWInfo(&viw, we->bv), TRUE);
 _10: DeleteRowBuf(par.bv);
 _20: DeleteTable(par.tv);
}

void LOCALF SetLTIT(HWND hdlg, I4B id, I4B ir, HTBL ta, BOOL sw)
{ // 項目名リスト作成
  I4B i, i0, ni;
  rI4B vi;
  HTBL tb;

  vi = (rI4B)TablePtr(ta);
  tb = (HTBL)TableColumnExtra(ta, 0);
  if (sw == 0) {
    i0 = 0; ni = NTableRows(ta);
  } else {
    i0 = NTableRows(ta); ni = TableCapacity(ta) - i0;
  }
  SendDlgItemMessage(hdlg, id, WM_SETREDRAW, FALSE, 0);
  SendDlgItemMessage(hdlg, id, LB_RESETCONTENT, 0, 0);
  for (i = 0; i < ni; i++) {
    SendDlgItemMessage(hdlg, id, LB_ADDSTRING, 0, (iANY)TableColumnTitle(tb, vi[i0 + i]));
  }
  SendDlgItemMessage(hdlg, id, LB_ADDSTRING, 0, (iANY)"");
  SendDlgItemMessage(hdlg, id, LB_SETCURSEL, ir, 0);
  SendDlgItemMessage(hdlg, id, WM_SETREDRAW, TRUE, 0);
  InvalidateRect(GetDlgItem(hdlg, id), NULL, TRUE);
}

  // 表示項目設定情報
typedef struct {
  HTBL  ta;
  pSTR  arr;
  pU2B  pf;
} VIW0P;

BOOL LOCALF VIW0_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 表示項目ダイアログプロシージャ
  I4B i1, i2, fc;
  VIW0P *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VIW0P *)lpa));
    ScanARRTable(pa->ta, pa->arr);
    SetLTIT(hdlg, 101, 0, pa->ta, 0);
    SetLTIT(hdlg, 102, 0, pa->ta, 1);
    SetEINT(hdlg, 105, *pa->pf);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VIW0P *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 103:
      if ((i2 = GetLSEL(hdlg, 102)) < TableCapacity(pa->ta) - NTableRows(pa->ta)) {
        InsertARRTableRow(pa->ta, i1 = GetLSEL(hdlg, 101), i2);
        i1++;
        goto _10;
      }
      break;
    case 104:
      if ((i1 = GetLSEL(hdlg, 101)) < NTableRows(pa->ta)) {
        i2 = DeleteARRTableRow(pa->ta, i1);
       _10:
        SetLTIT(hdlg, 101, i1, pa->ta, 0);
        SetLTIT(hdlg, 102, i2, pa->ta, 1);
      }
      break;
    case IDPSH+1:
    case IDPSH+2:
    case IDOK:
      PrintARRTable(pa->arr, pa->ta);
      fc = GetEINT(hdlg, 105); if (fc >= 0 && fc < NTableRows(pa->ta)) { *pa->pf = (U2B)fc;}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

iANY LOCALF VIW1_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 絞り込み条件表のウィンドウプロシージャ
  switch (umsg) {
  case TBCM_ASKCELLFORMAT:
    if (((rPOSI)wpa)->ir == VIWCAP - 1 && ((rPOSI)wpa)->ic > 0) {
      return DC_INR|DC_DED|DC_RHD;
    }
    break;
  }
  return DefBOLTBLProc(hwnd, umsg, wpa, lpa);
}

  // 絞り込み条件設定情報
typedef struct {
  HTBL  tc;
  pSTR  cnd;
} VIW1P;

BOOL LOCALF VIW1_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 絞り込みダイアログプロシージャ
  VIW1P *pa;
  POSI c;
  static TBCI tci = { 0, "lx, ic, cm, wk", NULL, NULL, TTF_ADJ, 3, 0 };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VIW1P *)lpa));
    SubclassWindow(GetDlgItem(hdlg, 101), VIW1_WndProc);
    ScanCNDTable(pa->tc, pa->cnd);
    SetTTBL(hdlg, 101, pa->tc, &tci);
    c.ir = 0; c.ic = 1;
    SendDlgItemMessage(hdlg, 101, TBCM_SETCUR, (uANY)&c, FALSE);
    PrintCNDTable(pa->cnd, pa->tc);
    SetSSTR(hdlg, 102, pa->cnd);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VIW1P *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case MKU4B(101, APPN_CHANGE):
      RedrawWindow(GetDlgItem(hdlg, 101), NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
      PrintCNDTable(pa->cnd, pa->tc);
      SetSSTR(hdlg, 102, pa->cnd);
      break;
    case IDPSH:
    case IDPSH+2:
    case IDOK:
      PrintCNDTable(pa->cnd, pa->tc);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

iANY LOCALF VIW2_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 並べ替え条件表のウィンドウプロシージャ
  switch (umsg) {
  case TBCM_ASKCELLFORMAT:
    if (((rPOSI)wpa)->ic < 0) {
      return (((rPOSI)wpa)->ir < 0)? DC_CHD|DC_RHD|DC_CEN: DC_INR|DC_RHD|DC_RGT;
    }
    break;
  case TBCM_GETCELLTEXT:
    if (((rPOSI)wpa)->ic < 0) {
      if (((rPOSI)wpa)->ir < 0) {
        sprintfs((pSTR)lpa, "優先順位");
      } else {
        sprintfs((pSTR)lpa, "%d ", ((rPOSI)wpa)->ir + 1);
      }
      return 0;
    }
    break;
  }
  return DefBOLTBLProc(hwnd, umsg, wpa, lpa);
}

  // 並べ替え条件設定情報
typedef struct {
  HTBL  ts;
  pSTR  srt;
} VIW2P;

BOOL LOCALF VIW2_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 並べ替えダイアログプロシージャ
  VIW2P *pa;
  static TBCI tci = { 0, NULL, NULL, NULL, TTF_ADJ|TTF_HDW, 1, 8 };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VIW2P *)lpa));
    SubclassWindow(GetDlgItem(hdlg, 101), VIW2_WndProc);
    ScanSRTTable(pa->ts, pa->srt);
    SetTTBL(hdlg, 101, pa->ts, &tci);
    PrintSRTTable(pa->srt, pa->ts);
    SetSSTR(hdlg, 102, pa->srt);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VIW2P *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case MKU4B(101, APPN_CHANGE):
      RedrawWindow(GetDlgItem(hdlg, 101), NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
      PrintSRTTable(pa->srt, pa->ts);
      SetSSTR(hdlg, 102, pa->srt);
      break;
    case IDPSH:
    case IDPSH+1:
    case IDOK:
      PrintSRTTable(pa->srt, pa->ts);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_arrange(HWND hwnd, I4B ip)
{ // 表示項目／絞り込み／並べ替え
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  HTBL tb;
  VIWI viw;
  VIWE dat;
  // 表示項目
  static VIW0P par0;
  static DLGI dit0[] = {
    { C_BGRP|wsG,   6,  0, 48, 18,  -1, "" },
    { C_SCEN|wsG,   8,  6, 44,  8,  -1, "表示項目" },
    { C_BPSH|wsG,  58,  3, 48, 14, IDPSH+1, "絞り込み" },
    { C_BPSH|wsG, 110,  3, 48, 14, IDPSH+2, "並べ替え" },
    { C_SLFT|wsG,   8, 30, 80,  8,  -1, "表示項目(列タイトル)" },
    { C_LSEL|wsT,   8, 40, 80,124, 101, "" },
    { C_SLFT|wsG, 152, 30, 80,  8,  -1, "非表示項目" },
    { C_LSEL|wsT, 152, 40, 80,124, 102, "" },
    { C_BPSH|wsGT, 96, 64, 48, 14, 103, "＜追加(&A)" },
    { C_BPSH|wsT,  96, 82, 48, 14, 104, "＞除外(&D)" },
    { C_SLFT|wsG,   8,169, 48,  8,  -1, "固定列数(&F):" },
    { C_ENUM|wsT,  56,167, 24, 12, 105, "" },
    { C_BDEF|wsGT,134,204, 48, 14, IDOK, "OK"   },
    { C_BPSH|wsT, 186,204, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg0 = { dit0, _countof(dit0), 0, 0, 240, 224, "表示形式" };
  // 絞り込み
  static VIW1P par1;
  static DLGI dit1[] = {
    { C_BPSH|wsG,   6,  3, 48, 14, IDPSH, "表示項目" },
    { C_BGRP|wsG,  58,  0, 48, 18,  -1, "" },
    { C_SCEN|wsG,  60,  6, 44,  8,  -1, "絞り込み" },
    { C_BPSH|wsG, 110,  3, 48, 14, IDPSH+2, "並べ替え" },
    { C_SLFT|wsG,   8, 30, 48,  8,  -1, "絞り込み条件" },
    { C_TTBX|wsGT,  8, 40,224,116, 101, "" },
    { C_BGRP|wsG,   6,156,228, 32,  -1, "絞り込み条件式" },
    { C_SMUL|wsG,  12,166,216, 18, 102, "" },
    { C_BDEF|wsGT,134,204, 48, 14, IDOK, "OK"   },
    { C_BPSH|wsT, 186,204, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg1 = { dit1, _countof(dit1), 0, 0, 240, 224, "表示形式" };
  // 並べ替え
  static VIW2P par2;
  static DLGI dit2[] = {
    { C_BPSH|wsG,   6,  3, 48, 14, IDPSH, "表示項目" },
    { C_BPSH|wsG,  58,  3, 48, 14, IDPSH+1, "絞り込み" },
    { C_BGRP|wsG, 110,  0, 48, 18,  -1, "" },
    { C_SCEN|wsG, 112,  6, 44,  8,  -1, "並べ替え" },
    { C_SLFT|wsG,   8, 30, 48,  8,  -1, "並べ替え条件" },
    { C_TTBF|wsGT,  8, 40,224,116, 101, "" },
    { C_BGRP|wsG,   6,156,228, 32,  -1, "並べ替え条件式" },
    { C_SMUL|wsG,  12,166,216, 18, 102, "" },
    { C_BDEF|wsGT,134,204, 48, 14, IDOK, "OK"   },
    { C_BPSH|wsT, 186,204, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg2 = { dit2, _countof(dit2), 0, 0, 240, 224, "表示形式" };
  // プロパティシート
  static PSHI psp[] = {
    { &dlg0, VIW0_DlgProc, (iANY)&par0, sizeof(par0) },
    { &dlg1, VIW1_DlgProc, (iANY)&par1, sizeof(par1) },
    { &dlg2, VIW2_DlgProc, (iANY)&par2, sizeof(par2) },
  };
  static PSHS psh = { psp, _countof(psp) };

  if (we->flg & TBCS_DCV) return;
  tb = OHTBL(we->op);
  dat = *(pVIWE)RowBufPtr(we->bv);
  par0.ta = CreateARRTable(0, tb); if (!par0.ta) return;
  par0.arr = dat.arr;
  par0.pf = &dat.fc;
  par1.tc = CreateCNDTable(VIWCAP, tb); if (!par1.tc) goto _30;
  par1.cnd = dat.cnd;
  par2.ts = CreateSRTTable(VIWCAP, tb); if (!par2.ts) goto _20;
  par2.srt = dat.srt;
  if (PropSheetInput(hwnd, &psh, ip) == IDCANCEL) goto _10;
  *(pVIWE)RowBufPtr(we->bv) = dat;
  SendMessage(hwnd, TBCM_CHANGEVIEW, (uANY)SetVIWInfo(&viw, we->bv), TRUE);
 _10: DeleteTable(par0.ta);
 _20: DeleteTable(par1.tc);
 _30: DeleteTable(par2.ts);
}

void LOCALF cmd_viewa(HWND hwnd, BOOL sw)
{ // 全項目表示／表示形式解除
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  VIWI viw;

  if (we->flg & TBCS_DCV) return;
  SetRowBufCellValue(we->bv, 3, I4BBox(0));
  SetRowBufCellValue(we->bv, 4, sw? "": "*");
  SetRowBufCellValue(we->bv, 5, "");
  if (sw) { SetRowBufCellValue(we->bv, 6, "");}
  SendMessage(hwnd, TBCM_CHANGEVIEW, (uANY)SetVIWInfo(&viw, we->bv), TRUE);
}

static CODI diHRH[] = {
  { TBCS_HRH, "表示しない" }, { 0, "行インデックス" }
};
static CODS dsHRH = { diHRH, _countof(diHRH) };

static CODI diHCH[] = {
  { TBCS_HCH, "表示しない" }, { TBCS_UCI, "列インデックス" }, { TBCS_UCN, "列名" }, { 0, "列タイトル" }
};
static CODS dsHCH = { diHCH, _countof(diHCH) };

  // 表示オプション情報
typedef struct {
  I1B   face[32];
  I4B   ptsz;
  I4B   tbcs;
} VOPP;

BOOL LOCALF setvopt_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 表示オプション設定ダイアログプロシージャ
  VOPP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (VOPP *)lpa));
    SetESTR(hdlg, 101, pa->face);
    SetEINT(hdlg, 102, pa->ptsz);
    SetCCOD(hdlg, 103, pa->tbcs & TBCS_HRH, &dsHRH);
    SetCCOD(hdlg, 104, pa->tbcs & (TBCS_HCH|TBCS_UCI|TBCS_UCN), &dsHCH);
    SetBFLG(hdlg, 105, pa->tbcs & TBCS_EMD);
    SetBFLG(hdlg, 106, pa->tbcs & TBCS_DDD);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (VOPP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetESTR(hdlg, 101, pa->face, sizeof(pa->face) - 1);
      if (pa->face[0] == '\0') { strcpyx(pa->face, DEFFACE, sizeof(pa->face) - 1);}
      pa->ptsz = GetEINT(hdlg, 102); if (pa->ptsz < 6 || pa->ptsz > 30) { pa->ptsz = DEFPTSZ;}
      pa->tbcs = (pa->tbcs &~TBCS_HRH) | GetCCOD(hdlg, 103, &dsHRH);
      pa->tbcs = (pa->tbcs &~(TBCS_HCH|TBCS_UCI|TBCS_UCN)) | GetCCOD(hdlg, 104, &dsHCH);
      if (GetBFLG(hdlg, 105)) { pa->tbcs |= TBCS_EMD;} else { pa->tbcs &=~TBCS_EMD;}
      if (GetBFLG(hdlg, 106)) { pa->tbcs |= TBCS_DDD;} else { pa->tbcs &=~TBCS_DDD;}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_setvopt(HWND hwnd)
{ // 表示オプション
  VOPP par;
  HFNT hfnt;
  LOGFONT lof;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 48,  8,  -1, "フォント(&F):" },
    { C_ESTR|wsT,  56,  8, 66, 12, 101, "" },
    { C_ENUM|wsT, 128,  8, 24, 12, 102, "" },
    { C_SLFT|wsG, 155, 10, 16,  8,  -1, "pt" },
    { C_SLFT|wsG,   8, 26, 48,  8,  -1, "行見出し(&R):" },
    { C_CSEL|wsT,  56, 24, 58,128, 103, "" },
    { C_SLFT|wsG,   8, 42, 48,  8,  -1, "列見出し(&C):" },
    { C_CSEL|wsT,  56, 40, 58,128, 104, "" },
    { C_BFLG|wsGT,  8, 60,120, 10, 105, "Enterキーで下に移動する(&D)" },
    { C_BFLG|wsGT,  8, 74,128, 10, 106, "ドロップダウンリストを使用しない(&L)" },
    { C_BDEF|wsGT, 86,124, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 138,124, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 192, 144, "表示オプション" };

  hfnt = (HFNT)SendMessage(hwnd, WM_GETFONT, 0, 0);
  GetObject(hfnt, sizeof(LOGFONT), &lof);
  strcpyn(par.face, lof.lfFaceName, sizeof(par.face) - 1);
  par.ptsz = iround(abs(lof.lfHeight) * PTPI / DEFDPI);
  par.tbcs = SendMessage(hwnd, TBCM_GETMODE, 0, 0);
  if (DlgBoxInput(hwnd, &dlg, setvopt_DlgProc, (iANY)&par) == IDCANCEL) return;
  SendMessage(hwnd, TBCM_SETMODE, par.tbcs, FALSE);
  hfnt = CreateFontIndirect(SetLOGFONT(&lof, par.face, PT2DOTS(par.ptsz), 0));
  SendMessage(hwnd, WM_SETFONT, (uANY)hfnt, TRUE);
  DeleteObject(hfnt);
}

  // 集計表作成情報
typedef struct {
  HTBL  tg;
  I1B   grp[512];
} SUMP;

BOOL LOCALF SUM_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 集計表作成ダイアログプロシージャ
  SUMP *pa;
  static TBCI tci = { 0, "ic, sw, tit, fmt", NULL, NULL, TTF_ADJ, 3, 0 };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (SUMP *)lpa));
    ScanGRPTable(pa->tg, pa->grp);
    SetTTBL(hdlg, 101, pa->tg, &tci);
    PrintGRPTable(pa->grp, pa->tg);
    SetSSTR(hdlg, 102, pa->grp);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (SUMP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case MKU4B(101, APPN_CHANGE):
      RedrawWindow(GetDlgItem(hdlg, 101), NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
      PrintGRPTable(pa->grp, pa->tg);
      SetSSTR(hdlg, 102, pa->grp);
      break;
    case IDOK:
      PrintGRPTable(pa->grp, pa->tg);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_summary(HWND hwnd)
{ // 集計
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  HWND hsum;
  HVIW vw;
  static TBWI tbw = { NULL, TBCS_DED|TBCS_DSE, NULL, NULL, 0 };
  static SUMP par;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8, 48,  8,  -1, "集計項目" },
    { C_TTBX|wsGT,  8, 18,272,116, 101, "" },
    { C_BGRP|wsG,   6,134,276, 32,  -1, "集計項目リスト" },
    { C_SMUL|wsG,  12,144,256, 18, 102, "" },
    { C_BDEF|wsGT,182,188, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 234,188, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 288, 208, "集計表作成" };

  if (WindowID(hwnd) == IDSUM) {
    PostMessage(hFRM(hwnd), WM_COMMAND, IDM_SUMMARY, 0);
    SendMessage(hwnd, WM_CLOSE, 0, 0); return;
  }
  vw = (HVIW)SendMessage(hwnd, TBCM_GETVIEW, 0, 0);
  if (!we->tg) {
    we->tg = CreateGRPTable(VIWCAP, ViewHTBL(vw)); if (!we->tg) return;
    par.tg = we->tg;
    par.grp[0] = '\0';
  } else {
    par.tg = we->tg;
    PrintGRPTable(par.grp, par.tg);
  }
  if (DlgBoxInput(hwnd, &dlg, SUM_DlgProc, (iANY)&par) == IDCANCEL) return;
  if (IsWindow(hsum = GetDlgItem(hFRM(hwnd), IDSUM))) { SendMessage(hFRM(hwnd), FRMM_DESTROYCHILD, (uANY)hsum, 0);}
  if (we->tsm) { DeleteTable(we->tsm); we->tsm = NULL;}
  we->tsm = CreateSummary(vw, par.grp); if (!we->tsm) return;
  tbw.op = CreateHOPN(we->tsm, FALSE); if (!tbw.op) return;
  we->hsum = CreateTableWindow(hFRM(hwnd), IDSUM, &tbw);
}

void LOCALF cmd_check(HWND hwnd)
{ // チェック
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B re;

  if (we->flg & TBCS_DED) return;
  BusyMsg(hFRM(hwnd), "処理中...");
  reset_error();
  re = CheckTable(OHTBL(we->op));
  EndBusy(hFRM(hwnd));
  OkBox(hFRM(hwnd), re? "エラーは見つかりませんでした。": "エラーが見つかりました。", NULL);
}

void LOCALF cmd_edit(HWND hwnd)
{ // 行編集
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  HBUF rb;

  if (we->flg & TBCS_DER) {
    SendMessage(hwnd, TBCM_MOVECUR, MVC_HOM, TRUE);
    SendMessage(hwnd, TBCM_EDITCELL, 0, 0); return;
  }
  rb = CreateRowBuf(OHTBL(we->op)); if (!rb) return;
  SendMessage(hwnd, TBCM_GETCURROW, (uANY)rb, 0);
  SendMessage(hwnd, TBCM_MOVECUR, MVC_SEL, TRUE);
  if (EditRowDlgBox(hwnd, rb, WindowText(hwnd))) {
    SendMessage(hwnd, TBCM_SETCURROW, (uANY)rb, 0);
  } else {
    SendMessage(hwnd, TBCM_SETSEL, FALSE, TRUE);
  }
  DeleteRowBuf(rb);
}

void LOCALF cmd_addedit(HWND hwnd)
{ // 行追加して編集
  SendMessage(hwnd, TBCM_MOVECUR, MVC_BTM, TRUE);
  SendMessage(hwnd, WM_COMMAND, IDM_EDIT, 0);
}

void LOCALF cmd_insertedit(HWND hwnd)
{ // 行挿入して編集
  if (!SendMessage(hwnd, TBCM_GETSEL, 0, 0)) {
    SendMessage(hwnd, TBCM_MOVECUR, MVC_SEL, TRUE);
  }
  SendMessage(hwnd, TBCM_INSERT, 0, 0);
  SendMessage(hwnd, WM_COMMAND, IDM_EDIT, 0);
}

void LOCALF cmd_seldelete(HWND hwnd)
{ // 行削除
  if (SendMessage(hwnd, TBCM_GETSEL, 0, 0)) {
    SendMessage(hwnd, TBCM_DELETE, 0, 0); return;
  }
  SendMessage(hwnd, TBCM_MOVECUR, MVC_SEL, TRUE);
  if (YesNoBox(hFRM(hwnd), "この行を削除しますか？", NULL) == IDYES) {
    SendMessage(hwnd, TBCM_DELETE, 0, 0);
  } else {
    SendMessage(hwnd, TBCM_SETSEL, FALSE, TRUE);
  }
}

void LOCALF cmd_psort(HWND hwnd)
{ // 物理的に並べ替え
  HVIW vw;

  if (YesNoBox(hFRM(hwnd), "現在の表示順でデータを物理的に並べ替えます。よろしいですか？", NULL) != IDYES) return;
  vw = (HVIW)SendMessage(hwnd, TBCM_GETVIEW, 0, 0);
  BusyMsg(hFRM(hwnd), "処理中...");
  SortTableRowsByView(vw);
  SendMessage(hwnd, TBCM_UPDATE, FALSE, TRUE);
  EndBusy(hFRM(hwnd));
}

iANY LOCALF TBL_command(HWND hwnd, uANY wpa, iANY lpa)
{ // コマンド
  switch (LOU2B(wpa)) {
  case IDM_SAVE:
    cmd_save(hwnd); break;
  case IDM_IMPORT:
    cmd_import(hwnd); break;
  case IDM_EXPORT:
    cmd_export(hwnd); break;
  case IDM_PRINT:
    cmd_printtbl(hwnd); break;
  case IDM_PRINTSLP:
    cmd_printslp(hwnd); break;
  case IDM_CUT:
    SendMessage(hwnd, TBCM_CUT, 0, 0); break;
  case IDM_COPY:
    SendMessage(hwnd, TBCM_COPY, 0, 0); break;
  case IDM_PASTE:
    SendMessage(hwnd, TBCM_PASTE, 0, 0); break;
  case IDM_CLEAR:
    SendMessage(hwnd, TBCM_CLEAR, 0, 0); break;
  case IDM_INSERT:
    SendMessage(hwnd, TBCM_INSERT, 0, 0); break;
  case IDM_DELETE:
    SendMessage(hwnd, TBCM_DELETE, 0, 0); break;
  case IDM_OPENLINK:
    SendMessage(hwnd, TBCM_OPENLINK, 0, 0); break;
  case IDM_SEARCH:
    cmd_search(hwnd, 0); break;
  case IDM_NSEARCH:
    cmd_search(hwnd, 1); break;
  case IDM_VIEW:
    cmd_view(hwnd); break;
  case IDM_ARRANGE:
    cmd_arrange(hwnd, 0); break;
  case IDM_FILTER:
    cmd_arrange(hwnd, 1); break;
  case IDM_SORT:
    cmd_arrange(hwnd, 2); break;
  case IDM_VIEWA:
    cmd_viewa(hwnd, 0); break;
  case IDM_VIEWB:
    cmd_viewa(hwnd, 1); break;
  case IDM_SETVOPT:
    cmd_setvopt(hwnd); break;
  case IDM_SUMMARY:
    cmd_summary(hwnd); break;
  case IDM_CHECK:
    cmd_check(hwnd); break;
  case IDM_EDIT:
    cmd_edit(hwnd); break;
  case IDM_ADDEDIT:
    cmd_addedit(hwnd); break;
  case IDM_INSERTEDIT:
    cmd_insertedit(hwnd); break;
  case IDM_SELDELETE:
    cmd_seldelete(hwnd); break;
  case IDM_PSORT:
    cmd_psort(hwnd); break;
  }
  return 0;
}

iANY LOCALF TBL_close(HWND hwnd)
{ // 表ウィンドウを閉じる
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));
  I4B sv, re;

  sv = !(SendMessage(hwnd, TBCM_GETMODE, 0, 0) & TBCS_DED) && IsModified(we->op);
  if (sv) {
    re = YesNoCanBox(hFRM(hwnd), format("'%s'は変更されています。保存しますか？", WindowText(hwnd)), NULL);
    switch (re) {
    case IDYES: sv = TRUE;  break;
    case IDNO:  sv = FALSE; break;
    default: return 0;
    }
  }
  if (sv) {
    BusyMsg(hFRM(hwnd), "処理中...");
    reset_error();
    re = CheckTable(OHTBL(we->op));
    EndBusy(hFRM(hwnd));
    if (!re) {
      ErrorBox(hFRM(hwnd), "エラーが見つかりました。\n保存はキャンセルされます。", NULL);
      return 0;
    }
  }
  BusyMsg(hFRM(hwnd), sv? "保存中...": "");
  reset_error();
  re = CloseTable(we->op, sv);
  EndBusy(hFRM(hwnd));
  if (sv && !re) {
    ErrorBox(hFRM(hwnd), format("'%s'の保存に失敗しました。", TableFileName(OHTBL(we->op))), NULL);
  }
  return DefBOLTBLProc(hwnd, WM_CLOSE, 0, 0);
}

iANY LOCALF TBL_destroy(HWND hwnd)
{ // 表ウィンドウ終了処理
  pTBWE we = (pTBWE)GetWindowLong(hwnd, sizeof(iANY));

  if (IsWindow(we->hprn)) { SendMessage(hFRM(hwnd), FRMM_DESTROYCHILD, (uANY)we->hprn, 0);}
  if (IsWindow(we->hsum)) { SendMessage(hFRM(hwnd), FRMM_DESTROYCHILD, (uANY)we->hsum, 0);}
  if (!(we->flg & TBCS_DCV)) {
    SetLastVIW(we->tv, we->bv);
    CopyUserVIWTable(we->tvu, we->tv);
    SaveUserVIW(we->tvu);
    DeleteRowBuf(we->bv);
    DeleteTable(we->tv);
    DeleteTable(we->tvu);
    DeleteTable(we->tvs);
  }
  DeleteTable(we->tg);
  DeleteTable(we->tsm);
  hfree(we);
  return DefBOLTBLProc(hwnd, WM_DESTROY, 0, 0);
}

iANY LOCALF TBL_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // ウィンドウプロシージャ
  switch (umsg) {
  case TBCM_SETTABLE:
    return TBL_settable(hwnd, (pTBWI)wpa);
  case TBCM_TRACKPOPUP:
    return TBL_trackpopup(hwnd, (rPOSI)wpa);
  case WM_COMMAND:
    return TBL_command(hwnd, wpa, lpa);
  case WM_CLOSE:
    return TBL_close(hwnd);
  case WM_DESTROY:
    return TBL_destroy(hwnd);
  }
  return DefBOLTBLProc(hwnd, umsg, wpa, lpa);
}

I4B  LOCALF TBL_appstatus(HWND hwnd)
{ // 表ウィンドウの状態の取得
  I4B fmt, sta = 0;
  POSI c;
  STRBUF bf;

  SendMessage(hwnd, TBCM_GETCUR, (uANY)&c, 0);
  fmt = SendMessage(hwnd, TBCM_GETCELLFORMAT, (uANY)&c, 0);
  if (fmt & DC_LNK) {
    SendMessage(hwnd, TBCM_GETCELLTEXT, (uANY)&c, (iANY)bf);
    if (bf[0] != '\0') { sta |= APPS_LNK;}
  }
  return sta;
}

HWND LOCALF CreateTableWindowX(HWND hwnd, I4B id, pTBWI wi, WNDPROC prc)
{ // 表ウィンドウの作成
  static CREI cri = { "BOLTBL", wsCHV, };

  cri.tit = wi->tit? wi->tit: TableTitle(OHTBL(wi->op));
  cri.id = id? id: SendMessage(hwnd, FRMM_GETNEWID, IDPRN + 1, 0);
  cri.pa = (U4B)wi;
  return (HWND)SendMessage(hwnd, FRMM_CREATECHILD, (uANY)&cri, (iANY)prc);
}

HWND LOCALF CreateTableWindow(HWND hwnd, I4B id, pTBWI wi)
{ // 表ウィンドウの作成
  return CreateTableWindowX(hwnd, id, wi, TBL_WndProc);
}

//――――――――――――――――――――――――――――――――――――――//

void LOCALF fi_CreateDIB(pBIN sp)
{ // CreateDIB
  *(pP4B)(sp + 8) = CreateDIB(*(rI4B)sp, *(rI4B)(sp + 4), *(rI4B)(sp + 8));
}

void LOCALF fi_DIB_WID(pBIN sp)
{ // DIB_WID
  *(pI4B)sp = DIB_WID(*(pP4B)sp);
}

void LOCALF fi_DIB_HEI(pBIN sp)
{ // DIB_HEI
  *(pI4B)sp = DIB_HEI(*(pP4B)sp);
}

void LOCALF fi_DIB_BTS(pBIN sp)
{ // DIB_BTS
  *(pI4B)sp = DIB_BTS(*(pP4B)sp);
}

void LOCALF fi_DIB_IMG(pBIN sp)
{ // DIB_IMG
  *(pP4B)sp = DIB_IMG(*(pP4B)sp);
}

void LOCALF fi_CreateCompatibleDIB(pBIN sp)
{ // CreateCompatibleDIB
  *(pP4B)sp = CreateCompatibleDIB(*(rP4B)sp);
}

void LOCALF fi_DuplicateDIB(pBIN sp)
{ // DuplicateDIB
  *(pP4B)sp = DuplicateDIB(*(rP4B)sp);
}

void LOCALF fi_DeleteDIB(pBIN sp)
{ // DeleteDIB
  DeleteDIB(*(rP4B)sp);
}

void LOCALF fi_MoveDIB(pBIN sp)
{ // MoveDIB
  *(pP4B)(sp + 4) = MoveDIB(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_GetDIBSize(pBIN sp)
{ // GetDIBSize
  *(pP4B)(sp + 4) = GetDIBSize(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_LoadDIB(pBIN sp)
{ // LoadDIB
  *(pP4B)(sp + 4) = LoadDIB(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_SaveDIB(pBIN sp)
{ // SaveDIB
  *(pI4B)(sp + 4) = SaveDIB(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_ConvertDIB(pBIN sp)
{ // ConvertDIB
  *(pI4B)(sp + 4) = ConvertDIB(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_LoadBMP(pBIN sp)
{ // LoadBMP
  *(pP4B)(sp + 4) = LoadBMP(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_SaveBMP(pBIN sp)
{ // SaveBMP
  *(pI4B)(sp + 4) = SaveBMP(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_PasteDIB(pBIN sp)
{ // PasteDIB
  *(pI4B)(sp +12) = PasteDIB(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_TrimDIB(pBIN sp)
{ // TrimDIB
  *(pI4B)(sp +20) =
    TrimDIB(*(rP4B)sp, *(rI4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12), *(rI4B)(sp +16), *(rU4B)(sp +20));
}

void LOCALF fi_TransformDIB(pBIN sp)
{ // TransformDIB
  *(pI4B)(sp + 8) = TransformDIB(*(rP4B)sp, *(rP4B)(sp + 4), *(rU4B)(sp + 8));
}

void LOCALF fi_InvertDIB(pBIN sp)
{ // InvertDIB
  *(pI4B)(sp + 4) = InvertDIB(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_RotateDIB(pBIN sp)
{ // RotateDIB
  *(pI4B)(sp +12) = RotateDIB(*(rP4B)sp, *(rF8B)(sp + 4), *(rU4B)(sp +12));
}

void LOCALF fi_ResizeDIBX(pBIN sp)
{ // ResizeDIBX
  *(pI4B)(sp +12) = ResizeDIBX(*(rP4B)sp, *(rI4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_ResizeDIB(pBIN sp)
{ // ResizeDIB
  *(pI4B)(sp + 8) = ResizeDIB(*(rP4B)sp, *(rI4B)(sp + 4), *(rI4B)(sp + 8));
}

void LOCALF fi_SetOrigin(pBIN sp)
{ // SetOrigin
  SetOrigin(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_OriginX(pBIN sp)
{ // OriginX
  *(pF8B)(sp - 4) = OriginX(*(rP4B)sp);
}

void LOCALF fi_OriginY(pBIN sp)
{ // OriginY
  *(pF8B)(sp - 4) = OriginY(*(rP4B)sp);
}

void LOCALF fi_SetScale(pBIN sp)
{ // SetScale
  SetScale(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_ScaleX(pBIN sp)
{ // ScaleX
  *(pF8B)(sp - 4) = ScaleX(*(rP4B)sp);
}

void LOCALF fi_ScaleY(pBIN sp)
{ // ScaleY
  *(pF8B)(sp - 4) = ScaleY(*(rP4B)sp);
}

void LOCALF fi_SetCell(pBIN sp)
{ // SetCell
  *(pP4B)(sp +32) = SetCell(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28));
}

void LOCALF fi_MoveCell(pBIN sp)
{ // MoveCell
  *(pP4B)(sp +16) = MoveCell(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_ResizeCell(pBIN sp)
{ // ResizeCell
  *(pP4B)(sp +16) = ResizeCell(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_ReshapeCell(pBIN sp)
{ // ReshapeCell
  *(pP4B)(sp +32) = ReshapeCell(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28));
}

void LOCALF fi_SetCellMargin(pBIN sp)
{ // SetCellMargin
  SetCellMargin(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_CellMarginH(pBIN sp)
{ // CellMarginH
  *(pF8B)(sp - 4) = CellMarginH(*(rP4B)sp);
}

void LOCALF fi_CellMarginV(pBIN sp)
{ // CellMarginV
  *(pF8B)(sp - 4) = CellMarginV(*(rP4B)sp);
}

void LOCALF fi_SetLineStyle(pBIN sp)
{ // SetLineStyle
  *(pI4B)(sp + 4) = SetLineStyle(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_SetLineColor(pBIN sp)
{ // SetLineColor
  *(pI4B)(sp + 4) = SetLineColor(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_SetTextFont(pBIN sp)
{ // SetTextFont
  SetTextFont(*(rP4B)sp, *(rP4B)(sp + 4), *(rF8B)(sp + 8), *(rI4B)(sp +16), *(rI4B)(sp +20));
}

void LOCALF fi_SetTextStyle(pBIN sp)
{ // SetTextStyle
  SetTextStyle(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rP4B)(sp +28));
}

void LOCALF fi_TextSize(pBIN sp)
{ // TextSize
  *(pP4B)(sp +12) = TextSize(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_AveCharSize(pBIN sp)
{ // AveCharSize
  *(pP4B)(sp + 4) = AveCharSize(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_ZenCharSize(pBIN sp)
{ // ZenCharSize
  *(pP4B)(sp + 4) = ZenCharSize(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_DrawLine(pBIN sp)
{ // DrawLine
  DrawLine(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28));
}

void LOCALF fi_DrawCirc(pBIN sp)
{ // DrawCirc
  DrawCirc(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28), *(rF8B)(sp +36));
}

void LOCALF fi_RST(pBIN sp)
{ // RST
  *(pI4B)(sp +12) = RST(*(rI4B)sp, *(rI4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_DrawCell(pBIN sp)
{ // DrawCell
  DrawCell(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8));
}

void LOCALF fi_FillCell(pBIN sp)
{ // FillCell
  FillCell(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_FillPoly(pBIN sp)
{ // FillPoly
  FillPoly(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_FillCirc(pBIN sp)
{ // FillCirc
  FillCirc(*(rP4B)sp, *(rF8B)(sp + 4),
                      *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28), *(rF8B)(sp +36), *(rI4B)(sp +44));
}

void LOCALF fi_CellText(pBIN sp)
{ // CellText
  CellText(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_VCellText(pBIN sp)
{ // VCellText
  VCellText(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_SetGrid0(pBIN sp)
{ // SetGrid0
  SetGrid0(*(rP4B)sp, *(rF8B)(sp + 4),
                      *(rF8B)(sp +12), *(rI4B)(sp +20), *(rI4B)(sp +24), *(rF8B)(sp +28), *(rF8B)(sp +36));
}

void LOCALF fi_SetGrid1(pBIN sp)
{ // SetGrid1
  SetGrid1(*(rP4B)sp, *(rF8B)(sp + 4),
                      *(rF8B)(sp +12), *(rI4B)(sp +20), *(rI4B)(sp +24), *(rP4B)(sp +28), *(rF8B)(sp +32));
}

void LOCALF fi_SetGrid2(pBIN sp)
{ // SetGrid2
  SetGrid2(*(rP4B)sp, *(rF8B)(sp + 4),
                      *(rF8B)(sp +12), *(rI4B)(sp +20), *(rI4B)(sp +24), *(rF8B)(sp +28), *(rP4B)(sp +36));
}

void LOCALF fi_SetGrid3(pBIN sp)
{ // SetGrid3
  SetGrid3(*(rP4B)sp, *(rF8B)(sp + 4),
                      *(rF8B)(sp +12), *(rI4B)(sp +20), *(rI4B)(sp +24), *(rP4B)(sp +28), *(rP4B)(sp +32));
}

void LOCALF fi_GridCell(pBIN sp)
{ // GridCell
  *(pP4B)(sp +12) = GridCell(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_DrawGridCell(pBIN sp)
{ // DrawGridCell
  DrawGridCell(*(rP4B)sp, *(rP4B)(sp + 4), *(rI4B)(sp + 8), *(rI4B)(sp +12), *(rI4B)(sp +16));
}

void LOCALF fi_GridCellText(pBIN sp)
{ // GridCellText
  GridCellText(*(rP4B)sp, *(rP4B)(sp + 4),
                          *(rI4B)(sp + 8), *(rI4B)(sp +12), *(rI4B)(sp +16), *(rP4B)(sp +20), *(rI4B)(sp +24));
}

void LOCALF fi_SetStamp0(pBIN sp)
{ // SetStamp0
  SetStamp0(*(rP4B)sp, *(rF8B)(sp + 4), *(rP4B)(sp +12));
}

void LOCALF fi_SetStamp1(pBIN sp)
{ // SetStamp1
  SetStamp1(*(rP4B)sp, *(rF8B)(sp + 4), *(rP4B)(sp +12));
}

void LOCALF fi_SetStamp2(pBIN sp)
{ // SetStamp2
  SetStamp2(*(rP4B)sp, *(rF8B)(sp + 4), *(rP4B)(sp +12), *(rP4B)(sp +16));
}

void LOCALF fi_SetStamp3(pBIN sp)
{ // SetStamp3
  SetStamp3(*(rP4B)sp, *(rF8B)(sp + 4), *(rP4B)(sp +12), *(rP4B)(sp +16), *(rP4B)(sp +20));
}

void LOCALF fi_CellStamp(pBIN sp)
{ // CellStamp
  CellStamp(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_CellImage(pBIN sp)
{ // CellImage
  CellImage(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +12));
}

void LOCALF fi_OkBox(pBIN sp)
{ // OkBox
  *(pI4B)(sp + 8) = OkBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_OkCanBox(pBIN sp)
{ // OkCanBox
  *(pI4B)(sp + 8) = OkCanBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_YesNoBox(pBIN sp)
{ // YesNoBox
  *(pI4B)(sp + 8) = YesNoBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_YesNoCanBox(pBIN sp)
{ // YesNoCanBox
  *(pI4B)(sp + 8) = YesNoCanBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_ErrorBox(pBIN sp)
{ // ErrorBox
  *(pI4B)(sp + 8) = ErrorBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_WarningBox(pBIN sp)
{ // WarningBox
  *(pI4B)(sp + 8) = WarningBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_AlertBox(pBIN sp)
{ // AlertBox
  *(pI4B)(sp + 8) = AlertBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_ResultBox(pBIN sp)
{ // ResultBox
  *(pI4B)(sp +16) = ResultBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +16));
}

void LOCALF fi_hWND(pBIN sp)
{ // hWND
  *(pP4B)sp = hWND(*(rP4B)sp);
}

void LOCALF fi_SetReportInfo(pBIN sp)
{ // SetReportInfo
  SetReportInfo(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8), *(rI4B)(sp +12), *(rI4B)(sp +16));
}

void LOCALF fi_ReportTitle(pBIN sp)
{ // ReportTitle
  *(pP4B)sp = (P4B)ReportTitle(*(rP4B)sp);
}

void LOCALF fi_ReportAuthor(pBIN sp)
{ // ReportAuthor
  *(pP4B)sp = (P4B)ReportAuthor(*(rP4B)sp);
}

void LOCALF fi_ReportDate(pBIN sp)
{ // ReportDate
  *(pI4B)sp = ReportDate(*(rP4B)sp);
}

void LOCALF fi_ReportTime(pBIN sp)
{ // ReportTime
  *(pI4B)sp = ReportTime(*(rP4B)sp);
}

void LOCALF fi_SetReportExtra(pBIN sp)
{ // SetReportExtra
  SetReportExtra(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_ReportExtra(pBIN sp)
{ // ReportExtra
  *(pI4B)sp = ReportExtra(*(rP4B)sp);
}

void LOCALF fi_SetNPages(pBIN sp)
{ // SetNPages
  SetNPages(*(rP4B)sp, *(rI4B)(sp + 4));
}

void LOCALF fi_NPages(pBIN sp)
{ // NPages
  *(pI4B)sp = NPages(*(rP4B)sp);
}

void LOCALF fi_SetPaperSize(pBIN sp)
{ // SetPaperSize
  SetPaperSize(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20));
}

void LOCALF fi_PaperWidth(pBIN sp)
{ // PaperWidth
  *(pF8B)(sp - 4) = PaperWidth(*(rP4B)sp);
}

void LOCALF fi_PaperHeight(pBIN sp)
{ // PaperHeight
  *(pF8B)(sp - 4) = PaperHeight(*(rP4B)sp);
}

void LOCALF fi_SetPageSize(pBIN sp)
{ // SetPageSize
  SetPageSize(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12));
}

void LOCALF fi_PageWidth(pBIN sp)
{ // PageWidth
  *(pF8B)(sp - 4) = PageWidth(*(rP4B)sp);
}

void LOCALF fi_PageHeight(pBIN sp)
{ // PageHeight
  *(pF8B)(sp - 4) = PageHeight(*(rP4B)sp);
}

void LOCALF fi_PageLeft(pBIN sp)
{ // PageLeft
  *(pF8B)(sp - 4) = PageLeft(*(rP4B)sp);
}

void LOCALF fi_PageTop(pBIN sp)
{ // PageTop
  *(pF8B)(sp - 4) = PageTop(*(rP4B)sp);
}

void LOCALF fi_PageRight(pBIN sp)
{ // PageRight
  *(pF8B)(sp - 4) = PageRight(*(rP4B)sp);
}

void LOCALF fi_PageBottom(pBIN sp)
{ // PageBottom
  *(pF8B)(sp - 4) = PageBottom(*(rP4B)sp);
}

void LOCALF fi_SetPageMargin(pBIN sp)
{ // SetPageMargin
  SetPageMargin(*(rP4B)sp, *(rF8B)(sp + 4), *(rF8B)(sp +12), *(rF8B)(sp +20), *(rF8B)(sp +28));
}

void LOCALF fi_BodyWidth(pBIN sp)
{ // BodyWidth
  *(pF8B)(sp - 4) = BodyWidth(*(rP4B)sp);
}

void LOCALF fi_BodyHeight(pBIN sp)
{ // BodyHeight
  *(pF8B)(sp - 4) = BodyHeight(*(rP4B)sp);
}

void LOCALF fi_BodyLeft(pBIN sp)
{ // BodyLeft
  *(pF8B)(sp - 4) = BodyLeft(*(rP4B)sp);
}

void LOCALF fi_BodyTop(pBIN sp)
{ // BodyTop
  *(pF8B)(sp - 4) = BodyTop(*(rP4B)sp);
}

void LOCALF fi_BodyRight(pBIN sp)
{ // BodyRight
  *(pF8B)(sp - 4) = BodyRight(*(rP4B)sp);
}

void LOCALF fi_BodyBottom(pBIN sp)
{ // BodyBottom
  *(pF8B)(sp - 4) = BodyBottom(*(rP4B)sp);
}

void LOCALF fi_SetHeaderHeight(pBIN sp)
{ // SetHeaderHeight
  SetHeaderHeight(*(rP4B)sp, *(rF8B)(sp + 4));
}

void LOCALF fi_SetFooterHeight(pBIN sp)
{ // SetFooterHeight
  SetFooterHeight(*(rP4B)sp, *(rF8B)(sp + 4));
}

void LOCALF fi_HeaderHeight(pBIN sp)
{ // HeaderHeight
  *(pF8B)(sp - 4) = HeaderHeight(*(rP4B)sp);
}

void LOCALF fi_HeaderTop(pBIN sp)
{ // HeaderTop
  *(pF8B)(sp - 4) = HeaderTop(*(rP4B)sp);
}

void LOCALF fi_FooterHeight(pBIN sp)
{ // FooterHeight
  *(pF8B)(sp - 4) = FooterHeight(*(rP4B)sp);
}

void LOCALF fi_FooterBottom(pBIN sp)
{ // FooterBottom
  *(pF8B)(sp - 4) = FooterBottom(*(rP4B)sp);
}

void LOCALF fi_SetReqBodyWidth(pBIN sp)
{ // SetReqBodyWidth
  SetReqBodyWidth(*(rP4B)sp, *(rF8B)(sp + 4), *(rI4B)(sp +12));
}

void LOCALF fi_ReqBodyWidth(pBIN sp)
{ // ReqBodyWidth
  *(pF8B)(sp - 4) = ReqBodyWidth(*(rP4B)sp);
}

void LOCALF fi_PageCell(pBIN sp)
{ // PageCell
  *(pP4B)(sp + 4) = PageCell(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_BodyCell(pBIN sp)
{ // BodyCell
  *(pP4B)(sp + 4) = BodyCell(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_HeaderCell(pBIN sp)
{ // HeaderCell
  *(pP4B)(sp + 4) = HeaderCell(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_FooterCell(pBIN sp)
{ // FooterCell
  *(pP4B)(sp + 4) = FooterCell(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_EditRowDlgBox(pBIN sp)
{ // EditRowDlgBox
  *(pI4B)(sp + 8) = EditRowDlgBox(*(rP4B)sp, *(rP4B)(sp + 4), *(rP4B)(sp + 8));
}

void LOCALF fi_LoadIMG(pBIN sp)
{ // LoadIMG
  *(HIMG *)(sp + 4) = LoadIMG(*(HIMG *)sp, *(rSTR *)(sp + 4));
}

void LOCALF fi_SaveIMG(pBIN sp)
{ // SaveIMG
  *(BOOL *)(sp + 4) = SaveIMG(*(HIMG *)sp, *(rSTR *)(sp + 4));
}

void LOCALF fi_LoadJPG(pBIN sp)
{ // LoadJPG
  *(HDIB *)(sp + 4) = LoadJPG(*(HDIB *)sp, *(rSTR *)(sp + 4));
}

void LOCALF fi_SaveJPG(pBIN sp)
{ // SaveJPG
  *(BOOL *)(sp + 4) = SaveJPG(*(HDIB *)sp, *(rSTR *)(sp + 4));
}

void LOCALF fi_StatMsg(pBIN sp)
{ // StatMsg
  StatMsg(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_BusyMsg(pBIN sp)
{ // BusyMsg
  BusyMsg(*(rP4B)sp, *(rP4B)(sp + 4));
}

void LOCALF fi_EndBusy(pBIN sp)
{ // EndBusy
  EndBusy(*(rP4B)sp);
}

static BFNC fiBOL[] = {
  fi_CreateDIB, // 540
  fi_DIB_WID, // DIB_WIDTH
  fi_DIB_HEI, // DIB_HEIGHT
  fi_DIB_BTS, // DIB_BITS
  fi_DIB_IMG, // DIB_IMAGE
  fi_DIB_WID,
  fi_DIB_HEI,
  fi_DIB_BTS,
  fi_DIB_IMG,
  fi_CreateCompatibleDIB,
  fi_DuplicateDIB,
  fi_DeleteDIB,
  fi_MoveDIB,
  fi_GetDIBSize,
  fi_LoadDIB,
  fi_SaveDIB,
  fi_ConvertDIB,
  fi_LoadBMP,
  fi_SaveBMP,
  fi_PasteDIB,
  fi_TrimDIB,
  fi_TransformDIB,
  fi_InvertDIB,
  fi_RotateDIB,
  fi_ResizeDIBX,
  fi_ResizeDIB,

  fi_SetOrigin,
  fi_OriginX,
  fi_OriginY,
  fi_SetScale,
  fi_ScaleX,
  fi_ScaleY,
  fi_SetCell,
  fi_MoveCell,
  fi_ResizeCell,
  fi_ReshapeCell,
  fi_SetCellMargin,
  fi_CellMarginH,
  fi_CellMarginV,
  fi_SetLineStyle,
  fi_SetLineColor,
  fi_SetTextFont,
  fi_SetTextStyle,
  fi_TextSize,
  fi_AveCharSize,
  fi_ZenCharSize,
  fi_DrawLine,
  fi_DrawCirc,
  fi_RST,
  fi_DrawCell,
  fi_FillCell,
  fi_FillPoly,
  fi_FillCirc,
  fi_CellText,
  fi_VCellText,
  fi_SetGrid0,
  fi_SetGrid1,
  fi_SetGrid2,
  fi_SetGrid3,
  fi_GridCell,
  fi_DrawGridCell, // 600
  fi_GridCellText,
  fi_SetStamp0,
  fi_SetStamp1,
  fi_SetStamp2,
  fi_SetStamp3,
  fi_CellStamp,
  fi_CellImage,

  fi_OkBox,
  fi_OkCanBox,
  fi_YesNoBox,
  fi_YesNoCanBox,
  fi_ErrorBox,
  fi_WarningBox,
  fi_AlertBox,
  fi_ResultBox,

  fi_hWND,
  fi_SetReportInfo,
  fi_ReportTitle,
  fi_ReportAuthor,
  fi_ReportDate,
  fi_ReportTime,
  fi_SetReportExtra,
  fi_ReportExtra,
  fi_SetNPages,
  fi_NPages,
  fi_SetPaperSize,
  fi_PaperWidth,
  fi_PaperHeight,
  fi_SetPageSize,
  fi_PageWidth,
  fi_PageHeight,
  fi_PageLeft,
  fi_PageTop,
  fi_PageRight,
  fi_PageBottom,
  fi_SetPageMargin,
  fi_BodyWidth,
  fi_BodyHeight,
  fi_BodyLeft,
  fi_BodyTop,
  fi_BodyRight,
  fi_BodyBottom,
  fi_SetHeaderHeight,
  fi_SetFooterHeight,
  fi_BodyWidth, // HeaderWidth
  fi_HeaderHeight,
  fi_BodyLeft,  // HeaderLeft
  fi_HeaderTop,
  fi_BodyRight, // HeaderRight
  fi_BodyTop,   // HeaderBottom
  fi_BodyWidth, // FooterWidth
  fi_FooterHeight,
  fi_BodyLeft,  // FooterLeft
  fi_BodyBottom,// FooterTop
  fi_BodyRight, // FooterRight
  fi_FooterBottom,
  fi_SetReqBodyWidth,
  fi_ReqBodyWidth,
  fi_PageCell,
  fi_BodyCell,
  fi_HeaderCell,
  fi_FooterCell,

  fi_EditRowDlgBox,

  fi_LoadIMG,
  fi_SaveIMG,
  fi_LoadJPG,
  fi_SaveJPG,

  fi_StatMsg,
  fi_BusyMsg,
  fi_EndBusy,
};
static BFNS fsBOL = { fiBOL, _countof(fiBOL) };

//――――――――――――――――――――――――――――――――――――――//

typedef struct {
  F8B   csf;
  F8B   lsf;
} SPCA;

static COLI ciSPC[] = {
  { TID_F8B,  0, "csf", },
  { TID_F8B,  0, "lsf", },
};
static COLS csSPC = { ciSPC, _countof(ciSPC) };
static TBLI tiSPC = { &csSPC, };

void LOCALF fparSPC(HREP rp, rSTR *pp)
{ // 文字間調整倍率、行ピッチ倍率の設定
  SPCA dat;

  dat.csf = SpacingFactorC(rp);
  dat.lsf = SpacingFactorL(rp);
  ReadATR(&dat, &tiSPC, *pp); *pp = cpos();
  CloseBrackets(pp, TRUE);
  SetSpacingFactor(rp, dat.csf, dat.lsf);
}

typedef struct {
  I4B   id;
  I1B   tag[4];
  I1B   face[32]; // -+
  F8B   ch;       //  |
  I4B   flg;      //  |
  BGRC  col;      //  |
  F8B   bph;      //  |
  F8B   aph;      //  |
  F8B   fiw;      //  |
  F8B   liw;      //  |= PFMI
  F8B   riw;      // -+
} PFMA;

static COLI ciPFM[] = {
  { TID_U4B,  0, "id",  },
  { STR(4),   0, "tag", },
  { STR(32),  0, "face",},
  { TID_F8B,  0, "ch",  },
  { TID_U4B,  0, "flg", },
  { TID_U4B,  0, "col", },
  { TID_F8B,  0, "bph", },
  { TID_F8B,  0, "aph", },
  { TID_F8B,  0, "fiw", },
  { TID_F8B,  0, "liw", },
  { TID_F8B,  0, "riw", },
};
static COLS csPFM = { ciPFM, _countof(ciPFM) };
static TBLI tiPFM = { &csPFM, };

void LOCALF fparPFM(HREP rp, rSTR *pp)
{ // 段落書式登録
  PFMA dat;

  memset(&dat, 0, sizeof(PFMA)); dat.id = -1;
  ReadATR(&dat, &tiPFM, *pp); *pp = cpos();
  CloseBrackets(pp, TRUE);
  RegisterParagraphFormat(dat.id, dat.tag, (rPFMI)dat.face);
}

typedef struct {
  I1B   src[512];
} IMGA;

static COLI ciIMG[] = {
  { STR(512), 0, "src", },
};
static COLS csIMG = { ciIMG, _countof(ciIMG) };
static TBLI tiIMG = { &csIMG, };

void LOCALF fchrIMG(HREP rp, rSTR *pp, rCELL pc, PWHSZ sz)
{ // 画像出力
  IMGA dat;
  HDIB bm;
  SIZE siz;
  CELL cel;

  memset(&dat, 0, sizeof(IMGA));
  ReadATR(&dat, &tiIMG, *pp); *pp = cpos();
  CloseBrackets(pp, FALSE);
  bm = LoadJPG(NULL, dat.src); if (!bm) { bm = CreateDIBFromDDB(AppDDB(BID_DUMMY));}
  GetDIBSize(&siz, bm);
  sz->w = siz.cx * MMPI / DEFDPI;
  sz->h = siz.cy * MMPI / DEFDPI;
  if (pc) {
    cel = *pc; cel.x2 = cel.x1 + sz->w;
    CellImage(rp, &cel, bm, DT_AJW|(ParagraphAlignment(rp) &~0x03));
  }
  DeleteDIB(bm);
}

typedef struct {
  F8B   x0;   // -+
  F8B   y0;   //  |
  F8B   dcw;  //  |
  F8B   drh;  //  |
  F8B   *pw;  //  |
  I4B   nc;   //  |
  F8B   *ph;  //  |= GRID
  I4B   nr;   // -+
  I4B   col;
  I4B   rst;
  F8B   cw[16];
  F8B   rh[48];
} TBLA;

static COLI ciTBL[] = {
  { BIN(16), 0, NULL,  },
  { TID_F8B, 0, "dcw", },
  { TID_F8B, 0, "drh", },
  { BIN(4),  0, NULL,  },
  { TID_I4B, 0, "nc",  },
  { BIN(4),  0, NULL,  },
  { TID_I4B, 0, "nr",  },
  { TID_I4B, 0, "col", },
  { TID_I4B, 0, "rst", },
  { TID_F8B, 0, "cw0", },
  { TID_F8B, 0, "cw1", },
  { TID_F8B, 0, "cw2", },
  { TID_F8B, 0, "cw3", },
  { TID_F8B, 0, "cw4", },
  { TID_F8B, 0, "cw5", },
  { TID_F8B, 0, "cw6", },
  { TID_F8B, 0, "cw7", },
  { TID_F8B, 0, "cw8", },
  { TID_F8B, 0, "cw9", },
  { BIN(48), 0, NULL,  },
  { TID_F8B, 0, "rh0", },
  { TID_F8B, 0, "rh1", },
  { TID_F8B, 0, "rh2", },
  { TID_F8B, 0, "rh3", },
  { TID_F8B, 0, "rh4", },
  { TID_F8B, 0, "rh5", },
  { TID_F8B, 0, "rh6", },
  { TID_F8B, 0, "rh7", },
  { TID_F8B, 0, "rh8", },
  { TID_F8B, 0, "rh9", },
  { BIN(304),0, NULL,  },
};
static COLS csTBL = { ciTBL, _countof(ciTBL) };
static TBLI tiTBL = { &csTBL, };

void LOCALF fchrTBL(HREP rp, rSTR *pp, rCELL pc, PWHSZ sz)
{ // 表出力
  I4B i, j, fmt, sta;
  rSTR pt;
  F8B  tw, th;
  TBLA dat;
  WHSZ siz;
  CELL cel;

  memset(&dat, 0, sizeof(TBLA));
  dat.rst = RST_THN;
  ReadATR(&dat, &tiTBL, *pp); *pp = cpos();
  start(*pp);
  ZenCharSize(&siz, rp);
  dat.pw = dat.cw;
  dat.ph = dat.rh;
  if (dat.dcw <= 0.0) { dat.dcw = (DEFCWID + 1.5) * siz.w;}
  if (dat.drh <= 0.0) { dat.drh = siz.h * SpacingFactorL(rp);}
  if (dat.nc <= 0 || dat.nc > _countof(dat.cw)) { dat.nc = 1;}
  if (dat.nr <= 0 || dat.nr > _countof(dat.rh)) { dat.nr = 1;}
  tw = 0.0;
  for (i = 0; i < dat.nc; i++) {
    if (dat.cw[i] <= 0.0) { dat.cw[i] = dat.dcw;}
    tw += dat.cw[i];
  }
  th = 0.0;
  for (i = 0; i < dat.nr; i++) {
    if (dat.rh[i] <= 0.0) { dat.rh[i] = dat.drh;}
    th += dat.rh[i];
  }
  sz->w = tw;
  sz->h = th;
  if (pc) {
    fmt = ParagraphAlignment(rp);
    sta = FlowTextStatus(rp);
    dat.x0 = pc->x1;
    dat.y0 = pc->y1;
    if      (fmt & DT_BTM) { dat.y0 += (pc->y2 - pc->y1 - th);}
    else if (DTisMID(fmt)) { dat.y0 += (pc->y2 - pc->y1 - th) / 2;}
    for (i = 0; i < dat.nr; i++) {
      for (j = 0; j < dat.nc; j++) {
        SetLineColor(rp, dat.col);
        DrawGridCell(rp, (rGRID)&dat, i, j, dat.rst);
        if (token_is(TKN_STR)) {
          pt = buf();
          SetFlowTextStatus(rp, STA_PAR|STA_LIN);
          FlowText(rp, &pt, GridCell(&cel, (rGRID)&dat, i, j));
        }
      }
    }
    SetFlowTextStatus(rp, sta);
  }
  CloseBrackets(pp, FALSE);
}

 // 流し込みテキストのタグ要素
static FTEI giBOL[] = {
  { "spacing", fparSPC, NULL    },
  { "font",    fparPFM, NULL    },
  { "image",   NULL,    fchrIMG },
  { "table",   NULL,    fchrTBL },
};
static FTES gsBOL = { giBOL, _countof(giBOL) };

//――――――――――――――――――――――――――――――――――――――//

  // メインメニュー
static MNUI BOLMI[] = {
  { mfP,  0,             "ファイル(&F)"            }, // 0 ファイル
  { mf_,  IDM_OMENU1,    "メニュー(&M)"            },
  { mf_,  0,             ""                        },
  { mf_,  IDM_NEW,       "新規作成(&N)...\tCtrl+N" },
  { mf_,  IDM_OPEN,      "開く(&O)...\tCtrl+O"     },
  { mf_,  IDM_CLOSE,     "閉じる(&C)\tCtrl+F4"     },
  { mf_,  IDM_SAVE,      "上書保存(&S)\tCtrl+S"    },
  { mf_,  IDM_SAVEAS,    "名前を付けて保存(&A)...\tF12" },
  { mf_,  0,             ""                        },
  { mf_,  IDM_IMPORT,    "テキスト取込(&I)..."     },
  { mf_,  IDM_EXPORT,    "テキスト書出(&E)..."     },
  { mf_,  0,             ""                        },
  { mf_,  IDM_PRINT,     "印刷(&P)...\tCtrl+P"     },
  { mf_,  IDM_PRINTSLP,  "単票印刷(&L)..."         },
  { mf_,  0,             ""                        },
  { mfE,  IDM_EXIT,      "終了(&X)"                },
  { mfP,  0,             "編集(&E)"                }, // 1 編集
  { mf_,  IDM_CUT,       "切り取り(&T)\tCtrl+X"    },
  { mf_,  IDM_COPY,      "コピー(&C)\tCtrl+C"      },
  { mf_,  IDM_PASTE,     "貼り付け(&P)\tCtrl+V"    },
  { mf_,  0,             ""                        },
  { mf_,  IDM_CLEAR,     "クリア(&A)\tDel"         },
  { mf_,  IDM_INSERT,    "挿入(&I)\tCtrl+E"        },
  { mf_,  IDM_DELETE,    "削除(&D)\tCtrl+D"        },
  { mf_,  0,             ""                        },
  { mf_,  IDM_OPENLINK,  "リンクを開く(&O)"        },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SEARCH,    "検索(&F)...\tCtrl+F"     },
  { mfE,  IDM_NSEARCH,   "次を検索(&N)\tF3"        },
  { mfP,  0,             "表示(&V)"                }, // 2 表示  VIW_POS
  { mf_,  IDM_VIEW,      "表示形式(&V)...\tF5"     },
  { mf_,  0,             ""                        },
  { mf_,  IDM_ARRANGE,   "表示項目(&A)..."         },
  { mf_,  IDM_FILTER,    "絞り込み(&F)..."         },
  { mf_,  IDM_SORT,      "並べ替え(&S)..."         },
  { mf_,  0,             ""                        },
  { mf_,  IDM_VIEWA,     "全項目表示(&W)\tF10"     },
  { mf_,  IDM_VIEWB,     "表示形式解除(&B)\tShift+F10" },
  { mf_,  0,             ""                        },
  { mfE,  IDM_SETVOPT,   "表示オプション(&O)..."   },
  { mfP,  0,             "データ(&D)"              }, // 3 データ
  { mf_,  IDM_SUMMARY,   "集計(&S)..."             },
  { mf_,  0,             ""                        },
  { mf_,  IDM_CHECK,     "チェック(&C)\tShift+F5"  },
  { mf_,  0,             ""                        },
  { mf_,  IDM_EDIT,      "行編集(&E)\tF8"          },
  { mf_,  IDM_ADDEDIT,   "行追加(&A)\tShift+F7"    },
  { mf_,  IDM_INSERTEDIT,"行挿入(&I)\tF9"          },
  { mf_,  IDM_SELDELETE, "行削除(&D)\tShift+F9"    },
  { mf_,  0,             ""                        },
  { mfE,  IDM_PSORT,     "物理的に並べ替え(&P)"    },
  { mfP,  0,             "処理(&P)"                }, // 4 処理
  { mf_,  IDM_EXECUTE,   "一括処理(&X)..."         },
  { mf_,  0,             ""                        },
  { mf_,  IDM_REPORT,    "帳票作成(&R)..."         },
  { mf_,  0,             ""                        },
  { mf_,  IDM_DBWHO,     "ＤＢ接続状況(&D)"        },
  { mf_,  IDM_SITEWHO,   "ログイン状況(&S)"        },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SETUSR,    "ユーザー管理(&U)"        },
  { mf_,  IDM_UNLOCK,    "ロック解除(&L)..."       },
  { mfE,  IDM_BACKUP,    "ファイル転送(&B)..."     },
  { mfP,  0,             "ツール(&T)"              }, // 5 ツール
  { mf_,  IDM_COMPILE,   "コンパイル(&C)..."       },
  { mf_,  0,             ""                        },
  { mf_,  IDM_TEDIT,     "テキスト編集(&T)..."     },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SETENV,    "環境設定(&E)..."         },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SETOPT,    "オプション設定(&O)..."   },
  { mf_,  0,             ""                        },
  { mfE,  IDM_SETDATE,   "計算日設定(&D)..."       },
  { mfP,  0,             "ウィンドウ(&W)"          }, // 6 ウィンドウ  WIN_POS
  { mf_,  IDM_PREVWINDOW,"前のウィンドウ(&P)\tShift+Ctrl+F6" },
  { mf_,  IDM_NEXTWINDOW,"次のウィンドウ(&N)\tCtrl+F6" },
  { mf_,  0,             ""                        },
  { mf_,  IDM_MAXIMIZE,  "単独で表示(&M)"          },
  { mf_,  IDM_TILE,      "左右に並べて表示(&T)"    },
  { mfE,  IDM_HTILE,     "上下に並べて表示(&H)"    },
  { mfPE, 0,             "ヘルプ(&H)"              }, // 7 ヘルプ
  { mf_,  IDM_MANUAL,    "マニュアル(&M)\tF1"      },
  { mf_,  0,             ""                        },
  { mfE,  IDM_ABOUT,     "バージョン情報(&A)"      },
};
static MNUS BOLMS = { BOLMI, _countof(BOLMI) };

#define  VIW_POS  2
#define  WIN_POS  6

static MNUI PRNMI[] = {
  { mfP,  0,             "表示(&V)"                }, // 表示(PRN)
  { mf_,  IDM_PREVPAGE,  "前ページ(&P)\tCtrl+Alt+P" },
  { mf_,  IDM_NEXTPAGE,  "次ページ(&N)\tCtrl+Alt+N" },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SETPRN,    "用紙設定(&S)\tCtrl+Alt+S" },
  { mf_,  0,             ""                        },
  { mf_,  IDM_ZOOMIN,    "拡大(&Z)\tCtrl+;"        },
  { mf_,  IDM_ZOOMOUT,   "縮小(&O)\tCtrl+-"        },
  { mf_,  0,             ""                        },
  { mf_,  IDM_SAMESCALE, "等倍表示(&S)\tCtrl+1"    },
  { mfE,  IDM_AUTOSCALE, "全体表示(&A)\tCtrl+0"    },
};
static MNUS PRNMS = { PRNMI, _countof(PRNMI) };

  // ツールバー
static TOBI BOLTI[] = {
  { tbfB,      IDM_PREVWINDOW, "前のウィンドウ" }, //  0
  { tbfB,      IDM_NEXTWINDOW, "次のウィンドウ" },
  { tbfV,      0,              ""               },
  { tbfL(192), IDBAS,          ""               },
  { tbfB,      IDM_CLOSE,      "閉じる"         },
  { tbfV,      0,              ""               },
  { tbfB,      IDM_NEW,        "新規作成"       },
  { tbfB,      IDM_OPEN,       "開く"           },
  { tbfB,      IDM_SAVE,       "上書保存"       },
  { tbfB,      IDM_PRINT,      "印刷"           },
  { tbfV,      0,              ""               },
  { tbfB,      IDM_CUT,        "切り取り"       }, // 11  CUT_IDX
  { tbfB,      IDM_COPY,       "コピー"         },
  { tbfB,      IDM_PASTE,      "貼り付け"       },
  { tbfB,      IDM_SEARCH,     "検索"           },
  { tbfV,      0,              ""               },
  { tbfB,      IDM_VIEW,       "表示形式"       }, // 16  VIW_IDX
  { tbfB,      IDM_ARRANGE,    "表示項目"       },
  { tbfB,      IDM_FILTER,     "絞り込み"       },
  { tbfB,      IDM_SORT,       "並べ替え"       },
  { tbfV,      0,              ""               },
  { tbfB,      IDM_SUMMARY,    "集計"           },
  { tbfB,      IDM_CHECK,      "チェック"       },
  { tbfB,      IDM_EDIT,       "行編集"         },
  { tbfB,      IDM_ADDEDIT,    "行追加"         },
  { tbfB,      IDM_INSERTEDIT, "行挿入"         },
  { tbfB,      IDM_SELDELETE,  "行削除"         },
  { tbfV,      0,              ""               },
};
static TOBS BOLTS = { BOLTI, _countof(BOLTI) };

#define  CUT_IDX 11
#define  VIW_IDX 16

static TOBI TXTVW[] = {
  { tbfB,      IDM_SAVEAS,     "名前を付けて保存" },
  { tbfL(90),  IDPOS,          ""               },
  { tbfB,      IDM_CHECK,      "チェック"       },
  { tbfB,      IDM_COMPILE,    "コンパイル"     },
  { tbfV,      0,              ""               },
};
static TOBI TXTTI[VIW_IDX + _countof(TXTVW)];
static TOBS TXTTS = { TXTTI, _countof(TXTTI) };

static TOBI PRNVW[] = {
  { tbfB,      IDM_PREVPAGE,   "前ページ"       },
  { tbfB,      IDM_NEXTPAGE,   "次ページ"       },
  { tbfL(54),  IDPAG,          ""               },
  { tbfB,      IDM_SETPRN,     "用紙設定"       },
  { tbfV,      0,              ""               },
  { tbfB,      IDM_ZOOMIN,     "拡大"           },
  { tbfB,      IDM_ZOOMOUT,    "縮小"           },
  { tbfL(42),  IDSCL,          ""               },
  { tbfB,      IDM_SAMESCALE,  "等倍表示"       },
  { tbfB,      IDM_AUTOSCALE,  "全体表示"       },
  { tbfV,      0,              ""               },
};
static TOBI PRNTI[CUT_IDX + _countof(PRNVW)];
static TOBS PRNTS = { PRNTI, _countof(PRNTI) };

void LOCALF PrepToolBar(void)
{ // ツールバー設定
  I4B i;

  for (i = 0; i < _countof(TXTTI); i++) {
    TXTTI[i] = (i < VIW_IDX)? BOLTI[i]: TXTVW[i - VIW_IDX];
  }
  for (i = 0; i < _countof(PRNTI); i++) {
    PRNTI[i] = (i < CUT_IDX)? BOLTI[i]: PRNVW[i - CUT_IDX];
  }
}

static TOBI BOLSI[] = {
  { tbfL(512), IDBAS, "" },
};
static TOBS BOLSS = { BOLSI, _countof(BOLSI) };

  // 開始メニュー
static MNDI BOLDI[] = {
  { mf_,  IDM_NEW,       "新規作成",        BID_INPUT   }, //  0
  { mf_,  IDM_OPEN,      "表を開く",        BID_TABLE   },
  { mf_,  IDM_EXECUTE,   "一括処理",        BID_EXECUTE },
  { mf_,  IDM_REPORT,    "帳票類印刷",      BID_REPORT  },
  { mf_,  IDM_COMPILE,   "コンパイル",      BID_EXECUTE },
  { mf_,  IDM_SETOPT,    "オプション設定",  BID_SYSTEM  },
  { mf_,  IDJMP + 1,     "システム管理",    BID_SYSTEM  },
  { mf_,  IDM_EXIT,      "終　　了",        BID_EXIT    },
  { mf_,  IDM_SETUSR,    "ユーザー管理",    BID_TABLE   }, //  1
  { mf_,  IDM_DBWHO,     "ＤＢ接続状況",    BID_SYSTEM  },
  { mf_,  IDM_SITEWHO,   "ログイン状況",    BID_SYSTEM  },
  { mf_,  IDM_UNLOCK,    "ロック解除",      BID_SYSTEM  },
  { mf_,  IDM_BACKUP,    "ファイル転送",    BID_SYSTEM  },
  { mf_,  IDM_SETENV,    "環境設定",        BID_SYSTEM  },
  { mf_,  IDM_TEDIT,     "テキスト編集",    BID_TEXT    },
  { mf_,  IDJMP,         "戻　　る",        BID_BACK    },
};
static MNDS BOLDS = { BOLDI, _countof(BOLDI), 0, 0, NULL, NULL };

  // 環境設定情報
typedef struct {
  I1B   snam[16];
  I1B   stit[32];
  I1B   sdsc[64];
  F8B   rtax;
  I4B   fymn;
  I4B   nmfy;
  I1B   udir[512];
} ENVD;

static COLI ciENV[] = {
  { STR(16),  0, "SiteNam", "[BOLENV]", },
  { STR(32),  0, "SiteTit", },
  { STR(64),  0, "SiteDsc", },
  { TID_F8B,  0, "TaxRate", },
  { TID_I4B,  0, "FYMonth", },
  { TID_I4B,  0, "NMonthF", },
  { STR(512), 0, "UserDir", },
};
static COLS csENV = { ciENV, _countof(ciENV) };
static TBLI tiENV = { &csENV, NULL, "BOLENV", NULL, NULL, 0, NULL, "BOLENV.INI", 0, sizeof(ENVD) };

ENVD EnvDat;

void LOCALF setenv(void)
{ // 環境設定
  SITI var;

  var.nam = EnvDat.snam;
  var.tit = EnvDat.stit;
  var.dsc = EnvDat.sdsc;
  var.tax = EnvDat.rtax;
  var.fym = EnvDat.fymn;
  var.nmf = EnvDat.nmfy;
  var.dir = EnvDat.udir;
  SetSiteVariables(&var);
}

void LOCALF LoadENV(void)
{ // 環境設定読込
  strcpyx(EnvDat.snam, SiteName(), sizeof(EnvDat.snam) - 1);
  strcpyx(EnvDat.stit, SiteTitle(), sizeof(EnvDat.stit) - 1);
  strcpyx(EnvDat.sdsc, SiteDescription(), sizeof(EnvDat.sdsc) - 1);
  EnvDat.rtax = TaxRate();
  EnvDat.fymn = FYearMonth();
  EnvDat.nmfy = NMonthFYear();
  strcpyx(EnvDat.udir, UserPath(), sizeof(EnvDat.udir) - 1);
  if (file_exists(tiENV.imp)) {
    ReadINI(&EnvDat, &tiENV);
  }
  setenv();
}

void LOCALF SaveENV(void)
{ // 環境設定書出
  setenv();
  WriteINI(&EnvDat, &tiENV);
}

#define  UOPT_ALI  0x0001
#define  UOPT_UMD  0x0002
#define  UOPT_ACN  0x0004
#define  UOPT_AOP  0x0008
#define  UOPT_ELG  0x0010

#define  BGRC_PTR  RGB(208,255,224)
#define  BGRC_IDX  RGB(208,208,208)
#define  BGRC_OLD  RGB(255,224,208)

  // 初期設定情報
typedef struct {
  WPOS  wpo;
  I1B   face[32]; // -+
  I4B   ptsz;     //  |
  I4B   tbcs;     //  |
  I4B   cptr;     //  |
  I4B   cidx;     //  |
  I4B   uopt;     //  |
  I1B   unam[32]; //  |
  I1B   upwd[32]; //  |
  I1B   cnam[16]; //  |= OPTP
  I1B   onam[16]; // -+
  I1B   bdir[512];
} INID;

static COLI ciINI[] = {
  { TID_I4B,  0, "WinPosX", "["PRGNAM"]", }, // 0
  { TID_I4B,  0, "WinPosY", },
  { TID_I4B,  0, "WinSizW", },
  { TID_I4B,  0, "WinSizH", },
  { TID_I4B,  0, "WinMaxm", },
  { STR(32),  0, "TblFont", },
  { TID_I4B,  0, "TblFSiz", },
  { TID_I4B,  0, "TblStyl", },
  { TID_HEX,  0, "CPtrCol", }, // 8
  { TID_HEX,  0, "CIdxCol", }, // 9
  { TID_I4B,  0, "UserOpt", },
  { STR(32),  0, "UserNam", },
  { STR(32),  0, "UserPwd", NULL, NULL, CF_HCH, },
  { STR(16),  0, "StartDB", },
  { STR(16),  0, "OpenTbl", },
  { STR(512), 0, "BackDir", },
};
#define  ciCPTR  ciINI[8]
#define  ciCIDX  ciINI[9]
static COLS csINI = { ciINI, _countof(ciINI) };
static TBLI tiINI = { &csINI, NULL, "BOLINI", NULL, NULL, 0, NULL, PRGNAM".INI", 0, sizeof(INID) };

static INID IniDat = {
  { 0, 0, 1200, 730, FALSE },
  DEFFACE, DEFPTSZ,
  0,
  BGRC_PTR, BGRC_IDX,
  0,
  "", "",
  "", "",
  "",
};

rSTR LOCALF defface(void) { return IniDat.face;}
I4B  LOCALF defptsz(void) { return IniDat.ptsz;}
I4B  LOCALF optflg(void)  { return IniDat.tbcs;}

void LOCALF LoadINI(void)
{ // 初期化ファイル読込
  LOGFONT lof;
  STRBUF bak;

  get_working_path(bak, sizeof(bak));
  set_working_path(UserPath());
  if (file_exists(tiINI.imp)) {
    ReadINI(&IniDat, &tiINI);
  }
  set_working_path(bak);
  SetAppFont(FID_DEF, CreateFontIndirect(SetLOGFONT(&lof, IniDat.face, PT2DOTS(IniDat.ptsz), 0)));
  SetAppColor(CID_PTR, IniDat.cptr); if (IniDat.cidx == BGRC_OLD) { IniDat.cidx = BGRC_IDX;}
  SetAppColor(CID_IDX, IniDat.cidx);
  if (IniDat.uopt & UOPT_ELG) { enable_error_logging();} else { disable_error_logging();}
}

void LOCALF SaveINI(void)
{ // 初期化ファイル書出
  I4B sw;
  STRBUF bak;

  if (!(IniDat.uopt & UOPT_ALI)) { IniDat.upwd[0] = '\0';}
  get_working_path(bak, sizeof(bak));
  set_working_path(UserPath());
  sw = disable_error_reporting();
  WriteINI(&IniDat, &tiINI);
  if (sw) { enable_error_reporting();}
  set_working_path(bak);
}

I4B LOCALF AppStatusX(HWND hwnd)
{ // 状態の取得
  I4B sta;

  sta = AppStatus(hwnd);
  switch (sta & APPS_ACT) {
  case APPS_TXT: sta |= TXT_appstatus((HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0)); break;
  case APPS_PRN: sta |= PRN_appstatus((HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0)); break;
  case APPS_DIB: sta |= DIB_appstatus((HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0)); break;
  case APPS_TBL: sta |= TBL_appstatus((HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0)); break;
  }
  return sta;
}

#define  sta_ACT  ((sta & APPS_ACT) != 0)
#define  sta_NON  ((sta & APPS_ACT) == 0)
#define  sta_TXT  ((sta & APPS_ACT) == APPS_TXT)
#define  sta_PRN  ((sta & APPS_ACT) == APPS_PRN)
#define  sta_DIB  ((sta & APPS_ACT) == APPS_DIB)
#define  sta_TBL  ((sta & APPS_ACT) == APPS_TBL)
#define  sta_EDI  ((sta & APPS_DED) == 0)
#define  sta_SEL  ((sta & APPS_SEL) != 0)
#define  sta_MUL  ((sta & APPS_MUL) != 0)
#define  sta_CFT  ((sta & APPS_CFT) != 0)
#define  sta_CFB  ((sta & APPS_CFB) != 0)
#define  sta_PVP  ((sta & APPS_PVP) != 0)
#define  sta_NXP  ((sta & APPS_NXP) != 0)
#define  sta_SKP  ((sta & APPS_SKP) != 0)
#define  sta_LSC  ((sta & APPS_LSC) != 0)
#define  sta_USC  ((sta & APPS_USC) != 0)
#define  sta_LNK  ((sta & APPS_LNK) != 0)

BOOL LOCALF Enabled(I4B id, I4B sta)
{ // コマンドが使用可能かどうかの判定
  switch (id) {
  case IDM_OMENU:
  case IDM_OMENU1:
  case IDM_REPORT:
  case IDM_SETOPT:
  case IDM_SETDATE:
    return sta_NON;
  case IDM_CLOSE:
  case IDM_PRINT:
    return sta_ACT;
  case IDM_SAVE:
  case IDM_CHECK:
    return (sta_TXT || sta_TBL) && sta_EDI && CurAuth() >= 2;
  case IDM_PASTE:
    return ((sta_TXT && sta_CFT) || (sta_TBL && ((sta_CFB && sta_SEL) || sta_CFT))) && sta_EDI && CurAuth() >= 2;
  case IDM_SAVEAS:
    return sta_TXT && sta_EDI && CurAuth() >= 2;
  case IDM_IMPORT:
  case IDM_CLEAR:
  case IDM_EDIT:
  case IDM_ADDEDIT:
  case IDM_INSERTEDIT:
  case IDM_SELDELETE:
  case IDM_PSORT:
    return sta_TBL && sta_EDI && CurAuth() >= 2;
  case IDM_EXPORT:
  case IDM_PRINTSLP:
  case IDM_VIEW:
  case IDM_ARRANGE:
  case IDM_FILTER:
  case IDM_SORT:
  case IDM_VIEWA:
  case IDM_VIEWB:
  case IDM_SETVOPT:
  case IDM_SUMMARY:
    return sta_TBL;
  case IDM_CUT:
    return ((sta_TXT && sta_SEL) || sta_TBL) && sta_EDI && CurAuth() >= 2;
  case IDM_COPY:
    return (sta_TXT && sta_SEL) || sta_TBL;
  case IDM_INSERT:
    return sta_TBL && sta_SEL && sta_EDI && CurAuth() >= 2;
  case IDM_DELETE:
    return (sta_TXT || sta_TBL) && sta_SEL && sta_EDI && CurAuth() >= 2;
  case IDM_OPENLINK:
    return sta_TBL && sta_LNK;
  case IDM_SEARCH:
  case IDM_NSEARCH:
    return sta_TXT || (sta_TBL && !sta_SEL);
  case IDM_EXECUTE:
    return sta_NON && CurAuth() >= 2;
  case IDM_NEW:
  case IDM_UNLOCK:
  case IDM_BACKUP:
    return sta_NON && CurAuth() >= 3;
  case IDM_COMPILE:
    return (sta_NON || (sta_TXT && sta_EDI)) && CurAuth() >= 3;
  case IDM_TEDIT:
    return CurAuth() >= 3;
  case IDM_SETUSR:
  case IDM_SETENV:
    return sta_NON && CurAuth() == 4;
  case IDM_PREVWINDOW:
  case IDM_NEXTWINDOW:
  case IDM_MAXIMIZE:
  case IDM_TILE:
  case IDM_HTILE:
    return sta_MUL;
  case IDM_PREVPAGE:
    return sta_PRN && sta_PVP;
  case IDM_NEXTPAGE:
    return sta_PRN && sta_NXP;
  case IDM_SETPRN:
    return sta_PRN && !sta_SKP;
  case IDM_ZOOMIN:
    return (sta_PRN || sta_DIB) && !sta_USC;
  case IDM_ZOOMOUT:
    return (sta_PRN || sta_DIB) && !sta_LSC;
  case IDM_SAMESCALE:
  case IDM_AUTOSCALE:
  case IDM_INVERT:
    return sta_PRN || sta_DIB;
  }
  return TRUE;
}

pMNUS LOCALF viwpop(I4B sta)
{ // 表示メニュー
  I4B i, i1, i2, j;
  static MNUI VMI[24];
  static MNUS VMS = { VMI, 0 };

  switch (sta & APPS_ACT) {
  case APPS_PRN:
  case APPS_DIB: return &PRNMS;
  }
  MenuSlice(&i1, &i2, &BOLMS, VIW_POS);
  for (i = i1, j = 0; i < i2 && j < _countof(VMI); i++, j++) {
    VMI[j] = BOLMI[i];
  }
  VMI[j-1].flg |= mfE;
  VMS.ni = j;
  return &VMS;
}

pMNUS LOCALF winpop(HWND hwnd)
{ // ウィンドウメニュー
  I4B i, i1, i2, j, j0, nc;
  HWND hchi;
  static MNUI WMI[24], WM0 = { mf_, 0, "" };
  static MNUS WMS = { WMI, 0 };

  MenuSlice(&i1, &i2, &BOLMS, WIN_POS);
  for (i = i1, j = 0; i < i2 && j < _countof(WMI); i++, j++) {
    WMI[j] = BOLMI[i];
  }
  WMI[j-1].flg |= mfE;
  nc = SendMessage(hwnd, FRMM_GETNCHILDREN, 0, 0);
  if (nc > 0) {
    WMI[j-1].flg &=~mfE;
    WMI[j++] = WM0;
    j0 = j;
    for (i = nc - 1; i >= 0 && j < _countof(WMI); i--, j++) {
      WMI[j].flg = (i == nc - 1)? mfC: mf_;
      hchi = (HWND)SendMessage(hwnd, FRMM_GETCHILD, i, 0);
      WMI[j].idm = IDM_WINDOW0 + j - j0;
      WMI[j].txt = basnam(WindowText(hchi));
    }
    WMI[j-1].flg |= mfE;
  }
  WMS.ni = j;
  return &WMS;
}

void LOCALF enummenuitems(HMENU hmnu, I4B sta)
{ // メニュー項目設定
  I4B i, n, id;
  HMENU hsub;

  n = GetMenuItemCount(hmnu);
  for (i = 0; i < n; i++) {
    id = GetMenuItemID(hmnu, i);
    if (id == -1 && !!(hsub = GetSubMenu(hmnu, i))) { enummenuitems(hsub, sta);}
    else if (id > 0) { EnableMenuItem(hmnu, id, Enabled(id, sta)? mf_: mfG);}
  }
}

iANY LOCALF FRM_initmenu(HWND hwnd, HMENU hmnu)
{ // メニュー設定
  I4B sta;

  sta = AppStatusX(hwnd);
  ChangeMenuBar(hmnu, VIW_POS, viwpop(sta));
  ChangeMenuBar(hmnu, WIN_POS, winpop(hwnd));
  DrawMenuBar(hwnd);
  enummenuitems(hmnu, sta);
  return 0;
}

iANY LOCALF FRM_inittool(HWND hwnd)
{ // ツールバー設定
  I4B i, id, ni, sta;
  HWND hact, htob;
  pTOBS ts;
  static pTOBS bk;

  htob = GetDlgItem(hwnd, IDTOB); if (!htob) return 0;
  hact = (HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0);
  sta = AppStatusX(hwnd);
  switch (sta & APPS_ACT) {
  case APPS_TXT: ts = &TXTTS; break;
  case APPS_PRN:
  case APPS_DIB: ts = &PRNTS; break;
  default:       ts = &BOLTS; break;
  }
  if (ts != bk) {
    SendMessage(htob, TOBM_RESETITEMS, (uANY)ts, TRUE);
    bk = ts;
  }
  ni = SendMessage(htob, TOBM_GETNITEMS, 0, 0);
  for (i = 0; i < ni; i++) {
    if ((id = ((pTOBI)SendMessage(htob, TOBM_GETITEMINFO, i, 0))->idm) > 0) {
      EnableWindow(GetDlgItem(htob, id), Enabled(id, sta));
    }
  }
  SetDlgItemText(htob, IDBAS, hact? basnam(WindowText(hact)): dformat("yyyy 年 m 月 d 日", CurDate()));
  switch (sta & APPS_ACT) {
  case APPS_TXT:
    SetDlgItemText(htob, IDPOS, TXT_POS);
    break;
  case APPS_PRN:
    SetDlgItemText(htob, IDPAG, PRN_PAG);
    SetDlgItemText(htob, IDSCL, PRN_SCL);
    break;
  case APPS_DIB:
    SetDlgItemText(htob, IDPAG, DIB_PAG); EnableDlgItem(htob, IDPAG, FALSE);
    SetDlgItemText(htob, IDSCL, DIB_SCL);
    break;
  }
  for (i = 0; i < BOLDS.ni; i++) {
    if ((id = BOLDS.mi[i].idm) > 0) {
      BOLDS.mi[i].flg = Enabled(id, sta)? mf_: mfG;
    }
  }
  return 0;
}

  // ユーザー名とパスワード
typedef struct {
  I1B   usr[32];
  I1B   pwd[32];
} PWDP;

BOOL LOCALF getpwd_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // ユーザー確認ダイアログプロシージャ
  PWDP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (PWDP *)lpa));
    SetESTR(hdlg, 101, pa->usr);
    SetFocus(GetDlgItem(hdlg, (pa->usr[0] == '\0')? 101: 102));
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return FALSE;
  case WM_COMMAND:
    pa = (PWDP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetESTR(hdlg, 101, pa->usr, sizeof(pa->usr) - 1);
      GetESTR(hdlg, 102, pa->pwd, sizeof(pa->pwd) - 1);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL LOCALF GetPwd(HWND hwnd, PWDP *pa)
{ // ユーザー名とパスワード取得
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 40,  8,  -1, "ユーザー名:" },
    { C_ESTR|wsT,  48,  8,100, 12, 101, "" },
    { C_SLFT|wsG,   8, 26, 40,  8,  -1, "パスワード:" },
    { C_EPWD|wsT,  48, 24,100, 12, 102, "" },
    { C_BDEF|wsGT, 54, 60, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 106, 60, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 80, "ユーザー確認" };

  return DlgBoxInput(hwnd, &dlg, getpwd_DlgProc, (iANY)pa) == IDOK;
}

BOOL LOCALF alreadyloggedin(rSTR usr)
{ // 既にログインしている
  I4B i, ni, re = FALSE;
  HTBL tb;

  if (file_size(PRGNAM".BSU") == 0) return FALSE;
  tb = CreateBSUTable(32, TRUE); if (!tb) return FALSE;
  ni = NTableRows(tb);
  for (i = 0; i < ni; i++) {
    if (!_stricmp(usr, TableRow(tb, i))) { re = TRUE; break;}
  }
  DeleteTable(tb);
  return re;
}

void LOCALF cmd_login(HWND hwnd)
{ // ログイン
  I4B re;
  static rSTR alertstr =
    "同名のユーザーが既にログインしています。\n"
    "プログラムを二重に起動していないか確認してください。\n"
    "二重起動している場合、「中止」でこのプログラムを終了するか\n"
    "先に起動した方を終了してから「再試行」で続行します。\n"
    "二重起動していない場合、「無視」で続行して構いません。";

  if (!(IniDat.uopt & UOPT_ALI)) {
   _00: IniDat.upwd[0] = '\0';
    re = GetPwd(hwnd, (PWDP *)&IniDat.unam);
    if (!re) { SendMessage(hwnd, WM_CLOSE, 0, 0); return;}
  }
 _10:
  reset_error();
  if (alreadyloggedin(IniDat.unam)) {
    re = AlertBox(hwnd, alertstr, NULL);
    switch (re) {
    default: SendMessage(hwnd, WM_CLOSE, 0, 0); return;
    case IDRETRY: goto _10;
    case IDIGNORE: break;
    }
  }
  re = LoginSite(IniDat.unam, IniDat.upwd);
  if (!re) {
    ErrorBox(hwnd, "ログインに失敗しました。", NULL);
    IniDat.uopt &=~UOPT_ALI;
    goto _00;
  }
  if ((IniDat.uopt & UOPT_ACN) && IniDat.cnam[0] != '\0') {
    re = ConnectDB(IniDat.cnam);
    if (re && (IniDat.uopt & UOPT_AOP) && IniDat.onam[0] != '\0') {
      PostMessage(hwnd, WM_COMMAND, IDM_OPEN1, 0); return;
    }
  }
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

rSTR LOCALF dbwhostr(void)
{ // ＤＢへの接続状況、ファイルのロック状況
  I4B i, ni;
  pSTR pt;
  PLCKI pc;
  HTBL tb;
  static STRBUF msg;

  if (CurDBName()[0] == '\0') { return "ＤＢに接続していません。";}
  *(pt = msg) = '\0';
  if (file_size(addext(CurDBName(), ".BDU")) == 0) goto _10;
  tb = CreateBDUTable(32, TRUE); if (!tb) goto _10;
  ni = NTableRows(tb);
  for (i = 0; i < ni; i++) {
    if (pt - msg < 450) {
      pt += sprintfs(pt, (i == 0)? "'%s'": "、'%s'", TableRow(tb, i));
    }
  }
  if (ni > 0) { pt += sprintfs(pt, "が'%s'に接続中です。\n", CurDBName());}
  DeleteTable(tb);
  if (file_size(addext(CurDBName(), ".LCK")) == 0) goto _10;
  tb = CreateLCKTable(32, TRUE); if (!tb) goto _10;
  ni = NTableRows(tb);
  for (i = 0; i < ni; i++) {
    if (pt - msg < 450) {
      pc = TableRow(tb, i);
      pt += sprintfs(pt, (i == 0)? "'%s'を'%s'が": "、'%s'を'%s'が", DBTableFileName(pc->id), pc->usr);
    }
  }
  if (ni > 0) { pt += sprintfs(pt, "ロックしています。");}
  DeleteTable(tb); _10:
  return msg;
}

rSTR LOCALF sitewhostr(void)
{ // サイトへのログイン状況
  I4B i, ni;
  pSTR pt;
  HTBL tb;
  static STRBUF msg;

  *(pt = msg) = '\0';
  if (file_size(addext(SiteName(), ".BSU")) == 0) goto _10;
  tb = CreateBSUTable(32, TRUE); if (!tb) goto _10;
  ni = NTableRows(tb);
  for (i = 0; i < ni; i++) {
    if (pt - msg < 450) {
      pt += sprintfs(pt, (i == 0)? "'%s'": "、'%s'", TableRow(tb, i));
    }
  }
  if (ni > 0) { pt += sprintfs(pt, "がログイン中です。");}
  DeleteTable(tb); _10:
  return msg;
}

void LOCALF cmd_omenu(HWND hwnd, BOOL sw)
{ // 開始メニュー
  I4B re;

  if (AppStatus(hwnd) & APPS_ACT) return;
  if (!(IniDat.uopt & UOPT_ACN)) {
    DisconnectDB();
    SendMessage(hwnd, FRMM_INITTOOL, 0, 0);
  }
  if (!sw && !(IniDat.uopt & UOPT_UMD)) return;
 _00:
  BOLDS.msg2 = (CurDBName()[0] == '\0')? sitewhostr(): dbwhostr();
  re = MenuDlgBox(hwnd, &BOLDS, PRGTIT);
  if (re == IDREFRESH) goto _00;  else if (re == IDCANCEL) return;
  if (re == IDMANUAL) { re = IDM_MANUAL;}
  PostMessage(hwnd, WM_COMMAND, re, 0);
}

#define  CMD_NEW  1
#define  CMD_EDI  2
#define  CMD_COM  3

  // 新規作成情報
typedef struct {
  I4B   cmd;
  I4B   pro;     // -+
  I1B   nam[16]; //  |
  I1B   tit[32]; //  |= PROI
  I1B   dsc[64]; // -+
} NEWP;

void LOCALF cmd_tedit(HWND hwnd);
void LOCALF cmd_compile(HWND hwnd);

BOOL LOCALF new_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 新規作成ダイアログプロシージャ
  I4B id, sw;
  NEWP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (NEWP *)lpa));
    SetBSEL(hdlg, 101, pa->cmd == CMD_NEW || pa->cmd == 0);
    SetBSEL(hdlg, 102, pa->cmd == CMD_EDI);
    SetBSEL(hdlg, 103, pa->cmd == CMD_COM);
    SetBSEL(hdlg, 105, pa->pro == PRO_DEF || pa->pro == 0);
    SetBSEL(hdlg, 106, pa->pro == PRO_OPR);
    SetBSEL(hdlg, 107, pa->pro == PRO_REP);
    SetESTR(hdlg, 109, pa->nam);
    SetESTR(hdlg, 111, pa->tit);
    SetESTR(hdlg, 113, pa->dsc);
    sw = GetBSEL(hdlg, 101);
    for (id = 107; id <= 112; id++) {
      EnableDlgItem(hdlg, id, sw);
    }
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (NEWP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 101: case 102: case 103:
      sw = GetBSEL(hdlg, 101);
      for (id = 104; id <= 113; id++) {
        EnableDlgItem(hdlg, id, sw);
      }
      break;
    case IDOK:
      pa->cmd = GetBSEL(hdlg, 101)? CMD_NEW: GetBSEL(hdlg, 102)? CMD_EDI: CMD_COM;
      pa->pro = GetBSEL(hdlg, 105)? PRO_DEF: GetBSEL(hdlg, 106)? PRO_OPR: PRO_REP;
      GetESTR(hdlg, 109, pa->nam, sizeof(pa->nam) - 1);
      GetESTR(hdlg, 111, pa->tit, sizeof(pa->tit) - 1);
      GetESTR(hdlg, 113, pa->dsc, sizeof(pa->dsc) - 1);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_new(HWND hwnd)
{ // 新規作成
  NEWP par;
  static CREI cri = { "BOLTXT", wsCHV, };
  static rSTR guidstr =
    "データベースの新規作成（ＤＢ定義プロシージャの登録）は、\n"
    "ＤＢ定義プロシージャのソースコードをコンパイルすることで行います。";
  static DLGI dit[] = {
    { C_SMUL|wsG,   8,  8,208, 24,  -1, "" },
    { C_BGRP|wsG,   6, 36,228, 24,  -1, "ソースコード処理選択" },
    { C_BSEL|wsGT, 14, 46, 60, 10, 101, "新規作成(&N)" },
    { C_BSEL|ws_,  78, 46, 60, 10, 102, "既存編集(&E)" },
    { C_BSEL|ws_, 142, 46, 60, 10, 103, "コンパイル(&C)" },
    { C_BGRP|wsG,   6, 64,228, 24, 104, "プロシージャ種別" },
    { C_BSEL|wsGT, 14, 74, 60, 10, 105, "ＤＢ定義(&F)" },
    { C_BSEL|ws_,  78, 74, 60, 10, 106, "一括処理(&X)" },
    { C_BSEL|ws_, 142, 74, 60, 10, 107, "帳票作成(&R)" },
    { C_SLFT|wsG,   8,100, 48,  8, 108, "名　前(&A):" },
    { C_ESTR|wsT,  56, 98, 48, 12, 109, "" },
    { C_SLFT|wsG,   8,116, 48,  8, 110, "タイトル(&T):" },
    { C_ESTR|wsT,  56,114, 96, 12, 111, "" },
    { C_SLFT|wsG,   8,132, 48,  8, 112, "説　明(&D):" },
    { C_ESTR|wsT,  56,130,162, 12, 113, "" },
    { C_BDEF|wsGT,134,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 186,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 240, 176, "新規作成" };

  dit[0].txt = guidstr;
  par.cmd = CMD_NEW; par.pro = PRO_DEF; par.nam[0] = par.tit[0] = par.dsc[0] = '\0';
 _00:
  if (DlgBoxInput(hwnd, &dlg, new_DlgProc, (iANY)&par) == IDCANCEL) {
    PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0); return;
  }
  switch (par.cmd) {
  case CMD_NEW:
    if (par.nam[0] == '\0') { ErrorBox(hwnd, "名前が必要です。", NULL); goto _00;}
    if (!isidn(par.nam)) { ErrorBox(hwnd, "この名前は使用できません。", NULL); goto _00;}
    cri.tit = addext(par.nam, ".C");
    cri.id = SendMessage(hwnd, FRMM_GETNEWID, IDPRN + 1, 0);
    cri.pa = (U4B)CreateTMP((pPROI)&par.pro); if (cri.pa == 0) return;
    SendMessage(hwnd, FRMM_CREATECHILD, (uANY)&cri, (iANY)TXT_WndProc);
    break;
  case CMD_EDI:
    cmd_tedit(hwnd);
    break;
  case CMD_COM:
    cmd_compile(hwnd);
    break;
  }
}

  // バイトコード選択情報
typedef struct {
  HTBL  tb;
  I4B   ir;
  I4B   md;
} BCDP;

#define  IDBACK  25

BOOL LOCALF selbcd_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // バイトコード選択ダイアログプロシージャ
  BCDP *pa;
  static TBCI tci = { 10, "nam, tit, dsc", NULL, NULL, TTF_ADJ, 2, 0 };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (BCDP *)lpa));
    if (pa->ir >= NTableRows(pa->tb)) { pa->ir = 0;}
    SetTSEL(hdlg, 101, pa->ir, pa->tb, &tci);
    if (pa->md) {
      SetBFLG(hdlg, 102, pa->md == OM_RDO);
      SetBFLG(hdlg, 103, FALSE);
      EnableDlgItem(hdlg, 102, pa->md == OM_RDW);
      EnableDlgItem(hdlg, 103, pa->md == OM_RDW);
    }
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (BCDP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 102:
      if (GetBFLG(hdlg, 102)) {
        SetBFLG(hdlg, 103, FALSE); EnableDlgItem(hdlg, 103, FALSE);
      } else {
        EnableDlgItem(hdlg, 103, pa->md == OM_RDW);
      }
      break;
    case MKU4B(101, APPN_LBUTTONDBLCLK): wpa = IDOK;
    case IDOK:
      if (NTableRows(pa->tb) > 0) { pa->ir = GetTSEL(hdlg, 101);} else { wpa = IDCANCEL;}
      if (pa->md) {
        pa->md = (GetBFLG(hdlg, 102)? OM_RDO: OM_RDW) | (GetBFLG(hdlg, 103)? OM_LCK: 0);
      }
      // fall through
    case IDCANCEL:
    case IDBACK:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_open(HWND hwnd, BOOL sw)
{ // 開く
  I4B re;
  HWND hchi;
  static TBWI tbw;
  // データベースを開く
  static BCDP par0;
  static DLGI dit0[] = {
    { C_SLFT|wsG,   8,  8, 48,  8,  -1, "データベース" },
    { C_TSEL|wsT,   8, 18,272,116, 101, "" },
    { C_BDEF|wsGT,182,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 234,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg0 = { dit0, _countof(dit0), 0, 0, 288, 176, "データベースを開く" };
  // 表を開く
  static BCDP par1;
  static DLGI dit1[] = {
    { C_SLFT|wsG,   8,  8, 48,  8,  -1, "表" },
    { C_TSEL|wsT,   8, 18,272,116, 101, "" },
    { C_BFLG|wsGT,  8,136, 88, 10, 102, "読取専用で開く(&O)" },
    { C_BFLG|wsGT, 96,136, 88, 10, 103, "ファイルをロックする(&L)" },
    { C_BPSH|wsGT,  8,156, 48, 14, IDBACK, "戻る(&B)" }, // 4
    { C_BDEF|wsT, 182,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 234,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg1 = { dit1, _countof(dit1), 0, 0, 288, 176, "表を開く" };

  par1.md = (CurAuth() >= 2)? OM_RDW: OM_RDO;
  if (CurDBName()[0] == '\0') { _00:
    par0.tb = CreateBSDTable(32, PRO_DEF); if (!par0.tb) return;
    if (NTableRows(par0.tb) == 0) {
      ErrorBox(hwnd, "ＤＢ定義プロシージャが登録されていません。", NULL); { re = FALSE; goto _10;}
    }
    if (DlgBoxInput(hwnd, &dlg0, selbcd_DlgProc, (iANY)&par0) == IDCANCEL) { re = FALSE; goto _10;}
    re = ConnectDB((rSTR)TableRow(par0.tb, par0.ir));
    if (!re) {
      ErrorBox(hwnd, "データベースへの接続に失敗しました。", NULL);
    }
   _10: DeleteTable(par0.tb);
    if (!re) goto _30;
    dit1[4].sty &=~wsD; par1.ir = 0;
  } else {
    if (sw && (IniDat.uopt & UOPT_AOP) && IniDat.onam[0] != '\0') {
      par1.ir = DBTableIndex(IniDat.onam); goto _20;
    } else if (!sw && !(IniDat.uopt & UOPT_ACN) && !(AppStatus(hwnd) & APPS_ACT)) {
      DisconnectDB(); goto _00;
    }
    dit1[4].sty |= wsD;
  }
  par1.tb = CreateBDDTable(32, TRUE); if (!par1.tb) return;
  re = DlgBoxInput(hwnd, &dlg1, selbcd_DlgProc, (iANY)&par1);
  DeleteTable(par1.tb);
  if (re == IDCANCEL) goto _30; else if (re == IDBACK) { DisconnectDB(); goto _00;}
 _20:
  tbw.tit = DBTableTitle(par1.ir); tbw.vs = DBTableVIWS(par1.ir);
  if (!!(hchi = (HWND)SendMessage(hwnd, FRMM_GETCHILDBYNAME, (uANY)tbw.tit, 0))) {
    ErrorBox(hwnd, "同名のファイルを既に開いています。", NULL);
    SendMessage(hwnd, FRMM_ACTIVATE, (uANY)hchi, 0); return;
  }
  BusyMsg(hwnd, "読込中...");
  reset_error();
  tbw.op = OpenTable(DBTableName(par1.ir), par1.md);
  EndBusy(hwnd);
  if (!tbw.op) {
    ErrorBox(hwnd, format("'%s'の読込に失敗しました。", tbw.tit), NULL);
   _30: PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0); return;
  }
  CreateTableWindow(hwnd, 0, &tbw);
}

void LOCALF cmd_execute(HWND hwnd)
{ // 一括処理
  static BCDP par;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8, 48,  8,  -1, "一括処理" },
    { C_TSEL|wsT,   8, 18,272,116, 101, "" },
    { C_BDEF|wsGT,182,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 234,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 288, 176, "一括処理" };

  par.tb = CreateBSDTable(32, PRO_OPR); if (!par.tb) return;
  if (NTableRows(par.tb) == 0) {
    ErrorBox(hwnd, "一括処理プロシージャが登録されていません。", NULL); goto _10;
  }
  if (DlgBoxInput(hwnd, &dlg, selbcd_DlgProc, (iANY)&par) == IDCANCEL) goto _10;
  reset_error();
  CallCommandMain((rSTR)TableRow(par.tb, par.ir), hwnd);
 _10: DeleteTable(par.tb);
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

void LOCALF cmd_report(HWND hwnd)
{ // 帳票作成
  HWND hprn;
  static BCDP par;
  static REPI rpi = { NULL, PSZ_A4P, CallReportMain, 0 };
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8, 48,  8,  -1, "帳票作成" },
    { C_TSEL|wsT,   8, 18,272,116, 101, "" },
    { C_BDEF|wsGT,182,156, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 234,156, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 288, 176, "帳票作成" };

  par.tb = CreateBSDTable(32, PRO_REP); if (!par.tb) return;
  if (NTableRows(par.tb) == 0) {
    ErrorBox(hwnd, "帳票作成プロシージャが登録されていません。", NULL); goto _10;
  }
  if (DlgBoxInput(hwnd, &dlg, selbcd_DlgProc, (iANY)&par) == IDCANCEL) goto _10;
  reset_error();
  if (!LoadReportBCD((rSTR)TableRow(par.tb, par.ir))) { _10:
    DeleteTable(par.tb);
    PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0); return;
  }
  rpi.tit = stostr(((pBSDI)TableRow(par.tb, par.ir))->tit);
  DeleteTable(par.tb);
  hprn = CreatePrintPreview(hwnd, &rpi);
  if (!hprn) { PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);}
}

BOOL LOCALF who_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // ログイン状況等ダイアログプロシージャ
  switch (umsg) {
  case WM_INITDIALOG:
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    switch (wpa) {
    case IDOK:
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_who(HWND hwnd, BOOL sw)
{ // ＤＢへの接続状況、ファイルのロック状況を表示／サイトへのログイン状況を表示
  static DLGI dit[] = {
    { C_SMUL|wsG,   8,  8,192, 80,  -1, NULL },
    { C_BDEF|wsGT,154,108, 48, 14, IDOK, "OK" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 208, 128, NULL };

  if (sw == 0) {
    dit[0].txt = dbwhostr(); dlg.tit =  "ＤＢ接続状況";
  } else {
    dit[0].txt = sitewhostr(); dlg.tit = "ログイン状況";
  }
  DlgBoxInput(hwnd, &dlg, who_DlgProc, (iANY)NULL);
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

void LOCALF cmd_setusr(HWND hwnd)
{ // ユーザー管理表を開く
  static TBWI tbw = { NULL, 0, "ユーザー管理表", NULL, 0 };

  BusyMsg(hwnd, "読込中...");
  reset_error();
  tbw.op = OpenBSATable(OM_RDW);
  EndBusy(hwnd);
  if (!tbw.op) {
    ErrorBox(hwnd, format("'%s'の読込に失敗しました。", tbw.tit), NULL);
    PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0); return;
  }
  CreateTableWindow(hwnd, 0, &tbw);
}

HBLK LOCALF CreateEnmBlk(HTBL tb, I4B ic)
{ // 文字列リストの作成
  I4B i, ni, ofs;
  pENMS ls;

  ni = NTableRows(tb) + 1;
  ls = (pENMS)CreateMemBlk(ni, sizeof(rSTR)); if (!ls) return NULL;
  ls->ps[0] = "";
  ofs = TableColumnOffset(tb, ic);
  for (i = 1; i < ni; i++) {
    ls->ps[i] = (rSTR)((pBIN)TableRow(tb, i - 1) + ofs);
  }
  ls->ni = ni;
  return (HBLK)ls;
}

  // ロック解除情報
typedef struct {
  HBLK  ls;
  I4B   va;
} UNLP;

BOOL LOCALF unlock_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // ロック解除ダイアログプロシージャ
  UNLP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (UNLP *)lpa));
    SetCSEL(hdlg, 101, pa->va, (rENMS)pa->ls);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (UNLP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      pa->va = GetCSEL(hdlg, 101);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_unlock(HWND hwnd)
{ // ファイルのロック解除(ユーザーの強制ログアウト)
  I4B re;
  HTBL tb;
  UNLP par;
  I1B usr[32];
  static DLGI dit[] = {
    { C_SMUL|wsG,   8,  8,144, 24,  -1, "ユーザーを強制的にログアウトさせて\nファイルのロック状態を解除します。" },
    { C_SLFT|wsG,   8, 42, 40,  8,  -1, "ユーザー名:" },
    { C_CSEL|wsT,  48, 40,100,128, 101, "" },
    { C_BDEF|wsGT, 54,108, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 106,108, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 128, "ロック解除" };

  if (file_size(addext(SiteName(), ".BSU")) == 0) goto _10;
  tb = CreateBSUTable(32, TRUE); if (!tb) return;
  par.ls = CreateEnmBlk(tb, 0); if (!par.ls) { DeleteTable(tb); return;}
  par.va = 0;
  re = (DlgBoxInput(hwnd, &dlg, unlock_DlgProc, (iANY)&par) == IDOK);
  strcpyn(usr, enmstr((pENMS)par.ls, par.va), sizeof(usr) - 1); if (usr[0] == '\0') { re = FALSE;}
  DeleteBinBlk(par.ls);
  DeleteTable(tb);
  if (!re) goto _10;
  if (!strcmp(usr, CurUser())) {
    if (YesNoBox(hwnd, "自分自身を強制ログアウト（プログラムを終了）しますか？", NULL) == IDYES) {
      ForceLogoutSite(usr);
      PostMessage(hwnd, WM_COMMAND, IDM_EXIT, 0); return;
    }
    goto _10;
  }
  ForceLogoutSite(usr);
  OkBox(hwnd, format("'%s'を強制ログアウトさせました。", usr), NULL);
 _10:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

  // ファイル転送情報
typedef struct {
  I4B   cmd;
  I4B   pro;
  HBLK  ls1;
  HBLK  ls2;
  HBLK  ls3;
  I4B   va;
  pSTR  dir;
} BKUP;

BOOL LOCALF backup_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // ファイル転送ダイアログプロシージャ
  BKUP *pa;
  rENMS ls;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (BKUP *)lpa));
    SetBSEL(hdlg, 101, pa->cmd != 2);
    SetBSEL(hdlg, 102, pa->cmd == 2);
    SetBSEL(hdlg, 103, pa->pro <= 1);
    SetBSEL(hdlg, 104, pa->pro == 2);
    SetBSEL(hdlg, 105, pa->pro == 3);
    ls = (rENMS)(GetBSEL(hdlg, 103)? pa->ls1: GetBSEL(hdlg, 104)? pa->ls2: pa->ls3);
    SetCSEL(hdlg, 106, 0, (rENMS)ls);
    SetESTR(hdlg, 107, pa->dir);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (BKUP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 103:
    case 104:
    case 105:
      ls = (rENMS)(GetBSEL(hdlg, 103)? pa->ls1: GetBSEL(hdlg, 104)? pa->ls2: pa->ls3);
      SetCSEL(hdlg, 106, 0, (rENMS)ls);
      break;
    case IDOK:
      pa->cmd = GetBSEL(hdlg, 101)? 1: 2;
      pa->pro = GetBSEL(hdlg, 103)? 1: GetBSEL(hdlg, 104)? 2: 3;
      pa->va = GetCSEL(hdlg, 106);
      GetESTR(hdlg, 107, pa->dir, sizeof(IniDat.bdir) - 1);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_backup(HWND hwnd)
{ // ファイル転送
  I4B re = FALSE;
  HTBL tb1, tb2, tb3;
  rENMS ls;
  I1B nam[32];
  static BKUP par = { 1, 1, NULL, NULL, NULL, 0, IniDat.bdir };
  static DLGI dit[] = {
    { C_BGRP|wsG,   6,  6,212, 24,  -1, "処理選択" },
    { C_BSEL|wsGT, 14, 16, 60, 10, 101, "バックアップ(&B)" },
    { C_BSEL|ws_,  78, 16, 60, 10, 102, "移　動(&M)" },
    { C_BGRP|wsG,   6, 34,212, 24,  -1, "対象ファイル" },
    { C_BSEL|wsGT, 14, 44, 60, 10, 103, "データベース(&D)" },
    { C_BSEL|ws_,  78, 44, 60, 10, 104, "一括処理(&X)" },
    { C_BSEL|ws_, 142, 44, 60, 10, 105, "帳票作成(&R)" },
    { C_SLFT|wsG,   8, 70, 48,  8,  -1, "名　前(&N):" },
    { C_CSEL|wsT,  56, 68, 58,128, 106, "" },
    { C_SLFT|wsG,   8, 88, 80,  8,  -1, "転送先フォルダ(&F):" },
    { C_ESTR|wsT,   8, 98,226, 12, 107, "" },
    { C_BDEF|wsGT,134,140, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 186,140, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 240, 160, "ファイル転送" };

  DisconnectDB();
  tb1 = CreateBSDTable(32, PRO_DEF); if (!tb1) return;
  tb2 = CreateBSDTable(32, PRO_OPR); if (!tb2) goto _50;
  tb3 = CreateBSDTable(32, PRO_REP); if (!tb3) goto _40;
  par.ls1 = CreateEnmBlk(tb1, 0); if (!par.ls1) goto _30;
  par.ls2 = CreateEnmBlk(tb2, 0); if (!par.ls2) goto _20;
  par.ls3 = CreateEnmBlk(tb3, 0); if (!par.ls3) goto _10;
 _00:
  re = (DlgBoxInput(hwnd, &dlg, backup_DlgProc, (iANY)&par) == IDOK);
  ls = (rENMS)((par.pro == 1)? par.ls1: (par.pro == 2)? par.ls2: par.ls3);
  strcpyn(nam, enmstr(ls, par.va), sizeof(nam) - 1); if (nam[0] == '\0') { re = FALSE;}
  if (re && par.dir[0] == '\0') {
    ErrorBox(hwnd, "転送先フォルダが必要です。", NULL); goto _00;
  }
  DeleteBinBlk(par.ls3); _10:
  DeleteBinBlk(par.ls2); _20:
  DeleteBinBlk(par.ls1); _30:
  DeleteTable(tb3); _40:
  DeleteTable(tb2); _50:
  DeleteTable(tb1);
  if (!re) goto _60;
  BusyMsg(hwnd, "処理中...");
  reset_error();
  switch (par.pro) {
  case 1:
    re = ConnectDB(nam); if (!re) break;
    re = ((par.cmd == 1)? BackupDBFiles: TrashDBFiles)(par.dir);
    DisconnectDB();
    break;
  case 2:
  case 3:
    re = ((par.cmd == 1)? copy_file_to: move_file_to)(par.dir, addext(nam, BCDExt(par.pro)));
    break;
  }
  EndBusy(hwnd);
  ResultBox(hwnd, "ファイル転送", NULL, re);
 _60:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

void LOCALF cmd_compile(HWND hwnd)
{ // コンパイル
  I4B re;
  static CPLP par;
  static CPLI cpi = { "BOLYAI_C.H", par.sfn, NULL, NULL, IAPP, 0, par.tit, par.dsc, };

 _00:
  if (!CompileDlgBox(hwnd, &par, 1)) goto _10;
  if (par.sfn[0] == '\0') { ErrorBox(hwnd, "ソースコード名が必要です。", NULL); goto _00;}
  if (par.nam[0] == '\0') { strcpyn(par.nam, basnamx(par.sfn), sizeof(par.nam) - 1);}
  if (par.tit[0] == '\0') { strcpyn(par.tit, par.nam, sizeof(par.tit) - 1);}
  cpi.ofn = addext(par.nam, BCDExt(par.pro));
  cpi.mai = BCDMain(par.pro);
  cpi.pro = par.pro;
  BusyMsg(hwnd, "処理中...");
  reset_error();
  re = CompileBCD(&cpi);
  EndBusy(hwnd);
  ResultBox(hwnd, "コンパイル", NULL, re);
 _10:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

#define  EXT_TXT  2
#define  EXT_DIB  3

I4B  LOCALF ext_type(rSTR nam)
{ // ファイル名の拡張子でファイル形式を判別
  I4B i;
  static rSTR ex2[] = { ".txt", ".c", ".cpp", ".h", ".ini", ".log" };
  static rSTR ex3[] = { ".bmp", ".dib", ".jpg", ".jpeg", ".jpe", ".jfif", ".tif", ".tiff", ".gif", ".png" };

  for (i = 0; i < _countof(ex2); i++) {
    if (strirfind(nam, ex2[i])) { return EXT_TXT;}
  }
  for (i = 0; i < _countof(ex3); i++) {
    if (strirfind(nam, ex3[i])) { return EXT_DIB;}
  }
  return 0;
}

void LOCALF cmd_tedit(HWND hwnd)
{ // テキスト編集
  I4B re;
  HWND hchi;
  WNDPROC prc;
  STRBUF nam, bak;
  static CREI cri = { NULL, wsCHV, };
  static OFNS ofn = { TFILTER, 1, NULL, OFN_HIDEREADONLY };

  if (CurAuth() < 2) { cri.sty |= TXCS_DED;}
  get_working_path(bak, sizeof(bak));
  (ofn.nam = nam)[0] = '\0';
  re = OpenFileDlgBox(hwnd, &ofn);
  set_working_path(bak);
  if (!re) {
    if (!(AppStatus(hwnd) & APPS_ACT)) { PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);}
    return;
  }
  if (!!(hchi = (HWND)SendMessage(hwnd, FRMM_GETCHILDBYNAME, (uANY)basnam(nam), 0))) {
    ErrorBox(hwnd, "同名のファイルを既に開いています。", NULL);
    SendMessage(hwnd, FRMM_ACTIVATE, (uANY)hchi, 0); return;
  }
  cri.tit = nam;
  cri.id = SendMessage(hwnd, FRMM_GETNEWID, IDPRN + 1, 0);
  switch (ext_type(nam)) {
  case EXT_TXT:
    BusyMsg(hwnd, "読込中...");
    reset_error();
    cri.pa = (U4B)LoadTXT(NULL, nam);
    EndBusy(hwnd);
    if (cri.pa == 0) return;
    cri.cls = "BOLTXT"; prc = TXT_WndProc;
    break;
  case EXT_DIB:
    BusyMsg(hwnd, "読込中...");
    reset_error();
    cri.pa = (U4B)LoadJPG(NULL, nam);
    EndBusy(hwnd);
    if (cri.pa == 0) return;
    cri.cls = "BOLDIB"; prc = DIB_WndProc;
    break;
  default:
    ErrorBox(hwnd, "このファイル形式はサポートしていません。", NULL); return;
  }
  SendMessage(hwnd, FRMM_CREATECHILD, (uANY)&cri, (iANY)prc);
}

BOOL LOCALF setenv_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 環境設定ダイアログプロシージャ
  ENVD *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (ENVD *)lpa));
    SetESTR(hdlg, 101, pa->snam);
    SetESTR(hdlg, 102, pa->stit);
    SetESTR(hdlg, 103, pa->sdsc);
    SetEDBL(hdlg, 104, pa->rtax * 100.0);
    SetEINT(hdlg, 105, pa->fymn);
    SetEINT(hdlg, 106, pa->nmfy);
    SetESTR(hdlg, 107, pa->udir);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (ENVD *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetESTR(hdlg, 101, pa->snam, sizeof(pa->snam) - 1);
      GetESTR(hdlg, 102, pa->stit, sizeof(pa->stit) - 1);
      GetESTR(hdlg, 103, pa->sdsc, sizeof(pa->sdsc) - 1);
      pa->rtax = GetEDBL(hdlg, 104) / 100.0; if (pa->rtax <= 0.0 || pa->rtax > 1.0) { pa->rtax = TaxRate();}
      pa->fymn = GetEINT(hdlg, 105); if (pa->fymn <= 0 || pa->fymn > 12) { pa->fymn = FYearMonth();}
      pa->nmfy = GetEINT(hdlg, 106); if (pa->nmfy <= 0 || pa->nmfy > 18) { pa->nmfy = NMonthFYear();}
      GetESTR(hdlg, 107, pa->udir, sizeof(pa->udir) - 2);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_setenv(HWND hwnd)
{ // 環境設定
  ENVD par;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 48,  8,  -1, "サイト名(&N):" },
    { C_ESTR|wsT,  56,  8, 48, 12, 101, "" },
    { C_SLFT|wsG,   8, 26, 48,  8,  -1, "タイトル(&T):" },
    { C_ESTR|wsT,  56, 24, 96, 12, 102, "" },
    { C_SLFT|wsG,   8, 42, 48,  8,  -1, "説　明(&D):" },
    { C_ESTR|wsT,  56, 40,162, 12, 103, "" },
    { C_SLFT|wsG,   8, 58, 48,  8,  -1, "消費税率(&C):" },
    { C_ENUM|wsT,  56, 56, 24, 12, 104, "" },
    { C_SLFT|wsG,  81, 58, 16,  8,  -1, "％" },
    { C_SLFT|wsG,   8, 74, 48,  8,  -1, "事業年度(&F):" },
    { C_ENUM|wsT,  56, 72, 24, 12, 105, "" },
    { C_SLFT|wsG,  81, 74, 24,  8,  -1, "月開始" },
    { C_ENUM|wsT, 106, 72, 24, 12, 106, "" },
    { C_SLFT|wsG, 131, 74, 24,  8,  -1, "ヶ月" },
    { C_SLFT|wsG,   8, 90, 80,  8,  -1, "ユーザーフォルダ(&U):" },
    { C_ESTR|wsT,   8,100,226, 12, 107, "" },
    { C_BDEF|wsGT,134,140, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 186,140, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 240, 160, "環境設定" };

  par = EnvDat;
  if (DlgBoxInput(hwnd, &dlg, setenv_DlgProc, (iANY)&par) == IDCANCEL) goto _10;
  if (_stricmp(par.snam, EnvDat.snam) != 0) {
    move_file(addext(par.snam, ".BSA"), addext(EnvDat.snam, ".BSA"));
    move_file(addext(par.snam, ".BSU"), addext(EnvDat.snam, ".BSU"));
    move_file(addext(par.snam, ".LOG"), addext(EnvDat.snam, ".LOG"));
  }
  EnvDat = par;
  SaveENV();
 _10:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

  // オプション設定情報
typedef struct {
  I1B   face[32];
  I4B   ptsz;
  I4B   tbcs;
  I4B   cptr;
  I4B   cidx;
  I4B   uopt;
  I1B   unam[32];
  I1B   upwd[32];
  I1B   cnam[16];
  I1B   onam[16];
} OPTP;

BOOL LOCALF setopt_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // オプション設定ダイアログプロシージャ
  I4B sw;
  OPTP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (OPTP *)lpa));
    SetESTR(hdlg, 101, pa->face);
    SetEINT(hdlg, 102, pa->ptsz);
    SetCCOD(hdlg, 103, pa->tbcs & TBCS_HRH, &dsHRH);
    SetCCOD(hdlg, 104, pa->tbcs & (TBCS_HCH|TBCS_UCI|TBCS_UCN), &dsHCH);
    SetEITM(hdlg, 105, &pa->cptr, &ciCPTR);
    SetEITM(hdlg, 106, &pa->cidx, &ciCIDX);
    SetBFLG(hdlg, 107, pa->tbcs & TBCS_EMD);
    SetBFLG(hdlg, 108, pa->tbcs & TBCS_ZBI);
    SetBFLG(hdlg, 109, pa->tbcs & TBCS_DDD);
    SetBFLG(hdlg, 110, pa->tbcs & TBCS_DER);
    SetBFLG(hdlg, 111, pa->uopt & UOPT_ALI);
    SetSSTR(hdlg, 113, pa->unam);
    SetBFLG(hdlg, 114, pa->uopt & UOPT_UMD);
    SetBFLG(hdlg, 115, sw = ((pa->uopt & UOPT_ACN) && pa->cnam[0] != '\0'));
    SetSSTR(hdlg, 117, pa->cnam);
    SetBFLG(hdlg, 118, (pa->uopt & UOPT_AOP) && pa->onam[0] != '\0');
    SetSSTR(hdlg, 120, pa->onam);
    SetBFLG(hdlg, 121, pa->uopt & UOPT_ELG);
    EnableDlgItem(hdlg, 115, pa->cnam[0] != '\0');
    EnableDlgItem(hdlg, 116, pa->cnam[0] != '\0');
    EnableDlgItem(hdlg, 117, pa->cnam[0] != '\0');
    EnableDlgItem(hdlg, 118, sw && pa->onam[0] != '\0');
    EnableDlgItem(hdlg, 119, sw && pa->onam[0] != '\0');
    EnableDlgItem(hdlg, 120, sw && pa->onam[0] != '\0');
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (OPTP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 115:
      if (!(sw = GetBFLG(hdlg, 115))) { SetBFLG(hdlg, 118, FALSE);}
      EnableDlgItem(hdlg, 118, sw && pa->onam[0] != '\0');
      EnableDlgItem(hdlg, 119, sw && pa->onam[0] != '\0');
      EnableDlgItem(hdlg, 120, sw && pa->onam[0] != '\0');
      break;
    case IDOK:
      GetESTR(hdlg, 101, pa->face, sizeof(pa->face) - 1);
      if (pa->face[0] == '\0') { strcpyx(pa->face, DEFFACE, sizeof(pa->face) - 1);}
      pa->ptsz = GetEINT(hdlg, 102); if (pa->ptsz < 6 || pa->ptsz > 30) { pa->ptsz = DEFPTSZ;}
      pa->tbcs = (pa->tbcs &~TBCS_HRH) | GetCCOD(hdlg, 103, &dsHRH);
      pa->tbcs = (pa->tbcs &~(TBCS_HCH|TBCS_UCI|TBCS_UCN)) | GetCCOD(hdlg, 104, &dsHCH);
      GetEITM(hdlg, 105, &pa->cptr, &ciCPTR); if (pa->cptr == 0) { pa->cptr = BGRC_PTR;}
      GetEITM(hdlg, 106, &pa->cidx, &ciCIDX); if (pa->cidx == 0) { pa->cidx = BGRC_IDX;}
      if (GetBFLG(hdlg, 107)) { pa->tbcs |= TBCS_EMD;} else { pa->tbcs &=~TBCS_EMD;}
      if (GetBFLG(hdlg, 108)) { pa->tbcs |= TBCS_ZBI;} else { pa->tbcs &=~TBCS_ZBI;}
      if (GetBFLG(hdlg, 109)) { pa->tbcs |= TBCS_DDD;} else { pa->tbcs &=~TBCS_DDD;}
      if (GetBFLG(hdlg, 110)) { pa->tbcs |= TBCS_DER;} else { pa->tbcs &=~TBCS_DER;}
      if (GetBFLG(hdlg, 111)) { pa->uopt |= UOPT_ALI;} else { pa->uopt &=~UOPT_ALI;}
      if (GetBFLG(hdlg, 114)) { pa->uopt |= UOPT_UMD;} else { pa->uopt &=~UOPT_UMD;}
      if (GetBFLG(hdlg, 115)) { pa->uopt |= UOPT_ACN;} else { pa->uopt &=~UOPT_ACN;}
      if (GetBFLG(hdlg, 118)) { pa->uopt |= UOPT_AOP;} else { pa->uopt &=~UOPT_AOP;}
      if (GetBFLG(hdlg, 121)) { pa->uopt |= UOPT_ELG;} else { pa->uopt &=~UOPT_ELG;}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_setopt(HWND hwnd)
{ // オプション設定
  OPTP par;
  LOGFONT lof;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 48,  8,  -1, "フォント(&F):" },
    { C_ESTR|wsT,  56,  8, 66, 12, 101, "" },
    { C_ENUM|wsT, 128,  8, 24, 12, 102, "" },
    { C_SLFT|wsG, 155, 10, 16,  8,  -1, "pt" },
    { C_SLFT|wsG,   8, 26, 48,  8,  -1, "行見出し(&R):" },
    { C_CSEL|wsT,  56, 24, 58,128, 103, "" },
    { C_SLFT|wsG,   8, 42, 48,  8,  -1, "列見出し(&C):" },
    { C_CSEL|wsT,  56, 40, 58,128, 104, "" },
    { C_SLFT|wsG, 128, 26, 60,  8,  -1, "セルポインタ色(&P):" },
    { C_ENUM|wsT, 188, 24, 40, 12, 105, "" },
    { C_SLFT|wsG, 128, 42, 60,  8,  -1, "見出しハイライト(&H):" },
    { C_ENUM|wsT, 188, 40, 40, 12, 106, "" },
    { C_BFLG|wsGT,  8, 60,120, 10, 107, "Enterキーで下に移動する(&D)" },
    { C_BFLG|wsGT,  8, 74,120, 10, 108, "インデックスを0から始める(&Z)" },
    { C_BFLG|wsGT,128, 60,128, 10, 109, "ドロップダウンリストを使用しない(&L)" },
    { C_BFLG|wsGT,128, 74,128, 10, 110, "ダイアログボックスを使用しない(&E)" },
    { C_BFLG|wsGT,  8, 92,120, 10, 111, "自動的にログインする(&A)" },
    { C_SLFT|wsG, 128, 93, 44,  8, 112, "ユーザー名:" },
    { C_SLFT|wsG, 172, 93, 84,  8, 113, "" },
    { C_BFLG|wsGT,  8,106,120, 10, 114, "開始メニューを使用する(&M)" },
    { C_BFLG|wsGT,  8,120,120, 10, 115, "自動的にＤＢに接続する(&N)" },
    { C_SLFT|wsG, 128,121, 28,  8, 116, "ＤＢ名:" },
    { C_SLFT|wsG, 156,121, 48,  8, 117, "" },
    { C_BFLG|wsGT,  8,134,120, 10, 118, "自動的に表を開く(&O)" },
    { C_SLFT|wsG, 128,135, 28,  8, 119, "表　名:" },
    { C_SLFT|wsG, 156,135, 48,  8, 120, "" },
    { C_BFLG|wsGT,  8,148,120, 10, 121, "エラーログを残す(&G)" },
    { C_BDEF|wsGT,150,172, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 202,172, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 256, 192, "オプション設定" };

  par = *(OPTP *)&IniDat.face;
  if (DlgBoxInput(hwnd, &dlg, setopt_DlgProc, (iANY)&par) == IDCANCEL) goto _10;
  reset_error();
  if (par.ptsz != IniDat.ptsz || strcmp(par.face, IniDat.face) != 0) {
    SetAppFont(FID_DEF, CreateFontIndirect(SetLOGFONT(&lof, par.face, PT2DOTS(par.ptsz), 0)));
  }
  set_error_message_index_base(!(par.tbcs & TBCS_ZBI));
  SetAppColor(CID_PTR, par.cptr);
  SetAppColor(CID_IDX, par.cidx);
  if (par.uopt & UOPT_ELG) { enable_error_logging();} else { disable_error_logging();}
  *(OPTP *)&IniDat.face = par;
 _10:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

BOOL LOCALF setdate_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 計算日設定ダイアログプロシージャ
  pI4B pa;
  static COLI co0 = { TID_YMD,  0, "ymd", };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (pI4B)lpa));
    SetEITM(hdlg, 101, pa, &co0);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (pI4B)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetEITM(hdlg, 101, pa, &co0); if (*pa == 0) { *pa = today();}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_setdate(HWND hwnd)
{ // 計算日設定
  I4B sr;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 48,  8,  -1, "計算日(&D):" },
    { C_ESTR|wsT,  56,  8, 56, 12, 101, "" },
    { C_BDEF|wsGT, 54, 60, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 106, 60, 48, 14, IDCANCEL, "キャンセル" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 80, "計算日設定" };

  sr = CurDate();
  if (DlgBoxInput(hwnd, &dlg, setdate_DlgProc, (iANY)&sr) == IDCANCEL) goto _10;
  SetCurDate(sr);
 _10:
  PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);
}

void LOCALF cmd_tile(HWND hwnd, I4B sw)
{ // 左右(上下)に並べて表示
  I4B flg;

  flg = SendMessage(hwnd, FRMM_GETFLAGS, 0, 0);
  flg &=~(FRMS_TIL|FRMS_HRZ|FRMS_RGT);
  switch (sw) {
  case 0: flg |= (FRMS_TIL|FRMS_VRT); break;
  case 1: flg |= (FRMS_TIL|FRMS_HRZ); break;
  }
  SendMessage(hwnd, FRMM_SETFLAGS, flg, 0);
  SendMessage(hwnd, FRMM_ARRANGE, OPR_TILE, 0);
}

void LOCALF cmd_window(HWND hwnd, I4B id)
{ // アクティブウィンドウ選択
  I4B nc;
  HWND hchi;

  nc = SendMessage(hwnd, FRMM_GETNCHILDREN, 0, 0);
  hchi = (HWND)SendMessage(hwnd, FRMM_GETCHILD, nc - 1 - id, 0);
  SendMessage(hwnd, FRMM_ARRANGE, OPR_ACTIVATE, (iANY)hchi);
}

void LOCALF cmd_manual(HWND hwnd)
{ // マニュアルを開く
  ShellExecute(NULL, "open", PRGNAM".PDF", NULL, NULL, SW_SHOWDEFAULT);
}

static HBMP hbmpMain;

rSTR LOCALF verstr(U4B ver)
{ // バージョン文字列
  rBIN vr = (rBIN)&ver; return format("Version %d.%d.%d", vr[0], vr[1], vr[2]);
}

BOOL LOCALF about_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // バージョン情報ダイアログプロシージャ
  switch (umsg) {
  case WM_INITDIALOG:
    SendDlgItemMessage(hdlg, 101, STM_SETIMAGE, IMAGE_BITMAP, (iANY)hbmpMain);
    SetSSTR(hdlg, 102, verstr(BOLALGVer()));
    SetSSTR(hdlg, 103, verstr(BOLBASVer()));
    SetSSTR(hdlg, 104, verstr(BOLCOMVer()));
    SetSSTR(hdlg, 105, verstr(BOLDBEVer()));
    SetSSTR(hdlg, 106, verstr(BOLEXTVer()));
    SetSSTR(hdlg, 107, verstr(BOLFROVer()));
    SetSSTR(hdlg, 108, verstr(BOLGUIVer()));
    SetSSTR(hdlg, 109, verstr(BOLPLSVer()));
    SetSSTR(hdlg, 110, verstr(MODVER));
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    switch (wpa) {
    case IDOK:
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

void LOCALF cmd_about(HWND hwnd)
{ // バージョン情報
  static DLGI dit[] = {
    { C_SBMP|wsG,   8, 10, 80, 80,101, ""       },
    { C_SLFT|wsG, 112, 10, 32,  8, -1, "BOLALG" },
    { C_SLFT|wsG, 144, 10, 56,  8,102, ""       },
    { C_SLFT|wsG, 112, 20, 32,  8, -1, "BOLBAS" },
    { C_SLFT|wsG, 144, 20, 56,  8,103, ""       },
    { C_SLFT|wsG, 112, 30, 32,  8, -1, "BOLCOM" },
    { C_SLFT|wsG, 144, 30, 56,  8,104, ""       },
    { C_SLFT|wsG, 112, 40, 32,  8, -1, "BOLDBE" },
    { C_SLFT|wsG, 144, 40, 56,  8,105, ""       },
    { C_SLFT|wsG, 112, 50, 32,  8, -1, "BOLEXT" },
    { C_SLFT|wsG, 144, 50, 56,  8,106, ""       },
    { C_SLFT|wsG, 112, 60, 32,  8, -1, "BOLFRO" },
    { C_SLFT|wsG, 144, 60, 56,  8,107, ""       },
    { C_SLFT|wsG, 112, 70, 32,  8, -1, "BOLGUI" },
    { C_SLFT|wsG, 144, 70, 56,  8,108, ""       },
    { C_SLFT|wsG, 112, 80, 32,  8, -1, "BOLPLS" },
    { C_SLFT|wsG, 144, 80, 56,  8,109, ""       },
    { C_SLFT|wsG,   8, 96, 96,  8, -1, PRGDSC   },
    { C_SLFT|wsG, 112, 96, 32,  8, -1, PRGNAM   },
    { C_SLFT|wsG, 144, 96, 56,  8,110, ""       },
    { C_SLFT|wsG,   8,126,144,  8, -1, VI_CPY   },
    { C_BDEF|wsGT,154,124, 48, 14, IDOK, "OK"   },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 208, 144, "バージョン情報" };

  DlgBoxInput(hwnd, &dlg, about_DlgProc, (iANY)NULL);
}

iANY LOCALF FRM_command(HWND hwnd, uANY wpa, iANY lpa)
{ // コマンド
  HWND hact, hchi;

  switch (LOU2B(wpa)) {
  case IDM_LOGIN:
    cmd_login(hwnd); break;
  case IDM_OMENU:
    cmd_omenu(hwnd, 0); break;
  case IDM_OMENU1:
    cmd_omenu(hwnd, 1); break;
  case IDM_NEW:
    cmd_new(hwnd); break;
  case IDM_OPEN:
    switch (AppStatus(hwnd) & APPS_ACT) {
    case APPS_TXT:
    case APPS_DIB: goto _10;
    }
    cmd_open(hwnd, 0); break;
  case IDM_OPEN1:
    cmd_open(hwnd, 1); break;
  case IDM_CLOSE:
    SendMessage((HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0), WM_CLOSE, 0, 0); break;
  case IDM_EXIT:
    SendMessage(hwnd, WM_CLOSE, 0, 0); return 0;
  case IDM_EXECUTE:
    cmd_execute(hwnd); break;
  case IDM_REPORT:
    cmd_report(hwnd); break;
  case IDM_DBWHO:
    cmd_who(hwnd, 0); break;
  case IDM_SITEWHO:
    cmd_who(hwnd, 1); break;
  case IDM_SETUSR:
    cmd_setusr(hwnd); break;
  case IDM_UNLOCK:
    cmd_unlock(hwnd); break;
  case IDM_BACKUP:
    cmd_backup(hwnd); break;
  case IDM_COMPILE:
    switch (AppStatus(hwnd) & APPS_ACT) {
    case APPS_TXT: goto _20;
    }
    cmd_compile(hwnd); break;
  case IDM_TEDIT: _10:
    cmd_tedit(hwnd); break;
  case IDM_SETENV:
    cmd_setenv(hwnd); break;
  case IDM_SETOPT:
    cmd_setopt(hwnd); break;
  case IDM_SETDATE:
    cmd_setdate(hwnd); break;
  case IDM_PREVWINDOW:
    SendMessage(hwnd, FRMM_ARRANGE, OPR_ACTIVATE, 0); break;
  case IDM_NEXTWINDOW:
    SendMessage(hwnd, FRMM_ARRANGE, OPR_ACTIVATE, SendMessage(hwnd, FRMM_GETCHILD, 0, 0)); break;
  case IDM_MAXIMIZE:
    cmd_tile(hwnd, -1); break;
  case IDM_TILE:
    cmd_tile(hwnd, 0); break;
  case IDM_HTILE:
    cmd_tile(hwnd, 1); break;
  case IDM_WINDOW0:
  case IDM_WINDOW1:
  case IDM_WINDOW2:
  case IDM_WINDOW3:
  case IDM_WINDOW4:
  case IDM_WINDOW5:
  case IDM_WINDOW6:
  case IDM_WINDOW7:
  case IDM_WINDOW8:
  case IDM_WINDOW9:
  case IDM_WINDOWA:
  case IDM_WINDOWB:
  case IDM_WINDOWC:
  case IDM_WINDOWD:
  case IDM_WINDOWE:
  case IDM_WINDOWF:
    cmd_window(hwnd, LOU2B(wpa) - IDM_WINDOW0); break;
  case IDM_MANUAL:
    cmd_manual(hwnd); break;
  case IDM_ABOUT:
    cmd_about(hwnd); break;
  default: _20:
    hact = (HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0);
    if (LOU2B(wpa) >= IDPRN && LOU2B(wpa) < IDM_LOGIN) {
      switch (HIU2B(wpa)) {
      case APPN_SETFOCUS:
        break;
      case APPN_LBUTTONDOWN:
      case APPN_RBUTTONDOWN:
        if ((hchi = GetDlgItem(hwnd, LOU2B(wpa))) != hact) {
          SendMessage(hwnd, FRMM_ACTIVATE, (uANY)hchi, 0);
        }
        return 0;
      case APPN_SELCHANGE:
        break;
      default:
        return 0;
      }
    } else if (hact) {
      SendMessage(hact, WM_COMMAND, wpa, lpa);
    }
    break;
  }
  SendMessage(hwnd, FRMM_INITTOOL, 0, 0);
  return 0;
}

iANY LOCALF FRM_close(HWND hwnd)
{ // フレームウィンドウを閉じる
  HWND bact, hact;

  bact = NULL;
  while (!!(hact = (HWND)SendMessage(hwnd, FRMM_GETACTIVE, 0, 0))) {
    if (hact == bact) return 0;
    SendMessage(hact, WM_CLOSE, 0, 0);
    bact = hact;
  }
  SendMessage(hwnd, FRMM_GETPLACEMENT, (uANY)&IniDat.wpo, 0);
  return DefBOLFRMProc(hwnd, WM_CLOSE, 0, 0);
}

iANY LOCALF FRM_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // メインウィンドウプロシージャ
  switch (umsg) {
  case WM_INITMENU:
    return FRM_initmenu(hwnd, (HMENU)wpa);
  case FRMM_INITTOOL:
    return FRM_inittool(hwnd);
  case FRMM_DESTROYCHILD:
    DefBOLFRMProc(hwnd, umsg, wpa, lpa);
    if (!SendMessage(hwnd, FRMM_GETACTIVE, 0, 0)) { PostMessage(hwnd, WM_COMMAND, IDM_OMENU, 0);}
    return 0;
  case WM_COMMAND:
    return FRM_command(hwnd, wpa, lpa);
  case WM_CLOSE:
    return FRM_close(hwnd);
  }
  return DefBOLFRMProc(hwnd, umsg, wpa, lpa);
}

typedef struct {
  I4B   idm;
  I4B   bid;
} ICOI;
  // コマンドとビットマップの対応表
static ICOI ICI[] = {
  { IDM_NEW,        BID_NEW     },
  { IDM_OPEN,       BID_OPEN    },
  { IDM_CLOSE,      BID_CLOSE   },
  { IDM_SAVE,       BID_SAVE    },
  { IDM_SAVEAS,     BID_SAVEAS  },
  { IDM_PRINT,      BID_PRINT   },
  { IDM_CUT,        BID_CUT     },
  { IDM_COPY,       BID_COPY    },
  { IDM_PASTE,      BID_PASTE   },
  { IDM_SEARCH,     BID_SEARCH  },
  { IDM_VIEW,       BID_VIEW    },
  { IDM_ARRANGE,    BID_ARRANGE },
  { IDM_FILTER,     BID_FILTER  },
  { IDM_SORT,       BID_SORT    },
  { IDM_SUMMARY,    BID_SUMMARY },
  { IDM_CHECK,      BID_CHECK   },
  { IDM_EDIT,       BID_EDIT    },
  { IDM_ADDEDIT,    BID_ADD     },
  { IDM_INSERTEDIT, BID_INSERT  },
  { IDM_SELDELETE,  BID_DELETE  },
  { IDM_COMPILE,    BID_COMPILE },
  { IDM_PREVWINDOW, BID_PREVWIN },
  { IDM_NEXTWINDOW, BID_NEXTWIN },
  { IDM_PREVPAGE,   BID_PREV    },
  { IDM_NEXTPAGE,   BID_NEXT    },
  { IDM_SETPRN,     BID_SETUP   },
  { IDM_ZOOMIN,     BID_ZOOMIN  },
  { IDM_ZOOMOUT,    BID_ZOOMOUT },
  { IDM_SAMESCALE,  BID_SAME    },
  { IDM_AUTOSCALE,  BID_WHOLE   },
};

BOOL LOCALF InitBOLYAI(uANY pa)
{ // 開始処理
  I4B i;

  InitBOLALG(0);
  InitBOLBAS(0);
  InitBOLCOM(0);
  InitBOLDBE(0);
  InitBOLEXT(0);
  InitBOLFRO(0);
  InitBOLGUI(0);
  InitBOLPLS(0);
  for (i = 0; i < _countof(ICI); i++) {
    SetMenuItemDDB(ICI[i].idm, AppDDB(ICI[i].bid));
  }
  InitPopupMenus();
  PrepToolBar();
  RegisterAPIs(&fsBOL);
  RegisterFlowTextTags(&gsBOL);
  return TRUE;
}

void LOCALF TermBOLYAI(void)
{ // 終了処理
  LogoutSite();
  TermPopupMenus();
  TermBOLPLS();
  TermBOLGUI();
  TermBOLFRO();
  TermBOLEXT();
  TermBOLDBE();
  TermBOLCOM();
  TermBOLBAS();
  TermBOLALG();
}

I4B  WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, pSTR lpszCmdLine, I4B nCmdShow)
{ // メイン関数
  HWND hwnd;
  MSG msg;
  HACCEL haccMain;
  HICON hicoMain;
  static FRMI fin = { PRGTIT, &IniDat.wpo, &BOLMS, IDTOB, &BOLTS, IDSTB, &BOLSS };

  InitBOLYAI(0);
  LoadENV();
  if (lpszCmdLine[0] != '\0') { SetUserPath(lpszCmdLine);}
  new_path_if_not_exists(UserPath());
  set_error_log_file(adddir(UserPath(), addext(SiteName(), ".LOG")));
  LoadINI();
//  start_debug(TRUE);

  haccMain = LoadAccelerators(hInstance, PRGNAM"ACC");
  hicoMain = LoadIcon(hInstance, PRGNAM"ICO");
  hbmpMain = LoadBitmap(hInstance, PRGNAM"BMP");
  hwnd = CreateBOLFRMWindow(hInstance, &fin); if (!hwnd) return 0;
  SubclassWindow(hwnd, FRM_WndProc);
  SendMessage(hwnd, WM_SETICON, ICON_BIG, (iANY)hicoMain);
  ShowWindow(hwnd, (IniDat.wpo.mx && nCmdShow == SW_SHOWNORMAL)? SW_SHOWMAXIMIZED: SW_SHOWDEFAULT);
  UpdateWindow(hwnd);
  PostMessage(hwnd, WM_COMMAND, IDM_LOGIN, 0);

  while (GetMessage(&msg, NULL, 0, 0) > 0) {
    if (!TranslateAccelerator(hwnd, haccMain, &msg)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  SaveINI();
//  stop_debug();
  TermBOLYAI();

  return msg.wParam;
}

//――――――――――――――――――――――――――――――――――――――//
