/*乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//
    bolgui.c
//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗*/

#include <windows.h>
#include <commctrl.h>

#define  _USE_MATH_DEFINES
#include <math.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <bolalg.h>
#include <bolbas.h>
#include <boldbe.h>
#include <bolfro.h>
#include "bolgui.h"

#define  MODNAM  "BOLGUI"
#define  MODVER  OCTVAL(2,6,0,0)

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

void WINAPI SetEITM(HWND hdlg, I4B id, rANY pv, rCOLI co)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞愝掕(楍忣曬)
  I1B bf[LBUF];

  SetESTR(hdlg, id, ColumnPrint(bf, pv, co));
}

void WINAPI GetEITM(HWND hdlg, I4B id, pANY pv, rCOLI co)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞庢摼(楍忣曬)
  I1B bf[LBUF];

  GetESTR(hdlg, id, bf, sizeof(bf) - 1);
  SetEITM(hdlg, id, ColumnScan(pv, bf, co), co);
}

void WINAPI SetCITM(HWND hdlg, I4B id, rANY pv, rCOLI co)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞愝掕(楍忣曬)
  I4B i, i0 = -1, ni;
  rSTR st;
  I1B bf[LBUF];

  ni = ColumnList(-1, co);
  ColumnPrint(bf, pv, co);
  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  for (i = 0; i < ni; i++) {
    st = (rSTR)ColumnList(i, co);
    if (!strcmp(st, bf)) { i0 = i;}
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (iANY)st);
  }
  if (i0 >= 0) {
    SendDlgItemMessage(hdlg, id, CB_SETCURSEL, i0, 0);
  } else {
    SetESTR(hdlg, id, bf);
  }
}

void WINAPI GetCITM(HWND hdlg, I4B id, pANY pv, rCOLI co)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞庢摼(楍忣曬)
  I1B bf[LBUF];

  GetESTR(hdlg, id, bf, sizeof(bf) - 1);
  ColumnScan(pv, bf, co);
}

void WINAPI SetCTBL(HWND hdlg, I4B id, I4B va, HTBL tb, rTBBI tt)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞愝掕(昞)
  I4B i, i0 = 0, ni;
  HVIW vw;
  I1B bf[LBUF];

  vw = CreateView(tb, "*", tt->cnd, tt->srt); if (!vw) return;
  ni = NViewRows(vw);
  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (iANY)"");
  for (i = 0; i < ni; i++) {
    *(pI4B)bf = 0; GetViewCellValue(bf, vw, i, tt->icv);
    if (*(rI4B)bf == va) { i0 = i + 1;}
    PrintViewCellValue(bf, vw, i, tt->icn);
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (iANY)bf);
  }
  SendDlgItemMessage(hdlg, id, CB_SETCURSEL, i0, 0);
  DeleteView(vw);
}

I4B  WINAPI GetCTBL(HWND hdlg, I4B id, HTBL tb, rTBBI tt)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞庢摼(昞)
  I4B i, va = 0;
  HVIW vw;
  I1B bf[LBUF];

  i = SendDlgItemMessage(hdlg, id, CB_GETCURSEL, 0, 0);
  vw = CreateView(tb, "*", tt->cnd, tt->srt); if (!vw) return 0;
  if (i > 0 && i <= NViewRows(vw)) {
    *(pI4B)bf = 0; GetViewCellValue(bf, vw, i - 1, tt->icv);
    va = *(rI4B)bf;
  }
  DeleteView(vw);
  return va;
}

void WINAPI SetTTBL(HWND hdlg, I4B id, HTBL tb, rTBCI tt)
{ // 昞僐儞僩儘乕儖愝掕
  I4B cw, mgn, w1, w2, w3, dm[2];
  HWND htbc;
  HVIW vw;
  RECT rct;

  htbc = GetDlgItem(hdlg, id);
  GetClientRect(htbc, &rct); w1 = rct.rgt - rct.lft;
  SendMessage(htbc, TBCM_SETTABLE, (uANY)tb, FALSE);
  vw = (HVIW)SendMessage(htbc, TBCM_GETVIEW, 0, 0);
  if (tt->arr || tt->cnd || tt->srt) {
    if (tt->arr) { ArrangeViewColumns(vw, tt->arr);}
    if (tt->cnd) { SelectViewRows(vw, tt->cnd);}
    if (tt->srt) { SortViewRows(vw, tt->srt);}
    SendMessage(htbc, TBCM_UPDATE, TRUE, FALSE);
  }
  if (tt->flg & TTF_HDW) {
    cw = SendMessage(htbc, TBCM_GETAVECHARWIDTH, 0, 0);
    mgn = (cw < 8)? 2: cw / 4;
    SendMessage(htbc, TBCM_SETCOLUMNWIDTH, -1, tt->hdw * cw + 2 * mgn + 2);
  }
  if (!(tt->flg & TTF_NOA)) {
    dm[0] = tt->ns? tt->ns: NViewRows(vw); dm[1] = NViewColumns(vw);
    SendMessage(htbc, TBCM_CALCSIZE, (uANY)dm, (iANY)&rct);
    if (rct.rgt - rct.lft > w1) { rct.rgt = rct.lft + w1;}
    AdjustWindow(htbc, &rct);
  }
  if (tt->flg & TTF_ADJ) {
    GetClientRect(htbc, &rct); w2 = rct.rgt - rct.lft;
    if (w1 > w2) {
      w3 = SendMessage(htbc, TBCM_GETCOLUMNWIDTH, tt->ica, 0);
      SendMessage(htbc, TBCM_SETCOLUMNWIDTH, tt->ica, w1 - w2 + w3);
      SendMessage(htbc, TBCM_CALCSIZE, (uANY)dm, (iANY)&rct);
      AdjustWindow(htbc, &rct);
    }
  }
}

void WINAPI SetTSEL(HWND hdlg, I4B id, I4B ir, HTBL tb, rTBCI tt)
{ // 昞僐儞僩儘乕儖(儕僗僩儃僢僋僗宆)僨乕僞愝掕
  HVIW vw;
  POSI c;

  SetTTBL(hdlg, id, tb, tt);
  vw = (HVIW)SendDlgItemMessage(hdlg, id, TBCM_GETVIEW, 0, 0);
  if (ir >= 0 && ir < NViewRows(vw)) {
    c.ir = ir; c.ic = 0;
    SendDlgItemMessage(hdlg, id, TBCM_SETCUR, (uANY)&c, FALSE);
    SendDlgItemMessage(hdlg, id, TBCM_SETSEL, TRUE, TRUE);
  }
}

I4B  WINAPI GetTSEL(HWND hdlg, I4B id)
{ // 昞僐儞僩儘乕儖(儕僗僩儃僢僋僗宆)僨乕僞庢摼
  I4B rn[2];

  SendDlgItemMessage(hdlg, id, TBCM_GETSEL, (uANY)rn, 0);
  return rn[0];
}

void WINAPI SetTINT(HWND hdlg, I4B id, I4B va, HTBL tb, rTBCI tt)
{ // 昞僐儞僩儘乕儖(儕僗僩儃僢僋僗宆)僨乕僞愝掕(抣)
  I4B ir;
  HVIW vw;
  POSI c;

  SetTTBL(hdlg, id, tb, tt); if (va == 0) return;
  vw = (HVIW)SendDlgItemMessage(hdlg, id, TBCM_GETVIEW, 0, 0);
  ir = SearchViewCellValue(vw, 0, 0, &va);
  if (ir >= 0 && ir < NViewRows(vw)) {
    c.ir = ir; c.ic = 0;
    SendDlgItemMessage(hdlg, id, TBCM_SETCUR, (uANY)&c, FALSE);
    SendDlgItemMessage(hdlg, id, TBCM_SETSEL, TRUE, TRUE);
  }
}

I4B  WINAPI GetTINT(HWND hdlg, I4B id)
{ // 昞僐儞僩儘乕儖(儕僗僩儃僢僋僗宆)僨乕僞庢摼(抣)
  I4B rn[2], va = 0;
  HVIW vw;
  I1B bf[LBUF];

  vw = (HVIW)SendDlgItemMessage(hdlg, id, TBCM_GETVIEW, 0, 0);
  SendDlgItemMessage(hdlg, id, TBCM_GETSEL, (uANY)rn, 0);
  if (rn[0] >= 0 && rn[0] < NViewRows(vw)) {
    *(pI4B)bf = 0; GetViewCellValue(bf, vw, rn[0], 0);
    va = *(rI4B)bf;
  }
  return va;
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

static CODI diDLM[] = { { '\t', "僞僽" }, { ',', "僐儞儅" }, { ';', "僙儈僐儘儞" }, { ' ', "僗儁乕僗" } };
static CODS dsDLM = { diDLM, _countof(diDLM) };

static CODI diQUO[] = { { 0, "側偟" }, { '\'', "僔儞僌儖僋僅乕僩"  }, { '"', "僟僽儖僋僅乕僩" } };
static CODS dsQUO = { diQUO, _countof(diQUO) };

static CODI diTSW[] = { { TSW_NON, "側偟" }, { TSW_NAM, "楍柤" }, { TSW_TIT, "楍僞僀僩儖" } };
static CODS dsTSW = { diTSW, _countof(diTSW) };

BOOL LOCALF CSVI_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 俠俽倁忣曬愝掕僟僀傾儘僌僾儘僔乕僕儍
  CSVI *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (CSVI *)lpa));
    SetCCOD(hdlg, 101, pa->dlm, &dsDLM);
    SetCCOD(hdlg, 102, pa->quo, &dsQUO);
    SetCCOD(hdlg, 103, pa->tsw, &dsTSW);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (CSVI *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      pa->dlm = GetCCOD(hdlg, 101, &dsDLM);
      pa->quo = GetCCOD(hdlg, 102, &dsQUO);
      pa->tsw = GetCCOD(hdlg, 103, &dsTSW);
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL WINAPI CSVInfoDlgBox(HWND hwnd, pCSVI pa)
{ // 俠俽倁忣曬愝掕僟僀傾儘僌儃僢僋僗
  static DLGI dit[] = {
    { C_SLFT|wsG,   8, 10, 56,  8,  -1, "嬫愗傝暥帤(&D):" },
    { C_CSEL|wsT,  64,  8, 72,128, 101, "" },
    { C_SLFT|wsG,   8, 26, 56,  8,  -1, "堷梡晞暥帤(&Q):" },
    { C_CSEL|wsT,  64, 24, 72,128, 102, "" },
    { C_SLFT|wsG,   8, 42, 56,  8,  -1, "僞僀僩儖峴(&T):" },
    { C_CSEL|wsT,  64, 40, 72,128, 103, "" },
    { C_BDEF|wsGT, 54, 92, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 106, 92, 48, 14, IDCANCEL, "僉儍儞僙儖" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 112, "僥僉僗僩僼傽僀儖" };

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

BOOL LOCALF STX_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 暥帤楍専嶕僟僀傾儘僌僾儘僔乕僕儍
  STXP *pa;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (STXP *)lpa));
    SetESTR(hdlg, 101, pa->str);
    SetBFLG(hdlg, 102, !(pa->flg & STX_UPR));
    SetBFLG(hdlg, 103, !(pa->flg & STX_ZEN));
    SetBFLG(hdlg, 104, pa->flg & STX_DSP);
    SetBSEL(hdlg, 105, !(pa->flg & (STX_ALL|STX_LFT|STX_RGT)));
    SetBSEL(hdlg, 106, pa->flg & STX_ALL);
    SetBSEL(hdlg, 107, pa->flg & STX_LFT);
    SetBSEL(hdlg, 108, pa->flg & STX_RGT);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (STXP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case IDOK:
      GetESTR(hdlg, 101, pa->str, sizeof(pa->str) - 1);
      pa->flg = 0;
      if (GetBFLG(hdlg, 102) == 0) { pa->flg |= STX_UPR;}
      if (GetBFLG(hdlg, 103) == 0) { pa->flg |= STX_ZEN;}
      if (GetBFLG(hdlg, 104))      { pa->flg |= STX_DSP;}
      if      (GetBSEL(hdlg, 106)) { pa->flg |= STX_ALL;}
      else if (GetBSEL(hdlg, 107)) { pa->flg |= STX_LFT;}
      else if (GetBSEL(hdlg, 108)) { pa->flg |= STX_RGT;}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL WINAPI SearchTextDlgBox(HWND hwnd, pSTXP pa, BOOL sw)
{ // 暥帤楍専嶕忣曬愝掕
  I4B i;
  static DLGI dit[] = {
    { C_SLFT|wsG,   8,  8, 76,  8,  -1, "専嶕偡傞暥帤楍(&T):" },
    { C_ESTR|wsT,   8, 18,194, 12, 101, "" },
    { C_BFLG|wsGT,  8, 40,120, 10, 102, "戝暥帤偲彫暥帤傪嬫暿偡傞(&C)" },
    { C_BFLG|wsGT,  8, 54,120, 10, 103, "慡妏偲敿妏傪嬫暿偡傞(&I)" },
    { C_BFLG|wsGT,  8, 68,120, 10, 104, "嬻敀傪柍帇偡傞(&S)" },
    { C_BSEL|wsGT,  8, 86, 60, 10, 105, "晹暘堦抳(&U)" },
    { C_BSEL|ws_,  72, 86, 60, 10, 106, "慡懱堦抳(&W)" },
    { C_BSEL|ws_,   8,100, 60, 10, 107, "慜曽堦抳(&P)" },
    { C_BSEL|ws_,  72,100, 60, 10, 108, "屻曽堦抳(&F)" },
    { C_BDEF|wsGT,102,140, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 154,140, 48, 14, IDCANCEL, "僉儍儞僙儖" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 208, 160, "専嶕" };

  for (i = 5; i <= 8; i++) {
    if (!sw) { dit[i].sty |= wsD;} else { dit[i].sty &=~wsD;}
  }
  return DlgBoxInput(hwnd, &dlg, STX_DlgProc, (iANY)pa) == IDOK;
}

#define  IDFIN  21

BOOL LOCALF EDI_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 峴曇廤僟僀傾儘僌僾儘僔乕僕儍
  I4B i, f, nc;
  HTBL tb;
  HBUF rb;
  U1B wk[LBUF];

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(rb = (HBUF)lpa));
    nc = NTableColumns(tb = RowBufHTBL(rb));
    for (i = 0; i < nc; i++) {
      f = TableColumnFlags(tb, i);
      if (f & CF_DED) continue;
      GetRowBufCellValue(wk, rb, i);
      if (f & (CF_DDL|CF_DDN)) {
        SetCITM(hdlg, 101 + i, wk, TableColumnInfo(tb, i));
      } else {
        SetEITM(hdlg, 101 + i, wk, TableColumnInfo(tb, i));
      }
    }
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    rb = (HBUF)GetWindowLong(hdlg, DWL_USER);
    nc = NTableColumns(tb = RowBufHTBL(rb));
    switch (wpa) {
    case IDOK:
      SendMessage(hdlg, WM_NEXTDLGCTL, 0, 0); break;
    case IDFIN:
      for (i = 0; i < nc; i++) {
        f = TableColumnFlags(tb, i);
        if (f & CF_DED) continue;
        if (f & (CF_DDL|CF_DDN)) {
          GetCITM(hdlg, 101 + i, wk, TableColumnInfo(tb, i));
        } else {
          GetEITM(hdlg, 101 + i, wk, TableColumnInfo(tb, i));
        }
        SetRowBufCellValue(rb, i, wk);
      }
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL WINAPI EditRowDlgBox(HWND hwnd, HBUF rb, rSTR tit)
{ // 峴曇廤
  I4B i, f, nc, sw, sty, x, x1, y, y1, w, w1, h, re = FALSE;
  HTBL tb;
  rSTR cls;
  HBLK SB, bk;
  PDLGI di;
  static DLGS dlg;

  SB = CreateStrBlk(65536); if (!SB) return FALSE;
  bk = SelectStrBlk(SB);
  nc = NTableColumns(tb = RowBufHTBL(rb));
  dlg.di = halloc((nc * 2 + 2) * sizeof(DLGI), TRUE); if (!dlg.di) { ierr(E_MEM); goto _10;}
  dlg.w = 160; dlg.h = 112;
  dlg.tit = tit? tit: "峴曇廤";
  y = 8; w1 = 48;
  for (i = 0; i < nc; i++) {
    f = TableColumnFlags(tb, i);
    if (f & CF_DED) continue;
    if (!(f & (CF_PAC|CF_GR1|CF_GR2|CF_GR3))) {
      if (i > 0) { y += 16;}
      w = ((strlen(TableColumnDescription(tb, i)) + 1) / 2) * 8;
      if (w > w1) { w1 = w;}
    }
  }
  y1 = ((y + 63) / 16) * 16; if (y1 > dlg.h) { dlg.h = y1;}
  di = dlg.di;
  x = 8; y = 8;
  for (i = 0; i < nc; i++) {
    f = TableColumnFlags(tb, i);
    if (f & CF_DED) continue;
    switch (f & (CF_PAC|CF_GR1|CF_GR2|CF_GR3)) {
    case CF_GR1: sw = 0; x =  96; break;
    case CF_GR2: sw = 0; x = 144; break;
    case CF_GR3: sw = 0; x = 192; break;
    case CF_PAC: sw = 0;
      if (x > 8) { x += 16;}
      break;
    default: sw = 1;
      if (i > 0) { x = 8; y += 16;}
      break;
    }
    w = ((strlen(TableColumnDescription(tb, i)) + 1) / 2) * 8; if (w < 48) { w = 48;}
    SetDLGI(di++, C_SLFT|wsG, x, y + 2, w, 8, -1, stostr(strconc(TableColumnDescription(tb, i), ":")));
    if (sw) { w = w1;}
    x += w;
    w = (TableColumnWidth(tb, i) / 2 + 2) * 8;
    if (f & (CF_DDL|CF_DDN)) {
      w += 8; h = 128;
      cls = "combobox";
      switch (f & (CF_DDL|CF_DDN)) {
      case CF_DDN: sty = wsCBV|cbsDH; break;
      default:     sty = wsCBV|cbsL;  break;
      }
    } else {
      h = 12;
      cls = "edit";
      switch (TableColumnTextAlign(tb, i)) {
      case DT_CEN: sty = wsCB|esC; break;
      case DT_RGT: sty = wsCB|esR; break;
      default:     sty = wsCB|esH; break;
      }
    }
    SetDLGI(di++, cls, sty|wsT|((f & (CF_HCH|CF_RDO))? wsD: 0), x, y, w, h, 101 + i, "");
    x += w;
    x1 = ((x + 13) / 16) * 16; if (x1 + 6 > dlg.w) { dlg.w = x1 + 6;}
  }
  SetDLGI(di++, C_BPSH|wsGT, dlg.w -106, dlg.h - 20, 48, 14, IDFIN, "OK");
  SetDLGI(di++, C_BPSH|wsT,  dlg.w - 54, dlg.h - 20, 48, 14, IDCANCEL, "僉儍儞僙儖");
  dlg.ni = di - dlg.di;
  re = (DlgBoxInput(hwnd, &dlg, EDI_DlgProc, (iANY)rb) == IDFIN);
  hfree(dlg.di);
 _10: SelectStrBlk(bk); DeleteStrBlk(SB);
  return re;
}

void LOCALF SetBOWN(HWND hdlg, rMNDI mi, BOOL sw)
{ // 儊僯儏乕儃僞儞愝掕
  I4B i;

  for (i = 0; i < 8; i++) {
    SetBSTR(hdlg, 101 + i, mi[i].txt);
    EnableDlgItem(hdlg, 101 + i, mi[i].idm > 0 && mi[i].flg == mf_);
  }
  if (sw) { SetFocus(GetDlgItem(hdlg, 101));}
}

void LOCALF DrawBOWN(LPDRAWITEMSTRUCT lpdis, rMNDI mi)
{ // 儊僯儏乕儃僞儞偺僆乕僫乕昤夋
  HDC hdc = lpdis->hDC;
  I4B tco;
  HFNT hfnt;
  RECT rct;

  rct = lpdis->rcItem;
  if (lpdis->itemState & ODS_FOCUS) {
    DrawEdge(hdc, &rct, EDGE_RAISED, BF_MONO|BF_RECT);
    InflateRect(&rct, -1, -1);
  }
  DrawFrameControl(hdc, &rct, DFC_BUTTON, DFCS_BUTTONPUSH | ((lpdis->itemState & ODS_SELECTED)? DFCS_FLAT: 0));
  if (mi->bid) {
    SetRect(&rct, 0, 0, MNDBMPW * 2, MNDBMPH * 2);
    DrawDDB(hdc, &rct, AppDDB(mi->bid), DT_CEN | ((lpdis->itemState & ODS_DISABLED)? DT_GRY: 0));
  }
  if (mi->txt) {
    rct = lpdis->rcItem;
    rct.top = (rct.top + rct.btm) / 2 + 4;
    InflateRect(&rct, -4, -4);
    if (lpdis->itemState & ODS_DISABLED) {
      tco = SetTextColor(hdc, AppColor(CID_GTX));
    }
    DrawText(hdc, mi->txt, -1, &rct, DT_WORDBREAK|DT_CENTER);
    if (mi->idm >= IDJMP && mi->idm <= IDJMPMAX) {
      hfnt = SelectObject(hdc, AppFont(FID_WEB));
      DrawText(hdc, "4", -1, &rct, DT_SINGLELINE|DT_RIGHT|DT_BOTTOM);
      SelectObject(hdc, hfnt);
    }
    if (lpdis->itemState & ODS_DISABLED) {
      SetTextColor(hdc, tco);
    }
  }
  if (lpdis->itemState & ODS_FOCUS) {
    rct = lpdis->rcItem;
    InflateRect(&rct, -4, -4);
    DrawFocusRect(hdc, &rct);
  }
}

BOOL LOCALF MND_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 奐巒儊僯儏乕僟僀傾儘僌僾儘僔乕僕儍
  I4B id, sr;
  MNDS *pa;
  static COLI co[] = {
    { TID_YMD,  0, "ymd", },
    { TID_YMN,  0, "ymn", },
    { TID_YMD,  0, "ymd", NULL, NULL, 0, NULL, NULL, (U4B)"yyyy 擭 m 寧 d 擔", },
    { TID_YMN,  0, "ymn", NULL, NULL, 0, NULL, NULL, (U4B)"yyyy 擭 m 寧", },
  };

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (MNDS *)lpa));
    SetBOWN(hdlg, pa->mi + pa->ip * 8, FALSE);
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    sr = CurDate();
    SetEITM(hdlg, 109, &sr, &co[pa->flg & 3]);
    SetSSTR(hdlg, 110, pa->msg1);
    SetSSTR(hdlg, 111, pa->msg2);
    return TRUE;
  case WM_DRAWITEM:
    pa = (MNDS *)GetWindowLong(hdlg, DWL_USER);
    if (wpa >= 101 && wpa <= 108) {
      DrawBOWN((LPDRAWITEMSTRUCT)lpa, pa->mi + pa->ip * 8 + wpa - 101);
    }
    return TRUE;
  case WM_COMMAND:
    pa = (MNDS *)GetWindowLong(hdlg, DWL_USER);
    if (HIU2B(wpa) == BN_CLICKED) {
      if (wpa != IDCANCEL) {
        GetEITM(hdlg, 109, &sr, &co[pa->flg & 3]);
        if (sr) { SetCurDate(sr);}
      }
      if (wpa == IDOK) {
        id = GetDlgCtrlID(GetFocus());
        if (id >= 101 && id <= 108) {
          SendDlgItemMessage(hdlg, id, BM_CLICK, 0, 0);
        } else if (id == 109) {
          SetEITM(hdlg, 109, &sr, &co[pa->flg & 3]);
          SetFocus(GetDlgItem(hdlg, 101));
        }
        return FALSE;
      } else if (wpa == IDCANCEL) {
        pa->ip = 0;
      } else if (wpa >= 101 && wpa <= 108) {
        id = (pa->mi + pa->ip * 8 + wpa - 101)->idm;
        if (id >= IDJMP && id <= IDJMPMAX && (id - IDJMP) * 8 + 7 < pa->ni) {
          pa->ip = id - IDJMP;
          SetBOWN(hdlg, pa->mi + pa->ip * 8, TRUE);
          return FALSE;
        }
        wpa = id;
      }
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

I4B  WINAPI MenuDlgBox(HWND hwnd, pMNDS pa, rSTR tit)
{ // 奐巒儊僯儏乕
  static DLGI dit[] = {
    { C_BOWN|wsGT,  6,  8, 64, 56, 101, "" },  // 0
    { C_BOWN|wsT,  74,  8, 64, 56, 102, "" },
    { C_BOWN|wsT, 142,  8, 64, 56, 103, "" },
    { C_BOWN|wsT, 210,  8, 64, 56, 104, "" },
    { C_BOWN|wsT,   6, 68, 64, 56, 105, "" },
    { C_BOWN|wsT,  74, 68, 64, 56, 106, "" },
    { C_BOWN|wsT, 142, 68, 64, 56, 107, "" },
    { C_BOWN|wsT, 210, 68, 64, 56, 108, "" },
    { C_SLFT|wsG,   8,138, 28,  8,  -1, NULL },// 8
    { C_ESTR|wsT,  36,136,  0, 12, 109, "" },  // 9
    { C_SLFT|wsG, 142,138,132,  8, 110, "" },
    { C_SMUL|wsG,   8,158,266, 40, 111, "" },  //11
    { C_BPSH|wsT, 122,204, 48, 14, IDMANUAL, "僿儖僾" },
    { C_BPSH|wsT, 174,204, 48, 14, IDREFRESH, "昞帵峏怴" },
    { C_BPSH|wsT, 226,204, 48, 14, IDCANCEL, "儊僯儏乕暵偠傞" },
  };
  static U2B w9[4] = { 56, 48, 72, 64 };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 280, 224, NULL };

  dit[8].txt = (pa->flg & 1)? "寁嶼寧:": "寁嶼擔:";
  dit[9].w = w9[pa->flg & 3];
  if (pa->flg & 4) { dit[11].x = 142; dit[11].y = 152;}
  else             { dit[11].x = 8;   dit[11].y = 158;}
  dlg.tit = tit? tit: "儊僯儏乕";
  if (!pa->msg1) { pa->msg1 = "";}
  if (!pa->msg2) { pa->msg2 = "";}
  return DlgBoxInput(hwnd, &dlg, MND_DlgProc, (iANY)pa);
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

#define  LINE_PITCH  24
#define  WHEEL_SENS  40

#define  KS_SHIFT    1
#define  KS_CONTROL  2

#define  KS_SFT  KS_SHIFT
#define  KS_CTL  KS_CONTROL

I4B  LOCALF KEYSTATE(void)
{ // 僉乕偺忬懺
  return ((GetKeyState(VK_SHIFT)&~1) != 0) + ((GetKeyState(VK_CONTROL)&~1) != 0) * 2;
}

static U4B CF_BOLRBLK;

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

#define  txc_setcur(hwnd, rc, rd)    SendMessage(hwnd, TXCM_SETCUR, rc, rd)
#define  txc_setsel(hwnd, se, rd)    SendMessage(hwnd, TXCM_SETSEL, se, rd)
#define  txc_update(hwnd, rd)        SendMessage(hwnd, TXCM_UPDATE, 0, rd)
#define  txc_movecur(hwnd, op, rd)   SendMessage(hwnd, TXCM_MOVECUR, op, rd)

  // 僥僉僗僩僐儞僩儘乕儖忣曬
typedef struct {
  HBLK  xb;
  I4B   flg;
  U2B   nr;
  U2B   nc;
  U2B   cr;
  U2B   cc;
  U2B   br;
  U2B   bc;
  U2B   ar;
  U2B   ac;
  HFNT  hfnt;
  I4B   cw;
  I4B   ch;
  I4B   rh;
} TXCE;
typedef TXCE *pTXCE;

#define  carc(ce)   HIU2B(CharPos((ce)->xb, *(rU4B)&(ce)->cr))
#define  carx(ce)   ((ce)->xb? ((ce)->cw * (carc(ce) - (ce)->bc) + (ce)->cw / 2): 0)
#define  cary(ce)   ((ce)->rh * ((ce)->cr - (ce)->br) + ((ce)->rh - (ce)->ch) / 2)

iANY LOCALF TXC_create(HWND hwnd, iANY lpa)
{ // 僥僉僗僩僂傿儞僪僂奐巒張棟
  pTXCE ce;

  ce = halloc(sizeof(TXCE), TRUE); if (!ce) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)ce);
  SendMessage(hwnd, TXCM_SETMODE, (U2B)WindowStyle(hwnd), FALSE);
  SendMessage(hwnd, WM_SETFONT, (uANY)NULL, FALSE);
  return 0;
}

iANY LOCALF TXC_setmode(HWND hwnd, I4B flg, BOOL rd)
{ // 忬懺僼儔僌愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  ce->flg = flg;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_settext(HWND hwnd, HBLK xb, BOOL rd)
{ // 僥僉僗僩忣曬愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  ce->xb = xb;
  txc_update(hwnd, rd);
  return 0;
}

iANY LOCALF TXC_setfont(HWND hwnd, HFNT hfnt, BOOL rd)
{ // 僼僅儞僩愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  SIZE siz;
  LOGFONT lof;

  GetObject(hfnt? hfnt: AppFont(FID_MON), sizeof(LOGFONT), &lof);
  GetZenCharSize(&siz, NULL, &lof);
  ce->hfnt = CreateFontIndirect(&lof);
  ce->cw = siz.cx / 2;
  ce->ch = siz.cy;
  ce->rh = siz.cy;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_setlinepitch(HWND hwnd, I4B rh)
{ // 峴僺僢僠愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (rh > 0) { ce->rh = rh;}
  return 0;
}

iANY LOCALF TXC_setcur(HWND hwnd, U4B rc, BOOL rd)
{ // 僇乕僜儖埵抲偺愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  *(pU4B)&ce->cr = rc;
  if (ce->cr > ce->nr) { ce->cr = ce->nr;}
  if (ce->cc > ce->nc) { ce->cc = ce->nc;}
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_settop(HWND hwnd, U4B rc, BOOL rd)
{ // 昞帵奐巒埵抲偺愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  *(pU4B)&ce->br = rc;
  if (ce->br > ce->nr) { ce->br = ce->nr;}
  if (ce->bc > ce->nc) { ce->bc = ce->nc;}
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_setsel(HWND hwnd, BOOL se, BOOL rd)
{ // 斖埻慖戰(慖戰夝彍)
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (ce->flg & TXCS_DSE) return 0;
  switch (((ce->flg & TXCS_SEL) != 0) * 2 + (se != 0)) {
  case 1:
    ce->flg |= TXCS_SEL; *(pU4B)&ce->ar = *(rU4B)&ce->cr;
    ParentNotify(hwnd, APPN_SELCHANGE, TRUE);
    break;
  case 2:
    ce->flg &=~TXCS_SEL; *(pU4B)&ce->ar = 0;
    ParentNotify(hwnd, APPN_SELCHANGE, FALSE);
    break;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_update(HWND hwnd, BOOL rd)
{ // 昞帵峏怴
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B nd, ns;
  RECT rct;

  if (!ce->xb) return 0;
  GetClientRect(hwnd, &rct);
  nd = (rct.rgt - (ce->cw / 2)) / ce->cw;
  ns = rct.btm / ce->rh;
  *(pU4B)&ce->nr = RowExt(ce->xb);
  if (ce->cr > ce->nr) { ce->cr = ce->nr;}
  if (ce->cc > ce->nc) { ce->cc = ce->nc;}
  if (ce->br > ce->nr) { ce->br = ce->nr;}
  if (ce->bc > ce->nc) { ce->bc = ce->nc;}
  txc_setsel(hwnd, FALSE, FALSE);
  if (ce->cr < ce->br) {
    ce->br = ce->cr;
  } else if (ns > 0 && ce->cr >= ce->br + ns) {
    ce->br = ce->cr - ns + 1;
  }
  if (ce->cc < ce->bc) {
    ce->bc = ce->cc;
  } else if (nd > 0 && ce->cc >= ce->bc + nd) {
    ce->bc = ce->cc - nd + 1;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_movecur(HWND hwnd, I4B op, BOOL rd)
{ // 僇乕僜儖偺憡懳堏摦
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B nd, ns;
  RECT rct;

  if (!ce->xb) return 0;
  GetClientRect(hwnd, &rct);
  nd = (rct.rgt - (ce->cw / 2)) / ce->cw;
  ns = rct.btm / ce->rh;
  if (op & MVC_SEL) {
    if (!(ce->flg & TXCS_SEL)) { txc_setsel(hwnd, TRUE, FALSE);}
  } else {
    if (ce->flg & TXCS_SEL) { txc_setsel(hwnd, FALSE, FALSE);}
  }
  switch (op & 0x00ff) {
  case MVC_LFT:
    *(pU4B)&ce->cr = PrevPos(ce->xb, *(rU4B)&ce->cr);
    break;
  case MVC_RGT:
    *(pU4B)&ce->cr = NextPos(ce->xb, *(rU4B)&ce->cr);
    break;
  case MVC_HOM:
    ce->cc = 0;
    break;
  case MVC_END:
    ce->cc = RowLen(ce->xb, ce->cr);
    break;
  }
  switch (op & 0xff00) {
  case MVC_LUP:
    if (ce->cr > 0) { ce->cr--;}
    break;
  case MVC_LDN:
    if (ce->cr < ce->nr) { ce->cr++;}
    break;
  case MVC_PUP:
    if (ce->br > ns) { ce->br -= ns;} else { ce->br = 0;}
    if (ce->cr > ns) { ce->cr -= ns;} else { ce->cr = 0;}
    break;
  case MVC_PDN:
    if (ce->br < ce->nr - ns) { ce->br += ns;} else { ce->br = ce->nr;}
    if (ce->cr < ce->nr - ns) { ce->cr += ns;} else { ce->cr = ce->nr;}
    break;
  case MVC_TOP:
    ce->cr = 0;
    break;
  case MVC_BTM:
    ce->cr = ce->nr;
    break;
  }
  if (op & MVC_SEL) {
    txc_setsel(hwnd, TRUE, FALSE);
  }
  if (ce->cr < ce->br) {
    ce->br = ce->cr;
  } else if (ns > 0 && ce->cr >= ce->br + ns) {
    ce->br = ce->cr - ns + 1;
  }
  if (ce->cc < ce->bc) {
    ce->bc = ce->cc;
  } else if (nd > 0 && ce->cc >= ce->bc + nd) {
    ce->bc = ce->cc - nd + 1;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_paint(HWND hwnd)
{ // 昤夋
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B x, y, cb, nd, ns, hi, bc1, bc2, tc1, tc2, bkc, tco, tal;
  rSTR pt, st, pb, p1, p2;
  HDC hdc, hmem;
  HBMP horg;
  HBRS hbrs;
  HFNT hfnt;
  RECT rct;
  PAINTSTRUCT ps;

  if (!ce->xb) return 0;
  GetClientRect(hwnd, &rct);
  nd = (rct.rgt - (ce->cw / 2)) / ce->cw;
  ns = rct.btm / ce->rh;
  SetHScrollBar(hwnd, 0, ce->nc + nd - 1, nd, ce->bc);
  SetVScrollBar(hwnd, 0, ce->nr + ns - 1, ns, ce->br);
  hdc = BeginPaint(hwnd, &ps);
  hmem = CreateCompatibleDC(hdc);
  horg = SelectObject(hmem, CreateCompatibleBitmap(hdc, rct.rgt, rct.btm));
  FillRect(hmem, &rct, hbrs = CreateSolidBrush(AppColor(CID_WIN))); DeleteObject(hbrs);
  bc1 = AppColor(CID_WIN); bc2 = AppColor(CID_HIL);
  tc1 = AppColor(CID_TXT); tc2 = AppColor(CID_HIT);
  bkc = SetBkColor(hmem, bc1);
  tco = SetTextColor(hmem, tc1);
  tal = SetTextAlign(hmem, TA_LEFT|TA_TOP|TA_NOUPDATECP);
  hfnt = SelectObject(hmem, ce->hfnt);
  pb = RowPtr(ce->xb, ce->br);
  if (ce->flg & TXCS_SEL) {
    p1 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->ar));
    p2 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->cr));
    if (p1 > p2) { pt = p1; p1 = p2; p2 = pt;}
  } else {
    p1 = p2 = pb;
  }
  hi = FALSE;
  SetWindowOrgEx(hmem, ce->cw * ce->bc, 0, NULL);
  x = ce->cw / 2; y = (ce->rh - ce->ch) / 2;
  for (pt = pb; *pt != '\0'; ) {
    switch ((pt >= p1 && pt < p2) * 2 + hi) {
    case 1: hi = FALSE; SetBkColor(hmem, bc1); SetTextColor(hmem, tc1); break;
    case 2: hi = TRUE;  SetBkColor(hmem, bc2); SetTextColor(hmem, tc2); break;
    }
    if (*pt == '\r' && *(pt+1) == '\n') {
      x = ce->cw / 2; y += ce->rh; pt += 2; continue;
    } else if (isprn(pt)) {
      cb = 1; st = pt; pt++;
    } else if (iszen(pt)) {
      cb = 2; st = pt; pt += 2;
    } else {
      cb = 1; st = "?"; pt++;
    }
    if (y > rct.btm) break;
    TextOut(hmem, x, y, st, cb);
    x += cb * ce->cw;
  }
  SetWindowOrgEx(hmem, 0, 0, NULL);
  SelectObject(hmem, hfnt);
  SetTextAlign(hmem, tal);
  SetTextColor(hmem, tco);
  SetBkColor(hmem, bkc);
  BitBlt(hdc, 0, 0, rct.rgt, rct.btm, hmem, 0, 0, SRCCOPY);
  DeleteObject(SelectObject(hmem, horg));
  DeleteDC(hmem);
  EndPaint(hwnd, &ps);
  SetCaretPos(carx(ce), cary(ce));
  return 0;
}

iANY LOCALF TXC_setfocus(HWND hwnd, uANY wpa)
{ // 僼僅乕僇僗愝掕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  CreateCaret(hwnd, NULL, 0, ce->rh);
  SetCaretPos(carx(ce), cary(ce));
  ShowCaret(hwnd);
  ParentNotify(hwnd, APPN_SETFOCUS, 0);
  return 0;
}

iANY LOCALF TXC_killfocus(HWND hwnd, uANY wpa)
{ // 僼僅乕僇僗夝彍
  HideCaret(hwnd);
  DestroyCaret();
  ParentNotify(hwnd, APPN_KILLFOCUS, 0);
  return 0;
}

iANY LOCALF TXC_copy(HWND hwnd, pSTR bf)
{ // 慖戰暥帤楍偺庢摼
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  rSTR pt, p1, p2;

  if (!ce->xb || !(ce->flg & TXCS_SEL)) return 0;
  p1 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->ar));
  p2 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->cr));
  if (p1 > p2) { pt = p1; p1 = p2; p2 = pt;}
  spncpy(bf, p1, p2);
  return 0;
}

iANY LOCALF TXC_delete(HWND hwnd, BOOL rd);

iANY LOCALF TXC_insert(HWND hwnd, rSTR bf)
{ // 暥帤楍偺憓擖
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  U4B rc;
  rSTR pt;

  if (!ce->xb || (ce->flg & TXCS_DED)) return 0;
  if (ce->flg & TXCS_SEL) { TXC_delete(hwnd, FALSE);}
  rc = CharPos(ce->xb, *(rU4B)&ce->cr);
  if (HIU2B(rc) > RowLen(ce->xb, LOU2B(rc))) { rc = MKU4B(LOU2B(rc), RowLen(ce->xb, LOU2B(rc)));}
  InsertStr(ce->xb, rc, bf);
  pt = RowPtr(ce->xb, rc);
  *(pU4B)&ce->cr = PtrRow(ce->xb, pt + strlen(bf));
  txc_update(hwnd, TRUE);
  return 0;
}

iANY LOCALF TXC_delete(HWND hwnd, BOOL rd)
{ // 慖戰暥帤楍偺嶍彍
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  rSTR pt, p1, p2;

  if (!ce->xb || (ce->flg & TXCS_DED) || !(ce->flg & TXCS_SEL)) return 0;
  p1 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->ar));
  p2 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->cr));
  if (p1 > p2) { pt = p1; p1 = p2; p2 = pt;}
  DeleteStr(ce->xb, PtrRow(ce->xb, p1), PtrRow(ce->xb, p2));
  *(pU4B)&ce->cr = PtrRow(ce->xb, p1);
  txc_update(hwnd, rd);
  return 0;
}

iANY LOCALF TXC_backspace(HWND hwnd)
{ // 屻戅
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (!ce->xb || (ce->flg & TXCS_DED)) return 0;
  if (ce->flg & TXCS_SEL) { return TXC_delete(hwnd, TRUE);}
  ce->flg |= TXCS_SEL; *(pU4B)&ce->ar = *(rU4B)&ce->cr;
  *(pU4B)&ce->cr = PrevPos(ce->xb, *(rU4B)&ce->cr);
  return TXC_delete(hwnd, TRUE);
}

iANY LOCALF TXC_deletechar(HWND hwnd)
{ // 暥帤嶍彍
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (!ce->xb || (ce->flg & TXCS_DED)) return 0;
  if (ce->flg & TXCS_SEL) { return TXC_delete(hwnd, TRUE);}
  ce->flg |= TXCS_SEL; *(pU4B)&ce->ar = *(rU4B)&ce->cr;
  *(pU4B)&ce->cr = NextPos(ce->xb, *(rU4B)&ce->cr);
  return TXC_delete(hwnd, TRUE);
}

iANY LOCALF TXC_copystr(HWND hwnd)
{ // 僐僺乕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  rSTR pt, p1, p2;
  HGLOBAL hg;

  if (!ce->xb || (ce->flg & TXCS_DSE) || !(ce->flg & TXCS_SEL)) return 0;
  p1 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->ar));
  p2 = RowPtr(ce->xb, CharPos(ce->xb, *(rU4B)&ce->cr));
  if (p1 > p2) { pt = p1; p1 = p2; p2 = pt;}
  hg = GlobalAlloc(GHND, p2 - p1 + 1); if (!hg) return 0;
  spncpy(GlobalLock(hg), p1, p2); GlobalUnlock(hg);
  if (!OpenClipboard(hwnd)) { GlobalFree(hg); return 0;}
  EmptyClipboard();
  SetClipboardData(CF_TEXT, hg);
  CloseClipboard();
  return 0;
}

iANY LOCALF TXC_cutstr(HWND hwnd)
{ // 愗傝庢傝
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (ce->flg & TXCS_DED) return 0;
  TXC_copystr(hwnd);
  return TXC_delete(hwnd, TRUE);
}

iANY LOCALF TXC_pastestr(HWND hwnd)
{ // 揬傝晅偗
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  HGLOBAL hg;

  if (ce->flg & TXCS_DED) return 0;
  if (!OpenClipboard(hwnd)) return 0;
  hg = GetClipboardData(CF_TEXT); if (!hg) { CloseClipboard(); return 0;}
  TXC_insert(hwnd, GlobalLock(hg)); GlobalUnlock(hg);
  CloseClipboard();
  return 0;
}

iANY LOCALF TXC_search(HWND hwnd, rSTR st, I4B flg)
{ // 暥帤楍専嶕
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B nd, ns;
  U4B rc;
  RECT rct;

  if (!ce->xb || (ce->flg & TXCS_DSE)) return 0;
  GetClientRect(hwnd, &rct);
  nd = (rct.rgt - (ce->cw / 2)) / ce->cw;
  ns = rct.btm / ce->rh;
  if (ce->flg & TXCS_SEL) { txc_setsel(hwnd, FALSE, FALSE);}
  rc = SearchStr(ce->xb, *(rU4B)&ce->cr, st, flg);
  if (rc == (U4B)-1) return 0;
  ce->flg |= TXCS_SEL; *(pU4B)&ce->ar = rc;
  *(pU4B)&ce->cr = PtrRow(ce->xb, RowPtr(ce->xb, rc) + strmatchx(RowPtr(ce->xb, rc), st, flg));
  if (ce->cr < ce->br) {
    ce->br = ce->cr;
  } else if (ns > 0 && ce->cr >= ce->br + ns) {
    ce->br = ce->cr - ns + 1;
  }
  if (ce->cc < ce->bc) {
    ce->bc = ce->cc;
  } else if (nd > 0 && ce->cc >= ce->bc + nd) {
    ce->bc = ce->cc - nd + 1;
  }
  ParentNotify(hwnd, APPN_SELCHANGE, TRUE);
  RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  return 0;
}

iANY LOCALF TXC_hscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悈暯僗僋儘乕儖
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B nd;
  RECT rct;

  GetClientRect(hwnd, &rct);
  nd = (rct.rgt - (ce->cw / 2)) / ce->cw;
  switch (LOU2B(wpa)) {
  case SB_LINELEFT:
    if (ce->bc > 0) { ce->bc--;}
    break;
  case SB_PAGELEFT:
    ce->bc = 0;
    break;
  case SB_LINERIGHT:
    if (ce->bc < ce->nc) { ce->bc++;}
    break;
  case SB_PAGERIGHT:
    ce->bc = ce->nc;
    break;
  case SB_THUMBPOSITION:
  case SB_THUMBTRACK:
    ce->bc = HIU2B(wpa);
    break;
  }
  SetHScrollBar(hwnd, 0, ce->nc + nd - 1, nd, ce->bc);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_vscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悅捈僗僋儘乕儖
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B ns;
  RECT rct;

  GetClientRect(hwnd, &rct);
  ns = rct.btm / ce->rh;
  switch (LOU2B(wpa)) {
  case SB_LINEUP:
    if (ce->br > 0) { ce->br--;}
    break;
  case SB_LINEDOWN:
    if (ce->br < ce->nr) { ce->br++;}
    break;
  case SB_PAGEUP:
    if (ce->br > ns) { ce->br -= ns;} else { ce->br = 0;}
    break;
  case SB_PAGEDOWN:
    if (ce->br < ce->nr - ns) { ce->br += ns;} else { ce->br = ce->nr;}
    break;
  case SB_THUMBPOSITION:
  case SB_THUMBTRACK:
    ce->br = HIU2B(wpa);
    break;
  }
  SetVScrollBar(hwnd, 0, ce->nr + ns - 1, ns, ce->br);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_mousewheel(HWND hwnd, uANY wpa)
{ // 儅僂僗儂僀乕儖
  I4B dy, rd = FALSE;

  dy = (I2B)HIU2B(wpa);
  if (dy >= WHEEL_SENS) {
    do { TXC_vscroll(hwnd, SB_LINEUP,   FALSE);} while ((dy -= WHEEL_SENS) >= WHEEL_SENS);
    rd = TRUE;
  } else if (dy <= -WHEEL_SENS) {
    do { TXC_vscroll(hwnd, SB_LINEDOWN, FALSE);} while ((dy += WHEEL_SENS) <= -WHEEL_SENS);
    rd = TRUE;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TXC_mousemove(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗堏摦
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B cr, cc;
  POINTS pts = MAKEPOINTS(lpa);

  if ((ce->flg & (TXCS_CAP|TXCS_SEL)) != (TXCS_CAP|TXCS_SEL)) return 0;
  cr = ce->br + (pts.y - (ce->rh - ce->ch) / 2) / ce->rh;
  cc = ce->bc + (pts.x - (ce->cw / 2)) / ce->cw;
  if (cr < 0 || cr > ce->nr || cc < 0 || cc > ce->nc) return 0;
  if (cr != ce->cr || cc != ce->cc) {
    txc_setsel(hwnd, TRUE, TRUE);
    txc_setcur(hwnd, MKU4B(cr, cc), TRUE);
  }
  return 0;
}

iANY LOCALF TXC_lbuttondown(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗嵍儃僞儞墴壓
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B cr, cc;
  POINTS pts = MAKEPOINTS(lpa);

  ParentNotify(hwnd, APPN_LBUTTONDOWN, lpa);
  cr = ce->br + (pts.y - (ce->rh - ce->ch) / 2) / ce->rh;
  cc = ce->bc + (pts.x - (ce->cw / 2)) / ce->cw;
  if (cr < 0 || cr > ce->nr || cc < 0 || cc > ce->nc) return 0;
  ce->flg |= TXCS_CAP;
  SetCapture(hwnd);
  if (ce->flg & TXCS_SEL) { txc_setsel(hwnd, FALSE, FALSE);}
  txc_setcur(hwnd, MKU4B(cr, cc), TRUE);
  txc_setsel(hwnd, TRUE, FALSE);
  return 0;
}

iANY LOCALF TXC_lbuttonup(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗嵍儃僞儞夝曻
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  if (ce->flg & TXCS_CAP) {
    ce->flg &=~TXCS_CAP;
    ReleaseCapture();
    if (ce->cr == ce->ar && ce->cc == ce->ac) { txc_setsel(hwnd, FALSE, FALSE);}
  }
  return 0;
}

iANY LOCALF TXC_keydown(HWND hwnd, uANY wpa, iANY lpa)
{ // 僉乕憖嶌
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  I4B ks = KEYSTATE();

  switch (wpa) {
  case VK_TAB:
    if (!ks) {
      if (ce->flg & TXCS_UNM) {
        SendMessage(GetParent(hwnd), WM_NEXTDLGCTL, 0, 0); return 0;
      }
      return TXC_insert(hwnd, "  ");
    } else {
      if (ce->flg & TXCS_UNM) {
        SendMessage(GetParent(hwnd), WM_NEXTDLGCTL, 1, 0); return 0;
      }
    }
    break;
  case VK_RETURN:
    if (!ks) { return TXC_insert(hwnd, "\r\n");} else break;
  case VK_LEFT:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_LFT|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_RIGHT:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_RGT|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_UP:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_LUP|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_DOWN:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_LDN|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_HOME:
    return txc_movecur(hwnd, MVC_HOM|((ks & KS_CTL)? MVC_TOP: 0)|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_END:
    return txc_movecur(hwnd, MVC_END|((ks & KS_CTL)? MVC_BTM: 0)|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_PRIOR:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_PUP|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_NEXT:
    if (ks & KS_CTL) break;
    return txc_movecur(hwnd, MVC_PDN|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_BACK:
    if (!ks) { return TXC_backspace(hwnd);} else break;
  case VK_DELETE:
    if (!ks) { return TXC_deletechar(hwnd);} else break;
  case 'C':
    if (ks & KS_CTL) { return TXC_copystr(hwnd);} else break;
  case 'V':
    if (ks & KS_CTL) { return TXC_pastestr(hwnd);} else break;
  case 'X':
    if (ks & KS_CTL) { return TXC_cutstr(hwnd);} else break;
  }
  return 0;
}

iANY LOCALF TXC_char(HWND hwnd, uANY wpa, iANY lpa)
{ // 暥帤
  static U1B zen[4];

  if (zen[0] && iszen2((rSTR)&wpa)) {
    zen[1] = (U1B)wpa;
    TXC_insert(hwnd, zen);
    zen[0] = 0;
  } else if (isprn((rSTR)&wpa)) {
    TXC_insert(hwnd, (rSTR)&wpa);
  } else if (iszen1((rSTR)&wpa)) {
    zen[0] = (U1B)wpa;
  }
  return 0;
}

void LOCALF TXC_imestart(HWND hwnd)
{ // 俬俵俤擖椡奐巒
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);
  HIMC himc;
  POINT pnt;
  LOGFONT lof;
  COMPOSITIONFORM cfm;

  GetCaretPos(&pnt);
  GetObject(ce->hfnt, sizeof(LOGFONT), &lof);
  himc = ImmGetContext(hwnd);
  cfm.dwStyle = CFS_POINT;
  cfm.ptCurrentPos.x = pnt.x;
  cfm.ptCurrentPos.y = pnt.y;
  ImmSetCompositionWindow(himc, &cfm);
  ImmSetCompositionFont(himc, &lof);
  ImmReleaseContext(hwnd, himc);
}

iANY LOCALF TXC_destroy(HWND hwnd)
{ // 僥僉僗僩僂傿儞僪僂廔椆張棟
  pTXCE ce = (pTXCE)GetWindowLong(hwnd, 0);

  DeleteObject(ce->hfnt);
  hfree(ce);
  return 0;
}

iANY WINAPI DefBOLTXTProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return TXC_create(hwnd, lpa);
  case TXCM_SETMODE:
    return TXC_setmode(hwnd, wpa, lpa);
  case TXCM_GETMODE:
    return ((pTXCE)GetWindowLong(hwnd, 0))->flg;
  case TXCM_SETTEXT:
    return TXC_settext(hwnd, (HBLK)wpa, lpa);
  case TXCM_GETTEXT:
    return (iANY)((pTXCE)GetWindowLong(hwnd, 0))->xb;
  case WM_SETFONT:
    return TXC_setfont(hwnd, (HFNT)wpa, lpa);
  case WM_GETFONT:
    return (iANY)((pTXCE)GetWindowLong(hwnd, 0))->hfnt;
  case TXCM_SETLINEPITCH:
    return TXC_setlinepitch(hwnd, wpa);
  case TXCM_GETLINEPITCH:
    return ((pTXCE)GetWindowLong(hwnd, 0))->rh;
  case TXCM_SETCUR:
    return TXC_setcur(hwnd, wpa, lpa);
  case TXCM_GETCUR:
    return *(rU4B)&((pTXCE)GetWindowLong(hwnd, 0))->cr;
  case TXCM_SETTOP:
    return TXC_settop(hwnd, wpa, lpa);
  case TXCM_GETTOP:
    return *(rU4B)&((pTXCE)GetWindowLong(hwnd, 0))->br;
  case TXCM_SETSEL:
    return TXC_setsel(hwnd, wpa, lpa);
  case TXCM_GETSEL:
    return (((pTXCE)GetWindowLong(hwnd, 0))->flg & TXCS_SEL) != 0;
  case TXCM_UPDATE:
    return TXC_update(hwnd, lpa);
  case TXCM_MOVECUR:
    return TXC_movecur(hwnd, wpa, lpa);
  case WM_ERASEBKGND:
    return 1;
  case WM_PAINT:
    return TXC_paint(hwnd);
  case WM_SETFOCUS:
    return TXC_setfocus(hwnd, wpa);
  case WM_KILLFOCUS:
    return TXC_killfocus(hwnd, wpa);
  case WM_GETDLGCODE:
    return DLGC_WANTALLKEYS;
  case TXCM_COPY:
    return TXC_copy(hwnd, (pSTR)wpa);
  case TXCM_INSERT:
    return TXC_insert(hwnd, (rSTR)wpa);
  case TXCM_DELETE:
  case WM_CLEAR:
    return TXC_delete(hwnd, TRUE);
  case WM_COPY:
    return TXC_copystr(hwnd);
  case WM_CUT:
    return TXC_cutstr(hwnd);
  case WM_PASTE:
    return TXC_pastestr(hwnd);
  case TXCM_SEARCH:
    return TXC_search(hwnd, (rSTR)wpa, lpa);
  case WM_HSCROLL:
    return TXC_hscroll(hwnd, wpa, TRUE);
  case WM_VSCROLL:
    return TXC_vscroll(hwnd, wpa, TRUE);
  case WM_MOUSEWHEEL:
    return TXC_mousewheel(hwnd, wpa);
  case WM_MOUSEMOVE:
    return TXC_mousemove(hwnd, wpa, lpa);
  case WM_LBUTTONDOWN:
    return TXC_lbuttondown(hwnd, wpa, lpa);
  case WM_LBUTTONUP:
    return TXC_lbuttonup(hwnd, wpa, lpa);
  case WM_RBUTTONDOWN:
    ParentNotify(hwnd, APPN_RBUTTONDOWN, lpa); return 0;
  case WM_KEYDOWN:
    return TXC_keydown(hwnd, wpa, lpa);
  case WM_CHAR:
    return TXC_char(hwnd, wpa, lpa);
  case WM_IME_STARTCOMPOSITION:
    HideCaret(hwnd); TXC_imestart(hwnd); break;
  case WM_IME_ENDCOMPOSITION:
    ShowCaret(hwnd); break;
  case WM_CLOSE:
    SendMessage(GetParent(hwnd), FRMM_DESTROYCHILD, (uANY)hwnd, 0); return 0;
  case WM_DESTROY:
    return TXC_destroy(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLTXTClass(HINSTANCE hinst)
{ // 僥僉僗僩僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = CS_HREDRAW|CS_VREDRAW;
  wcx.lpfnWndProc   = DefBOLTXTProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 2 * sizeof(iANY);
  wcx.hInstance     = hinst;
  wcx.hIcon         = NULL;
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_WINDOW + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLTXT";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

#define  prc_npages(hwnd)       SendMessage(hwnd, PRCM_NPAGES, 0, 0)
#define  prc_paperwidth(hwnd)   SendMessage(hwnd, PRCM_PAPERWIDTH, 0, 0)
#define  prc_paperheight(hwnd)  SendMessage(hwnd, PRCM_PAPERHEIGHT, 0, 0)

  // 報嶞僾儗價儏乕僐儞僩儘乕儖忣曬
typedef struct {
  pANY  rp;
  I4B   flg;
  I4B   x0;
  I4B   y0;
  I4B   sc;
  I4B   ip;
} PRCE;
typedef PRCE *pPRCE;

iANY LOCALF PRC_create(HWND hwnd, iANY lpa)
{ // 報嶞僾儗價儏乕僂傿儞僪僂奐巒張棟
  pPRCE pe;

  pe = halloc(sizeof(PRCE), TRUE); if (!pe) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)pe);
  SendMessage(hwnd, PRCM_SETMODE, (U2B)WindowStyle(hwnd)|APPS_DED|APPS_DSE, FALSE);
  return 0;
}

iANY LOCALF PRC_setmode(HWND hwnd, I4B flg, BOOL rd)
{ // 忬懺僼儔僌愝掕
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  pe->flg = flg;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_setreport(HWND hwnd, pANY rp, BOOL rd)
{ // 儗億乕僩忣曬愝掕
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  pe->rp = rp;
  pe->x0 = pe->y0 = 0;
  pe->sc = 100;
  pe->ip = 0;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_setorigin(HWND hwnd, U4B xy, BOOL rd)
{ // 尨揰偺愝掕
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  pe->x0 = (I2B)LOU2B(xy);
  pe->y0 = (I2B)HIU2B(xy);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_getorigin(HWND hwnd)
{ // 尨揰偺庢摼
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return MKU4B(pe->x0, pe->y0);
}

iANY LOCALF PRC_setscale(HWND hwnd, I4B sc, BOOL rd)
{ // 攞棪偺愝掕
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  if (sc > 0 && sc <= 800) { pe->sc = sc;}
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_setpage(HWND hwnd, I4B ip, BOOL rd)
{ // 儁乕僕愝掕
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  if (!pe->rp) return 0;
  if (ip >= 0 && ip < prc_npages(hwnd)) { pe->ip = ip;}
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_npages(HWND hwnd)
{ // 儁乕僕悢
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return pe->rp? NPages((HREP)pe->rp): 1;
}

iANY LOCALF PRC_paperwidth(HWND hwnd)
{ // 墶僒僀僘
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return iround(PaperWidth((HREP)pe->rp) * DEFDPI / MMPI);
}

iANY LOCALF PRC_paperheight(HWND hwnd)
{ // 廲僒僀僘
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return iround(PaperHeight((HREP)pe->rp) * DEFDPI / MMPI);
}

iANY LOCALF PRC_drawpage(HWND hwnd, HDC hdc, HDC hmem)
{ // 昤夋
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B i, dw, dh, pw, ph;
  HDIB bm;
  HDC hwrk;
  HBMP hbmp, horg;
  RECT rct;

  dw = prc_paperwidth(hwnd) * pe->sc / 100;
  dh = prc_paperheight(hwnd)* pe->sc / 100;
  pw = iround(PaperWidth((HREP)pe->rp) * PRNDPI / MMPI);
  ph = iround(PaperHeight((HREP)pe->rp)* PRNDPI / MMPI);
  SetRect(&rct, 0, 0, pw, ph);
  hwrk = CreateCompatibleDC(hdc);
  horg = SelectObject(hwrk, CreateCompatibleBitmap(hdc, pw, ph));
  StartPrint((HREP)pe->rp, hwrk, PRNDPI);
  for (i = 1; i < pe->ip + 1; i++) {
    SkipPage((HREP)pe->rp, i);
  }
  FillRect(hwrk, &rct, (HBRS)(COLOR_WINDOW + 1));
  DrawPage((HREP)pe->rp, pe->ip + 1);
  EndPrint((HREP)pe->rp);
  bm = CreateDIB(pw, ph, DIB_32B|DIB_TDN); if (!bm) goto _10;
  hbmp = SelectObject(hwrk, CreateCompatibleBitmap(hwrk, 1, 1));
  GetDIBits(hwrk, hbmp, 0, ph, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS);
  DeleteObject(SelectObject(hwrk, hbmp));
  ResizeDIB(bm, dw, dh);
  StretchDIBits(hmem, -pe->x0, -pe->y0, dw, dh, 0, 0, dw, dh, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS, SRCCOPY);
  DeleteDIB(bm); _10:
  DeleteObject(SelectObject(hwrk, horg));
  DeleteDC(hwrk);
  return 0;
}

iANY LOCALF PRC_paint(HWND hwnd)
{ // 昤夋
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B dw, dh;
  HDC hdc, hmem;
  HBMP horg;
  RECT rct;
  PAINTSTRUCT ps;

  if (!pe->rp) return 0;
  GetClientRect(hwnd, &rct);
  dw = prc_paperwidth(hwnd) * pe->sc / 100;
  dh = prc_paperheight(hwnd)* pe->sc / 100;
  if (dw > rct.rgt) {
    if (pe->x0 < 0) { pe->x0 = 0;} else if (pe->x0 > dw - rct.rgt) { pe->x0 = dw - rct.rgt;}
  } else {
    pe->x0 = (dw - rct.rgt) / 2;
  }
  if (dh > rct.btm) {
    if (pe->y0 < 0) { pe->y0 = 0;} else if (pe->y0 > dh - rct.btm) { pe->y0 = dh - rct.btm;}
  } else {
    pe->y0 = (dh - rct.btm) / 2;
  }
  SetHScrollBar(hwnd, 0, dw - 1, rct.rgt, pe->x0);
  SetVScrollBar(hwnd, 0, dh - 1, rct.btm, pe->y0);
  hdc = BeginPaint(hwnd, &ps);
  hmem = CreateCompatibleDC(hdc);
  horg = SelectObject(hmem, CreateCompatibleBitmap(hdc, rct.rgt, rct.btm));
  FillRect(hmem, &rct, (HBRS)(COLOR_APPWORKSPACE + 1));
  SendMessage(hwnd, PRCM_DRAWPAGE, (uANY)hdc, (iANY)hmem);
  BitBlt(hdc, 0, 0, rct.rgt, rct.btm, hmem, 0, 0, SRCCOPY);
  DeleteObject(SelectObject(hmem, horg));
  DeleteDC(hmem);
  EndPaint(hwnd, &ps);
  return 0;
}

iANY LOCALF PRC_hscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悈暯僗僋儘乕儖
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B dw;
  RECT rct;

  if (!pe->rp) return 0;
  GetClientRect(hwnd, &rct);
  dw = prc_paperwidth(hwnd) * pe->sc / 100; if (dw <= rct.rgt) return 0;
  switch (LOU2B(wpa)) {
  case SB_LINELEFT:
    if (pe->x0 > LINE_PITCH) { pe->x0 -= LINE_PITCH;} else { pe->x0 = 0;}
    break;
  case SB_LINERIGHT:
    if (pe->x0 < dw - rct.rgt - LINE_PITCH) { pe->x0 += LINE_PITCH;} else { pe->x0 = dw - rct.rgt;}
    break;
  case SB_PAGELEFT:
    if (pe->x0 > rct.rgt) { pe->x0 -= rct.rgt;} else { pe->x0 = 0;}
    break;
  case SB_PAGERIGHT:
    if (pe->x0 < dw - 2 * rct.rgt) { pe->x0 += rct.rgt;} else { pe->x0 = dw - rct.rgt;}
    break;
  case SB_THUMBPOSITION: goto _10;
  case SB_THUMBTRACK: rd = FALSE; _10:
    pe->x0 = HIU2B(wpa);
    break;
  }
  SetHScrollBar(hwnd, 0, dw - 1, rct.rgt, pe->x0);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_vscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悅捈僗僋儘乕儖
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B dh;
  RECT rct;

  if (!pe->rp) return 0;
  GetClientRect(hwnd, &rct);
  dh = prc_paperheight(hwnd) * pe->sc / 100; if (dh <= rct.btm) return 0;
  switch (LOU2B(wpa)) {
  case SB_LINEUP:
    if (pe->y0 > LINE_PITCH) { pe->y0 -= LINE_PITCH;} else { pe->y0 = 0;}
    break;
  case SB_LINEDOWN:
    if (pe->y0 < dh - rct.btm - LINE_PITCH) { pe->y0 += LINE_PITCH;} else { pe->y0 = dh - rct.btm;}
    break;
  case SB_PAGEUP:
    if (pe->y0 > rct.btm) { pe->y0 -= rct.btm;} else { pe->y0 = 0;}
    break;
  case SB_PAGEDOWN:
    if (pe->y0 < dh - 2 * rct.btm) { pe->y0 += rct.btm;} else { pe->y0 = dh - rct.btm;}
    break;
  case SB_THUMBPOSITION: goto _10;
  case SB_THUMBTRACK: rd = FALSE; _10:
    pe->y0 = HIU2B(wpa);
    break;
  }
  SetVScrollBar(hwnd, 0, dh - 1, rct.btm, pe->y0);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_mousewheel(HWND hwnd, uANY wpa)
{ // 儅僂僗儂僀乕儖
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B dy, rd = FALSE;

  if (!pe->rp) return 0;
  dy = (I2B)HIU2B(wpa);
  if (dy >= WHEEL_SENS) {
    do { PRC_vscroll(hwnd, SB_LINEUP,   FALSE);} while ((dy -= WHEEL_SENS) >= WHEEL_SENS);
    rd = TRUE;
  } else if (dy <= -WHEEL_SENS) {
    do { PRC_vscroll(hwnd, SB_LINEDOWN, FALSE);} while ((dy += WHEEL_SENS) <= -WHEEL_SENS);
    rd = TRUE;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF PRC_keydown(HWND hwnd, uANY wpa, iANY lpa)
{ // 僉乕憖嶌
  I4B ks = KEYSTATE();

  switch (wpa) {
  case VK_LEFT:
    PRC_hscroll(hwnd, SB_LINELEFT, TRUE); break;
  case VK_RIGHT:
    PRC_hscroll(hwnd, SB_LINERIGHT, TRUE); break;
  case VK_UP:
    PRC_vscroll(hwnd, SB_LINEUP, TRUE); break;
  case VK_DOWN:
    PRC_vscroll(hwnd, SB_LINEDOWN, TRUE); break;
  case VK_HOME: if (ks & KS_CTL) { PRC_hscroll(hwnd, SB_PAGELEFT, FALSE); goto _10;}
    PRC_hscroll(hwnd, SB_PAGELEFT, TRUE); break;
  case VK_END:  if (ks & KS_CTL) { PRC_hscroll(hwnd, SB_PAGERIGHT, FALSE); goto _20;}
    PRC_hscroll(hwnd, SB_PAGERIGHT, TRUE); break;
  case VK_PRIOR: _10:
    PRC_vscroll(hwnd, SB_PAGEUP, TRUE); break;
  case VK_NEXT: _20:
    PRC_vscroll(hwnd, SB_PAGEDOWN, TRUE); break;
  }
  return 0;
}

iANY LOCALF PRC_destroy(HWND hwnd)
{ // 報嶞僾儗價儏乕僂傿儞僪僂廔椆張棟
  hfree((pPRCE)GetWindowLong(hwnd, 0));
  return 0;
}

iANY WINAPI DefBOLPRNProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return PRC_create(hwnd, lpa);
  case PRCM_SETMODE:
    return PRC_setmode(hwnd, wpa, lpa);
  case PRCM_GETMODE:
    return ((pPRCE)GetWindowLong(hwnd, 0))->flg;
  case PRCM_SETREPORT:
    return PRC_setreport(hwnd, (HREP)wpa, lpa);
  case PRCM_GETREPORT:
    return (iANY)((pPRCE)GetWindowLong(hwnd, 0))->rp;
  case PRCM_SETORIGIN:
    return PRC_setorigin(hwnd, wpa, lpa);
  case PRCM_GETORIGIN:
    return PRC_getorigin(hwnd);
  case PRCM_SETSCALE:
    return PRC_setscale(hwnd, wpa, lpa);
  case PRCM_GETSCALE:
    return ((pPRCE)GetWindowLong(hwnd, 0))->sc;
  case PRCM_SETPAGE:
    return PRC_setpage(hwnd, wpa, lpa);
  case PRCM_GETPAGE:
    return ((pPRCE)GetWindowLong(hwnd, 0))->ip;
  case PRCM_NPAGES:
    return PRC_npages(hwnd);
  case PRCM_PAPERWIDTH:
    return PRC_paperwidth(hwnd);
  case PRCM_PAPERHEIGHT:
    return PRC_paperheight(hwnd);
  case PRCM_DRAWPAGE:
    return PRC_drawpage(hwnd, (HDC)wpa, (HDC)lpa);
  case WM_ERASEBKGND:
    return 1;
  case WM_PAINT:
    return PRC_paint(hwnd);
  case WM_SETFOCUS:
    ParentNotify(hwnd, APPN_SETFOCUS, 0); return 0;
  case WM_KILLFOCUS:
    ParentNotify(hwnd, APPN_KILLFOCUS, 0); return 0;
  case WM_GETDLGCODE:
    return DLGC_WANTALLKEYS;
  case WM_HSCROLL:
    return PRC_hscroll(hwnd, wpa, TRUE);
  case WM_VSCROLL:
    return PRC_vscroll(hwnd, wpa, TRUE);
  case WM_MOUSEWHEEL:
    return PRC_mousewheel(hwnd, wpa);
  case WM_LBUTTONDOWN:
    ParentNotify(hwnd, APPN_LBUTTONDOWN, lpa); return 0;
  case WM_RBUTTONDOWN:
    ParentNotify(hwnd, APPN_RBUTTONDOWN, lpa); return 0;
  case WM_KEYDOWN:
    return PRC_keydown(hwnd, wpa, lpa);
  case WM_CLOSE:
    SendMessage(GetParent(hwnd), FRMM_DESTROYCHILD, (uANY)hwnd, 0); return 0;
  case WM_DESTROY:
    return PRC_destroy(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLPRNClass(HINSTANCE hinst)
{ // 報嶞僾儗價儏乕僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = CS_HREDRAW|CS_VREDRAW;
  wcx.lpfnWndProc   = DefBOLPRNProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 2 * sizeof(iANY);
  wcx.hInstance     = hinst;
  wcx.hIcon         = NULL;
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_APPWORKSPACE + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLPRN";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

iANY LOCALF DIC_paperwidth(HWND hwnd)
{ // 墶僒僀僘
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return DIB_WIDTH((HDIB)pe->rp);
}

iANY LOCALF DIC_paperheight(HWND hwnd)
{ // 廲僒僀僘
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);

  return abs(DIB_HEIGHT((HDIB)pe->rp));
}

iANY LOCALF DIC_drawpage(HWND hwnd, HDC hdc, HDC hmem)
{ // 昤夋
  pPRCE pe = (pPRCE)GetWindowLong(hwnd, 0);
  I4B dw, dh, pw, ph;
  HDIB bm;

  dw = (pw = prc_paperwidth(hwnd)) * pe->sc / 100;
  dh = (ph = prc_paperheight(hwnd))* pe->sc / 100;
  if (pe->sc < 100) {
    bm = DuplicateDIB((HDIB)pe->rp); if (!bm) goto _10;
    ResizeDIB(bm, dw, dh);
    StretchDIBits(hmem, -pe->x0, -pe->y0, dw, dh, 0, 0, dw, dh, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS, SRCCOPY);
    DeleteDIB(bm); _10:;
  } else {
    bm = (HDIB)pe->rp;
    StretchDIBits(hmem, -pe->x0, -pe->y0, dw, dh, 0, 0, pw, ph, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS, SRCCOPY);
  }
  return 0;
}

iANY WINAPI DefBOLDIBProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case DICM_NPAGES:
    return 1;
  case DICM_PAPERWIDTH:
    return DIC_paperwidth(hwnd);
  case DICM_PAPERHEIGHT:
    return DIC_paperheight(hwnd);
  case DICM_DRAWPAGE:
    return DIC_drawpage(hwnd, (HDC)wpa, (HDC)lpa);
  }
  return DefBOLPRNProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLDIBClass(HINSTANCE hinst)
{ // 價僢僩儅僢僾僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = CS_HREDRAW|CS_VREDRAW;
  wcx.lpfnWndProc   = DefBOLDIBProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 2 * sizeof(iANY);
  wcx.hInstance     = hinst;
  wcx.hIcon         = NULL;
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_APPWORKSPACE + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLDIB";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

  // 僄僨傿僢僩僐儞僩儘乕儖嶌惉忣曬
typedef struct {
  I4B   sty;
  I4B   id;
  I4B   x, y;
  I4B   w, h;
  HFNT  hfnt;
} EDIS;
typedef EDIS *pEDIS;
typedef const EDIS *rEDIS;

static WNDPROC EditProc;

iANY LOCALF TBC_EditProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僄僨傿僢僩僐儞僩儘乕儖偺僂傿儞僪僂僾儘僔乕僕儍
  HWND hown;
  static I4B key;

  switch (umsg) {
  case WM_GETDLGCODE:
    return DLGC_WANTALLKEYS|DLGC_HASSETSEL;
  case WM_SETFOCUS:
    key = FALSE;
    break;
  case WM_KILLFOCUS:
    if (!key) { SendMessage(GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)WindowText(hwnd), 0);}
    break;
  case WM_KEYDOWN:
    switch (wpa) {
    case VK_TAB:
    case VK_RETURN:
    case VK_UP:
    case VK_DOWN:
    case VK_PRIOR:
    case VK_NEXT:
      key = TRUE;
      SendMessage(hown = GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)WindowText(hwnd), 0);
      SendMessage(hown, WM_KEYDOWN, wpa, lpa);
      return 0;
    case VK_ESCAPE:
      key = TRUE;
      SendMessage(GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)NULL, 0);
      return 0;
    }
    break;
  }
  return CallWindowProc(EditProc, hwnd, umsg, wpa, lpa);
}

HWND LOCALF CreateEditBox(HWND hwnd, rSTR st, rEDIS es)
{ // 僄僨傿僢僩僐儞僩儘乕儖偺嶌惉
  HWND hedi;

  hedi = CreateWindowEx(
    0,
    "edit",
    st,
    wsCB | es->sty,
    es->x, es->y,
    es->w, es->h,
    hwnd,
    (HMENU)es->id,
    WindowInstance(hwnd),
    NULL
  );
  EditProc = SubclassWindow(hedi, TBC_EditProc);
  SendMessage(hedi, WM_SETFONT, (uANY)(es->hfnt? es->hfnt: AppFont(FID_DLG)), FALSE);
  SetFocus(hedi);
  return hedi;
}

  // 僪儘僢僾僟僂儞儕僗僩嶌惉忣曬
typedef struct {
  I4B   sty;
  I4B   id;
  I4B   x, y;
  I4B   w, h;
  HFNT  hfnt;
  rCOLI co;
} DROS;
typedef DROS *pDROS;
typedef const DROS *rDROS;

static WNDPROC DropProc;

iANY LOCALF TBC_DropProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僪儘僢僾僟僂儞儕僗僩僐儞僩儘乕儖偺僂傿儞僪僂僾儘僔乕僕儍
  HWND hown;
  static I4B key;

  switch (umsg) {
  case WM_GETDLGCODE:
    return DLGC_WANTALLKEYS;
  case WM_SETFOCUS:
    key = FALSE;
    break;
  case WM_KILLFOCUS:
    if (!key) { SendMessage(GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)WindowText(hwnd), 0);}
    break;
  case WM_KEYDOWN:
    switch (wpa) {
    case VK_TAB:
    case VK_RETURN:
    case VK_LEFT:
    case VK_RIGHT:
    case VK_PRIOR:
    case VK_NEXT:
      key = TRUE;
      SendMessage(hown = GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)WindowText(hwnd), 0);
      SendMessage(hown, WM_KEYDOWN, wpa, lpa);
      return 0;
    case VK_ESCAPE:
      key = TRUE;
      SendMessage(GetParent(hwnd), TBCM_CLOSEEDIT, (uANY)NULL, 0);
      return 0;
    }
    break;
  }
  return CallWindowProc(DropProc, hwnd, umsg, wpa, lpa);
}

HWND LOCALF CreateDropDown(HWND hwnd, rSTR st, rDROS ds)
{ // 僪儘僢僾僟僂儞儕僗僩僐儞僩儘乕儖偺嶌惉
  HWND hedi;
  U1B wk[LBUF];

  hedi = CreateWindowEx(
    0,
    "combobox",
    st,
    wsCBV | ds->sty,
    ds->x, ds->y,
    ds->w, ds->h,
    hwnd,
    (HMENU)ds->id,
    WindowInstance(hwnd),
    NULL
  );
  DropProc = SubclassWindow(hedi, TBC_DropProc);
  SendMessage(hedi, WM_SETFONT, (uANY)(ds->hfnt? ds->hfnt: AppFont(FID_DLG)), FALSE);
  SetFocus(hedi);
  SetCITM(hwnd, ds->id, ColumnScan(wk, st, ds->co), ds->co);
  SendDlgItemMessage(hwnd, ds->id, CB_SHOWDROPDOWN, TRUE, 0);
  return hedi;
}

#define  tbc_getcellrect(hwnd, lc, pr)  SendMessage(hwnd, TBCM_GETCELLRECT, (uANY)(lc), (iANY)(pr))
#define  tbc_getrblkrect(hwnd, rn, pr)  SendMessage(hwnd, TBCM_GETRBLKRECT, (uANY)(rn), (iANY)(pr))
#define  tbc_drawcell(hwnd, lc, dr)     SendMessage(hwnd, TBCM_DRAWCELL, (uANY)(lc), (iANY)(dr))
#define  tbc_drawcellptr(hwnd, lc, dr)  SendMessage(hwnd, TBCM_DRAWCELLPTR, (uANY)(lc), (iANY)(dr))
#define  tbc_movecellptr(hwnd, lc, lp)  SendMessage(hwnd, TBCM_MOVECELLPTR, (uANY)(lc), (iANY)(lp))
#define  tbc_setcur(hwnd, lc, rd)       SendMessage(hwnd, TBCM_SETCUR, (uANY)(lc), rd)
#define  tbc_setfix(hwnd, lc, rd)       SendMessage(hwnd, TBCM_SETFIX, (uANY)(lc), rd)
#define  tbc_setsel(hwnd, se, rd)       SendMessage(hwnd, TBCM_SETSEL, se, rd)
#define  tbc_update(hwnd, sw, rd)       SendMessage(hwnd, TBCM_UPDATE, sw, rd)
#define  tbc_inputtext(hwnd, lc, bf)    SendMessage(hwnd, TBCM_INPUTTEXT, (uANY)(lc), (iANY)(bf))
#define  tbc_getcellformat(hwnd, lc)    SendMessage(hwnd, TBCM_GETCELLFORMAT, (uANY)(lc), 0)
#define  tbc_getcelltext(hwnd, lc, st)  SendMessage(hwnd, TBCM_GETCELLTEXT, (uANY)(lc), (iANY)(st))
#define  tbc_movecur(hwnd, op, rd)      SendMessage(hwnd, TBCM_MOVECUR, op, rd)

  // 昞僐儞僩儘乕儖忣曬
typedef struct {
  HVIW  vw;
  I4B   flg;
  I4B   nr;
  I4B   nc;
  I4B   hr;
  I4B   hc;
  I4B   tr;
  I4B   tc;
  I4B   cr;
  I4B   cc;
  I4B   br;
  I4B   bc;
  I4B   fr;
  I4B   fc;
  I4B   ar;
  I4B   ac;
  RBLK  rs;
  RBLK  rr;
  pI4B  cx;
  HFNT  hfnt;
  I4B   cw;
  I4B   rh;
  HWND  hedi;
  U4B   rsv;
} TBCE;
typedef TBCE *pTBCE;

#define  isremp(rn)   ((rn)->r1 > (rn)->r2)
#define  setremp(rn)  ((rn)->r1 = 0, (rn)->r2 = -1)

I4B  LOCALF nscroll(pTBCE ce, rRECT pr)
{ // 僗僋儘乕儖峴悢
  I4B ns;

  ns = (pr->btm / ce->rh) - ce->hr - ce->tr - ce->fr; if (ns < 0) { ns = 0;}
  return ns;
}

I4B  LOCALF lastcol(pTBCE ce, rRECT pr, I4B bc)
{ // 慡晹昞帵偝傟傞嵟屻偺楍
  I4B j, lft;

  for (lft = 0, j = -ce->hc; j < ce->nc && lft + ce->cx[ce->hc + j] <= pr->rgt; lft += ce->cx[ce->hc + j], j++) {
    if (j == ce->fc) { j = bc;}
  }
  return (j > bc)? j - 1: bc;
}

iANY LOCALF TBC_create(HWND hwnd, iANY lpa)
{ // 昞僂傿儞僪僂奐巒張棟
  pTBCE ce;

  ce = halloc(sizeof(TBCE), TRUE); if (!ce) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)ce);
  SendMessage(hwnd, TBCM_SETMODE, (U2B)WindowStyle(hwnd), FALSE);
  SendMessage(hwnd, WM_SETFONT, (uANY)NULL, FALSE);
  return 0;
}

iANY LOCALF TBC_setmode(HWND hwnd, I4B flg, BOOL rd)
{ // 忬懺僼儔僌愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  ce->flg = flg;
  ce->hr = !(ce->flg & TBCS_HCH);
  ce->hc = !(ce->flg & TBCS_HRH);
  ce->tr = !!(ce->flg & TBCS_ASR);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_settable(HWND hwnd, HTBL tb, BOOL rd)
{ // 昞偺愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B flg;

  if (ce->vw) { DeleteView(ce->vw);}
  if (!tb) { ce->vw = NULL; return 0;}
  ce->vw = CreateViewX(tb, NULL, NULL, 0, NULL, 0); if (!ce->vw) return 0;
  flg = TableFlags(tb);
  if (flg & TF_RDO) { ce->flg |= (TBCS_DED|TBCS_DSE);}
  else if (flg & TF_FIX) { ce->flg |= TBCS_DSE;}
  tbc_update(hwnd, TRUE, rd);
  return 0;
}

iANY LOCALF TBC_gettable(HWND hwnd)
{ // 昞偺庢摼
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  return (iANY)(ce->vw? ViewHTBL(ce->vw): NULL);
}

iANY LOCALF TBC_setnrows(HWND hwnd, I4B nr)
{ // 峴悢愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  ce->nr = (nr > 0)? nr: 1;
  return 0;
}

iANY LOCALF TBC_setncolumns(HWND hwnd, I4B nc)
{ // 楍悢愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  ce->nc = (nc > 0)? nc: 1;
  ce->cx = hrealloc(ce->cx, (ce->hc + ce->nc) * sizeof(I4B)); if (!ce->cx) { ierr(E_MEM);}
  return 0;
}

iANY LOCALF TBC_setcolumnwidth(HWND hwnd, I4B ic, I4B cw)
{ // 楍暆愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (ic >= -ce->hc && ic < ce->nc && cw > 0) { ce->cx[ce->hc + ic] = cw;}
  return 0;
}

iANY LOCALF TBC_getcolumnwidth(HWND hwnd, I4B ic)
{ // 楍暆庢摼
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  return (ic >= -ce->hc && ic < ce->nc)? ce->cx[ce->hc + ic]: 0;
}

iANY LOCALF TBC_setfont(HWND hwnd, HFNT hfnt, BOOL rd)
{ // 僼僅儞僩愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  SIZE siz;
  LOGFONT lof;

  GetObject(hfnt? hfnt: AppFont(FID_DEF), sizeof(LOGFONT), &lof);
  GetAveCharSize(&siz, NULL, &lof);
  ce->hfnt = CreateFontIndirect(&lof);
  ce->cw = siz.cx;
  ce->rh = siz.cy + ((siz.cy < 12)? 3: siz.cy / 6 + 1);
  tbc_update(hwnd, TRUE, rd);
  return 0;
}

iANY LOCALF TBC_setavecharwidth(HWND hwnd, I4B cw)
{ // 暯嬒暥帤暆愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (cw > 0) { ce->cw = cw;}
  return 0;
}

iANY LOCALF TBC_setrowheight(HWND hwnd, I4B rh)
{ // 峴崅偝愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (rh > 0) { ce->rh = rh;}
  return 0;
}

iANY LOCALF TBC_getcellrect(HWND hwnd, rPOSI lc, pRECT pr)
{ // 僙儖嬮宍
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B i, j;
  RECT rcc, rct;

  GetClientRect(hwnd, &rcc);
  SetRectEmpty(&rct);
  for (i = -ce->hr; i < ce->nr && rct.top < rcc.btm; rct.top += ce->rh, i++) {
    if (i == ce->fr) { i = ce->br;}
    if (i == lc->ir) goto _10;
  }
  rct.top = 0; goto _30;
 _10: rct.btm = rct.top + ce->rh;
  for (j = -ce->hc; j < ce->nc && rct.lft < rcc.rgt; rct.lft += ce->cx[ce->hc + j], j++) {
    if (j == ce->fc) { j = ce->bc;}
    if (j == lc->ic) goto _20;
  }
  rct.lft = rct.btm = 0; goto _30;
 _20: rct.rgt = rct.lft + ce->cx[ce->hc + j];
 _30: *pr = rct;
  return 0;
}

iANY LOCALF TBC_getrblkrect(HWND hwnd, rRBLK rn, pRECT pr)
{ // 峴僽儘僢僋嬮宍
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B i, r1, r2;
  RECT rcc, rct;

  GetClientRect(hwnd, &rcc);
  SetRectEmpty(&rct); if (isremp(rn)) goto _30;
  r1 = rn->r1; r2 = rn->r2;
  switch ((r1 >= ce->fr && r1 < ce->br) + (r2 >= ce->fr && r2 < ce->br) * 2) {
  case 1: r1 = ce->br; break;
  case 2: r2 = ce->fr - 1; break;
  case 3: goto _30;
  }
  for (i = -ce->hr; i < ce->nr && rct.top < rcc.btm; rct.top += ce->rh, i++) {
    if (i == ce->fr) { i = ce->br;}
    if (i == r1) goto _10;
  }
  rct.top = 0; goto _30;
 _10: rct.btm = rct.top + ce->rh;
  for ( ; i < ce->nr && rct.btm <= rcc.btm; rct.btm += ce->rh, i++) {
    if (i == ce->fr) { i = ce->br;}
    if (i == r2) goto _20;
  }
  rct.btm = 0; goto _30;
 _20: rct.rgt = rcc.rgt;
 _30: *pr = rct;
  return 0;
}

U4B WINAPI DefCST(I4B fmt)
{ // 僙儖偺昤夋怓
  I4B tcid, bcid, hcid, vcid;

  switch (fmt & (DC_INR|DC_INC|DC_CHD|DC_RHD|DC_SEL)) {
  case DC_CHD:
  case DC_RHD:
  case DC_CHD|DC_RHD: tcid = CID_TXT; bcid = CID_3DF; hcid = CID_3DD; vcid = CID_3DD; break;
  case DC_SEL:        tcid = CID_HIT; bcid = CID_HIL; hcid = CID_3DS; vcid = CID_3DS; break;
  case DC_RHD|DC_SEL: tcid = CID_HIT; bcid = CID_3DS; hcid = CID_3DD; vcid = CID_3DD; break;
  case DC_INC:
  case DC_INC|DC_SEL:
  case DC_INR|DC_INC: tcid = CID_TXT; bcid = CID_3DH; hcid = CID_3DS; vcid = CID_3DS; break;
  case DC_INC|DC_CHD:
  case DC_INR|DC_RHD: tcid = CID_TXT; bcid = CID_3DF; hcid = CID_3DS; vcid = CID_3DS; break;
  default:            tcid = CID_TXT; bcid = CID_WIN; hcid = CID_3DS; vcid = CID_3DS; break;
  }
  if (fmt & DC_FXR) { hcid = CID_TXT;}
  if (fmt & DC_FXC) { vcid = CID_TXT;}
  return CST(tcid, bcid, hcid, vcid);
}

void WINAPI SetDRWI(pDRWI di, pSTR bf, HDC hdc, pRECT pr)
{ // DRWI峔憿懱偺愝掕
  (di->bf = bf)[0] = '\0'; di->fmt = di->cst = di->pst = 0; di->hdc = hdc; di->pr = pr;
}

I4B  LOCALF hilight(I4B cid)
{ // 僴僀儔僀僩
  return NearestAppColorIndex(lighten(AppColor(cid), 224));
}

iANY LOCALF TBC_drawcell(HWND hwnd, rPOSI lc, rDRWI dr)
{ // 僙儖偺昤夋
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B tco, mgn, cst, tcid, bcid, hcid, vcid;
  HDC hdc = dr->hdc;
  HPEN hpen;
  HFNT hfnt;
  RECT rct = *dr->pr;
  LOGFONT lof;

  cst = dr->cst? dr->cst: DefCST(dr->fmt);
  tcid = ((pU1B)&cst)[0]; bcid = ((pU1B)&cst)[1]; hcid = ((pU1B)&cst)[2]; vcid = ((pU1B)&cst)[3];
  FillRect(hdc, &rct, AppBrush(bcid));
  hpen = SelectObject(hdc, AppPen(hcid));
  MoveTo(hdc, rct.lft, rct.btm - 1);
  LineTo(hdc, rct.rgt, rct.btm - 1);
  SelectObject(hdc, AppPen(vcid));
  MoveTo(hdc, rct.rgt - 1, rct.top);
  LineTo(hdc, rct.rgt - 1, rct.btm);
  if ((dr->fmt & (DC_CHD|DC_RHD)) && !(dr->fmt & (DC_INR|DC_INC|DC_SEL))) {
    SelectObject(hdc, AppPen(hilight(bcid)));
    MoveTo(hdc, rct.lft, rct.btm - 2);
    LineTo(hdc, rct.lft, rct.top);
    LineTo(hdc, rct.rgt - 1, rct.top);
    if (dr->fmt & DC_RDO) {
      tco = SetTextColor(hdc, AppColor(CID_RED));
      hfnt = SelectObject(hdc, AppFont(FID_WEB));
      rct.btm -= 1;
      DrawText(hdc, "x", -1, &rct, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
      SelectObject(hdc, hfnt);
      SetTextColor(hdc, tco); goto _10;
    }
  }
  if (dr->bf && dr->bf[0] != '\0') {
    if (tcid) { tco = SetTextColor(hdc, AppColor(tcid));}
    if (dr->fmt & DC_LNK) {
      GetObject(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONT), &lof);
      lof.lfUnderline = TRUE;
      hfnt = SelectObject(hdc, CreateFontIndirect(&lof));
    }
    mgn = (ce->cw < 8)? 2: ce->cw / 4;
    rct.lft += mgn; rct.rgt -= mgn + 1;
    DrawText(hdc, dr->bf, -1, &rct, DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER|(dr->fmt & 0x03));
    if (dr->fmt & DC_LNK) {
      DeleteObject(SelectObject(hdc, hfnt));
    }
    if (tcid) { SetTextColor(hdc, tco);}
  }
 _10: SelectObject(hdc, hpen);
  return 0;
}

U4B WINAPI DefPST(I4B fmt)
{ // 僙儖億僀儞僞偺昤夋怓
  I4B pcid, bcid, fcid, icid;

  switch (fmt & (DC_DED|DC_CHD|DC_RHD|DC_PTR)) {
  case DC_DED|DC_PTR: pcid = CID_RED; bcid = CID_PTR; fcid = CID_RED; icid = CID_WIN; break;
  case DC_CHD|DC_CUC:
  case DC_RHD|DC_CUR: pcid = CID_WIN; bcid = CID_IDX; fcid = CID_TXT; icid = CID_WIN; break;
  default:            pcid = CID_TXT; bcid = CID_PTR; fcid = CID_3DD; icid = CID_PTR; break;
  }
  return PST(pcid, bcid, fcid, icid);
}

iANY LOCALF TBC_drawcellptr(HWND hwnd, rPOSI lc, rDRWI dr)
{ // 僙儖億僀儞僞偺昤夋
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B x, t, md, tco, pst, pcid, bcid, fcid, icid;
  HDC hdc = dr->hdc;
  HPEN hpen;
  HBRS hbrs;
  HFNT hfnt;
  RECT rct = *dr->pr;
  POINT pt[3];

  if (GetFocus() != hwnd || (ce->flg & TBCS_LST)) return 0;
  pst = dr->pst? dr->pst: DefPST(dr->fmt);
  pcid = ((pU1B)&pst)[0]; bcid = ((pU1B)&pst)[1]; fcid = ((pU1B)&pst)[2]; icid = ((pU1B)&pst)[3];
  md = SetROP2(hdc, R2_NOTXORPEN);
  hpen = SelectObject(hdc, (pcid == CID_WIN)? GetStockObject(NULL_PEN): AppPen(pcid));
  hbrs = SelectObject(hdc, (bcid == CID_WIN)? GetStockObject(NULL_BRUSH): AppBrush(bcid));
  Rectangle(hdc, rct.lft, rct.top, rct.rgt - 1, rct.btm - 1);
  if (dr->fmt & DC_DED) {
    tco = SetTextColor(hdc, AppColor(fcid));
    hfnt = SelectObject(hdc, AppFont(FID_WEB));
    rct.btm -= 1;
    DrawText(hdc, "x", -1, &rct, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
    SelectObject(hdc, hfnt);
    SetTextColor(hdc, tco);
  } else if (dr->fmt & (DC_DDL|DC_DDN)) {
    SelectObject(hdc, AppPen(fcid));
    SelectObject(hdc, (icid == CID_WIN)? GetStockObject(NULL_BRUSH): AppBrush(icid));
    x = rct.rgt - (rct.btm - rct.top);
    t = (rct.btm - rct.top) / 4;
    pt[0].x = x + t;     pt[0].y = rct.top + t * 3 / 2 + 1;
    pt[1].x = x + t * 3; pt[1].y = pt[0].y;
    pt[2].x = x + t * 2; pt[2].y = rct.top + t * 5 / 2 + 1;
    Polygon(hdc, pt, _countof(pt));
    if (dr->fmt & DC_DDN) {
      MoveTo(hdc, x, rct.top + 1);
      LineTo(hdc, x, rct.btm - 2);
    }
  }
  SelectObject(hdc, hpen);
  SelectObject(hdc, hbrs);
  SetROP2(hdc, md);
  return 0;
}

void LOCALF drawcelldirect(HWND hwnd, rPOSI lc, pDRWI dr)
{ // 僙儖偺捈愙昤夋
  tbc_getcellrect(hwnd, lc, dr->pr);
  if (!IsRectEmpty(dr->pr)) {
    dr->fmt = tbc_getcellformat(hwnd, lc);
    tbc_getcelltext(hwnd, lc, dr->bf);
    tbc_drawcell(hwnd, lc, dr);
  }
}

void LOCALF drawcellptrdirect(HWND hwnd, rPOSI lc, pDRWI dr)
{ // 僙儖億僀儞僞偺捈愙昤夋
  tbc_getcellrect(hwnd, lc, dr->pr);
  if (!IsRectEmpty(dr->pr)) {
    dr->fmt = tbc_getcellformat(hwnd, lc);
    tbc_getcelltext(hwnd, lc, dr->bf);
    tbc_drawcell(hwnd, lc, dr);
    tbc_drawcellptr(hwnd, lc, dr);
  }
}

iANY LOCALF TBC_movecellptr(HWND hwnd, rPOSI lc, rPOSI lp)
{ // 僙儖億僀儞僞堏摦昤夋
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B bkm;
  POSI c;
  HDC hdc;
  HFNT hfnt;
  RECT rct;
  DRWI dri;
  I1B bf[LBUF];

  hdc = GetDC(hwnd);
  bkm = SetBkMode(hdc, TRANSPARENT);
  hfnt = SelectObject(hdc, ce->hfnt);
  SetDRWI(&dri, bf, hdc, &rct);
  if (lp) {
    for (c.ir = -ce->hr, c.ic = lp->ic; c.ir < 0; c.ir++) { drawcelldirect(hwnd, &c, &dri);}
    for (c.ir = lp->ir, c.ic = -ce->hc; c.ic < 0; c.ic++) { drawcelldirect(hwnd, &c, &dri);}
    drawcelldirect(hwnd, lp, &dri);
  }
  if (lc) {
    for (c.ir = -ce->hr, c.ic = lc->ic; c.ir < 0; c.ir++) { drawcellptrdirect(hwnd, &c, &dri);}
    for (c.ir = lc->ir, c.ic = -ce->hc; c.ic < 0; c.ic++) { drawcellptrdirect(hwnd, &c, &dri);}
    drawcellptrdirect(hwnd, lc, &dri);
  }
  SelectObject(hdc, hfnt);
  SetBkMode(hdc, bkm);
  ReleaseDC(hwnd, hdc);
  return 0;
}

iANY LOCALF TBC_hittest(HWND hwnd, pPOSI lc, iANY lpa)
{ // 巜掕揰傪娷傓僙儖
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B i, j, top, lft;
  POINT pnt;
  RECT rcc;

  pnt.x = LOU2B(lpa); pnt.y = HIU2B(lpa);
  GetClientRect(hwnd, &rcc);
  for (top = 0, i = -ce->hr; i < ce->nr && top < rcc.btm; top += ce->rh, i++) {
    if (i == ce->fr) { i = ce->br;}
    if (pnt.y >= top && pnt.y < top + ce->rh) goto _10;
  }
  return FALSE;
 _10:
  for (lft = 0, j = -ce->hc; j < ce->nc && lft < rcc.rgt; lft += ce->cx[ce->hc + j], j++) {
    if (j == ce->fc) { j = ce->bc;}
    if (pnt.x >= lft && pnt.x < lft + ce->cx[ce->hc + j]) goto _20;
  }
  return FALSE;
 _20:
  lc->ir = i; lc->ic = j;
  return TRUE;
}

iANY LOCALF TBC_dropbutton(HWND hwnd, rPOSI lc, iANY lpa)
{ // 僪儘僢僾僟僂儞儃僞儞
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POINT pnt;
  RECT rct;

  pnt.x = LOU2B(lpa); pnt.y = HIU2B(lpa);
  if (!(tbc_getcellformat(hwnd, lc) & (DC_DDL|DC_DDN))) return FALSE;
  tbc_getcellrect(hwnd, lc, &rct);
  return pnt.x >= rct.rgt - (rct.btm - rct.top) && pnt.x < rct.rgt;
}

iANY LOCALF TBC_openlink(HWND hwnd)
{ // 僇儗儞僩僙儖偺儕儞僋愭傪奐偔
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B fmt;
  I1B bf[LBUF];

  fmt = tbc_getcellformat(hwnd, (rPOSI)&ce->cr); if (!(fmt & DC_LNK)) return 0;
  tbc_getcelltext(hwnd, (rPOSI)&ce->cr, bf);
  if (bf[0] != '\0') { ShellExecute(NULL, "open", bf, NULL, NULL, SW_SHOWDEFAULT);}
  return 0;
}

#define  IDEDI  100

iANY LOCALF TBC_openedit(HWND hwnd, U4B ch, pDRWI dr)
{ // 僄僨傿僢僩僐儞僩儘乕儖傪奐偔
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;
  RECT rcc, rct;
  EDIS edi;
  DROS dro;

  if (!ce->vw || (ce->flg & (TBCS_DED|TBCS_LST)) || (dr->fmt & DC_DED)) return 0;
  if (ce->cr == NViewRows(ce->vw)) {
    if (!InsertViewRow(ce->vw, ce->cr)) return 0;
    tbc_update(hwnd, FALSE, FALSE);
    r.r1 = ce->cr; r.r2 = ce->cr + 1;
    tbc_getrblkrect(hwnd, &r, &rct);
    RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
    ParentNotify(hwnd, APPN_CHANGE, OPR_INSERT);
  }
  tbc_getcellrect(hwnd, (rPOSI)&ce->cr, &rct); if (IsRectEmpty(&rct)) return 0;
  if (!(dr->fmt & (DC_DDL|DC_DDN)) || (ce->flg & TBCS_DDD)) {
    edi.id = IDEDI;
    switch (dr->fmt & 0x0f) {
    default:     edi.sty = esH; break;
    case DC_CEN: edi.sty = esC; break;
    case DC_RGT: edi.sty = esR; break;
    }
    edi.x = rct.lft - 1;
    edi.y = rct.top - 1;
    edi.w = rct.rgt - edi.x;
    edi.h = rct.btm - edi.y;
    edi.hfnt = ce->hfnt;
    ce->hedi = CreateEditBox(hwnd, dr->bf, &edi);
    if (dr->bf[0] != '\0') {
      SendMessage(ce->hedi, WM_KEYDOWN, VK_END, 1);
    }
  } else {
    GetClientRect(hwnd, &rcc);
    dro.id = IDEDI;
    dro.sty = cbsL;
    dro.x = rct.lft - 2;
    dro.y = rct.top - 2;
    dro.w = rct.rgt - dro.x;
    dro.h = 10 * ce->rh;
    if (dro.w < 4 * ce->rh) { dro.w += ce->rh;} else if (dro.w < 5 * ce->rh) { dro.w = 5 * ce->rh;}
    if (dro.x + dro.w > rcc.rgt) { dro.x = rcc.rgt - dro.w;}
    dro.hfnt = ce->hfnt;
    dro.co = ViewColumnInfo(ce->vw, ce->cc);
    ce->hedi = CreateDropDown(hwnd, dr->bf, &dro);
  }
  if (ch) {
    SendMessage(ce->hedi, WM_CHAR, ((rU1B)&ch)[0], 1);
    if (((rU1B)&ch)[1]) { SendMessage(ce->hedi, WM_CHAR, ((rU1B)&ch)[1], 1);}
  }
  return 0;
}

iANY LOCALF TBC_closeedit(HWND hwnd, rSTR st)
{ // 僄僨傿僢僩僐儞僩儘乕儖傪暵偠傞
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (st) { tbc_inputtext(hwnd, (rPOSI)&ce->cr, st);}
  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  return 0;
}

iANY LOCALF TBC_setcur(HWND hwnd, rPOSI lc, BOOL rd)
{ // 僇儗儞僩僙儖偺愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B ns;
  POSI b, c;
  RECT rcc, rct;

  GetClientRect(hwnd, &rcc);
  ns = nscroll(ce, &rcc);
  if (rd) {
    c = *(rPOSI)&ce->cr;
    b = *(rPOSI)&ce->br;
  }
  if (lc->ir >= 0 && lc->ir < ce->nr && lc->ic >= 0 && lc->ic < ce->nc) {
    ce->cr = lc->ir;
    ce->cc = lc->ic;
  } else return 0;
  if (rd) {
    if (ce->cr >= ce->fr && ce->cr < ce->br || ns > 0 && ce->cr >= ce->br + ns) {
      ce->br = ce->cr - ns / 2; if (ce->br < ce->fr) { ce->br = ce->fr;}
    }
    if (ce->cc >= ce->fc && ce->cc < ce->bc) {
      ce->bc = ce->cc;
    } else {
      while (lastcol(ce, &rcc, ce->bc) < ce->cc) { ce->bc++;}
    }
    if (ce->br != b.ir || ce->bc != b.ic || ((ce->flg & TBCS_LST) && (ce->cr != c.ir))) {
      RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
    } else if (ce->cr != c.ir || ce->cc != c.ic) {
      if (!isremp(&ce->rr)) {
        tbc_getrblkrect(hwnd, &ce->rr, &rct);
        RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
        setremp(&ce->rr);
      }
      tbc_movecellptr(hwnd, (rPOSI)&ce->cr, &c);
    }
  }
  return 0;
}

iANY LOCALF TBC_settop(HWND hwnd, rPOSI lc, BOOL rd)
{ // 昞帵奐巒埵抲愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (lc->ir >= 0 && lc->ir < ce->nr && lc->ic >= 0 && lc->ic < ce->nc) {
    ce->br = lc->ir; if (ce->br < ce->fr) { ce->br = ce->fr;}
    ce->bc = lc->ic; if (ce->bc < ce->fc) { ce->bc = ce->fc;}
  } else return 0;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_setfix(HWND hwnd, rPOSI lc, BOOL rd)
{ // 屌掕峴丄楍悢愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (lc->ir >= 0 && lc->ir < ce->nr && lc->ic >= 0 && lc->ic < ce->nc) {
    ce->fr = lc->ir; if (ce->br < ce->fr) { ce->br = ce->fr;}
    ce->fc = lc->ic; if (ce->bc < ce->fc) { ce->bc = ce->fc;}
  } else return 0;
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

void LOCALF differ(pRBLK rd, rRBLK rs, rRBLK rn)
{ // 斖埻偺嵎暘
  switch (isremp(rs) + isremp(rn) * 2) {
  case 1: *rd = *rn; return;
  case 2: *rd = *rs; return;
  case 3: setremp(rd); return;
  }
  switch ((rs->r1 == rn->r1) + (rs->r2 == rn->r2) * 2) {
  case 0: rd->r1 = min(rs->r1, rn->r1); rd->r2 = max(rs->r2, rn->r2); break;
  case 1: rd->r1 = min(rs->r2, rn->r2) + 1; rd->r2 = max(rs->r2, rn->r2); break;
  case 2: rd->r2 = max(rs->r1, rn->r1) - 1; rd->r1 = min(rs->r1, rn->r1); break;
  case 3: setremp(rd); break;
  }
}

void LOCALF unionr(pRBLK ru, rRBLK rr, rRBLK rd)
{ // 斖埻偺暪崌
  switch (isremp(rr) + isremp(rd) * 2) {
  case 1: *ru = *rd; return;
  case 2: *ru = *rr; return;
  case 3: setremp(ru); return;
  }
  ru->r1 = min(rr->r1, rd->r1); ru->r2 = max(rr->r2, rd->r2);
}

iANY LOCALF TBC_setsel(HWND hwnd, BOOL se, BOOL rd)
{ // 斖埻慖戰(慖戰夝彍)
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;
  RECT rct;

  if (ce->flg & TBCS_DSE) return 0;
  r = *(rRBLK)&ce->rs;
  if (ce->flg & TBCS_SEL) {
    if (se) {
      if (ce->flg & TBCS_LST) {
        ce->rs.r1 = ce->rs.r2 = ce->cr;
        ParentNotify(hwnd, APPN_SELCHANGE, TRUE);
      } else {
        ce->rs.r1 = min(ce->cr, ce->ar);
        ce->rs.r2 = max(ce->cr, ce->ar);
      }
    } else {
      ce->flg &=~TBCS_SEL;
      setremp(&ce->rs);
      ParentNotify(hwnd, APPN_SELCHANGE, FALSE);
    }
  } else if (se) {
    ce->flg |= TBCS_SEL;
    ce->rs.r1 = ce->rs.r2 = ce->cr;
    *(pRBLK)&ce->ar = *(rRBLK)&ce->cr;
    ParentNotify(hwnd, APPN_SELCHANGE, TRUE);
  }
  differ(&r, &ce->rs, &r);
  unionr(&ce->rr, &ce->rr, &r);
  if (rd) {
    if (ce->flg & TBCS_LST) {
      RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
    } else {
      if (!isremp(&ce->rr)) {
        tbc_getrblkrect(hwnd, &ce->rr, &rct);
        RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
        setremp(&ce->rr);
      }
    }
  }
  return 0;
}

iANY LOCALF TBC_getsel(HWND hwnd, pRBLK rn)
{ // 慖戰忬懺偺庢摼
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (rn) *rn = ce->rs;
  return (ce->flg & TBCS_SEL) != 0;
}

iANY LOCALF TBC_update(HWND hwnd, BOOL sw, BOOL rd)
{ // 昞帵峏怴
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B j, ln, mgn;

  SendMessage(hwnd, TBCM_SETNROWS, SendMessage(hwnd, TBCM_ASKNROWS, 0, 0), 0);
  if (sw) {
    SendMessage(hwnd, TBCM_SETNCOLUMNS, SendMessage(hwnd, TBCM_ASKNCOLUMNS, 0, 0), 0);
    mgn = (ce->cw < 8)? 2: ce->cw / 4;
    for (j = -ce->hc; j < ce->nc; j++) {
      ln = SendMessage(hwnd, TBCM_ASKCOLUMNLENGTH, j, 0);
      SendMessage(hwnd, TBCM_SETCOLUMNWIDTH, j, ln * ce->cw + 2 * mgn + 2);
    }
  }
  if (ce->cr >= ce->nr) { ce->cr = ce->nr - 1;}
  if (ce->cc >= ce->nc) { ce->cc = ce->nc - 1;}
  if (ce->br >= ce->nr) { ce->br = ce->nr - 1;}
  if (ce->bc >= ce->nc) { ce->bc = ce->nc - 1;}
  if (ce->ar >= ce->nr) { ce->ar = ce->nr - 1;}
  if (ce->ac >= ce->nc) { ce->ac = ce->nc - 1;}
  if (ce->fr >= ce->nr) { ce->fr = ce->nr - 1;}
  if (ce->fc >= ce->nc) { ce->fc = ce->nc - 1;}
  tbc_setsel(hwnd, FALSE, FALSE);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_calcsize(HWND hwnd, rPOSI dm, pRECT pr)
{ // 僋儔僀傾儞僩嬮宍偺昁梫僒僀僘傪媮傔傞
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B i, j, nr, nc;
  RECT rct;

  nr = ((dm && dm->ir > 0)? dm->ir: ce->nr) + ce->tr;
  nc = (dm && dm->ic > 0 && dm->ic < ce->nc)? dm->ic: ce->nc;
  SetRectEmpty(&rct);
  for (i = -ce->hr; i < nr; rct.btm += ce->rh, i++) {
    if (i == ce->fr) { i = ce->br;}
  }
  for (j = -ce->hc; j < nc; rct.rgt += ce->cx[ce->hc + j], j++) {
    if (j == ce->fc) { j = ce->bc;}
  }
  *pr = rct;
  return 0;
}

iANY LOCALF TBC_editcell(HWND hwnd)
{ // 僇儗儞僩僙儖傪曇廤
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  DRWI dri;
  I1B bf[LBUF];

  if (ce->flg & (TBCS_DED|TBCS_LST)) return 0;
  if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, TRUE);}
  SetDRWI(&dri, bf, NULL, NULL);
  dri.fmt = tbc_getcellformat(hwnd, (rPOSI)&ce->cr);
  tbc_getcelltext(hwnd, (rPOSI)&ce->cr, dri.bf);
  return TBC_openedit(hwnd, 0, &dri);
}

iANY LOCALF TBC_copyeditcell(HWND hwnd)
{ // 僇儗儞僩僙儖傊忋偺僙儖偐傜僐僺乕偟偰曇廤
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c;
  DRWI dri;
  I1B bf[LBUF];

  if (ce->flg & (TBCS_DED|TBCS_LST)) return 0;
  if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, TRUE);}
  c.ir = ce->cr - (ce->cr > 0); c.ic = ce->cc;
  SetDRWI(&dri, bf, NULL, NULL);
  dri.fmt = tbc_getcellformat(hwnd, (rPOSI)&ce->cr);
  tbc_getcelltext(hwnd, &c, dri.bf);
  return TBC_openedit(hwnd, 0, &dri);
}

iANY LOCALF TBC_movecur(HWND hwnd, I4B op, BOOL rd)
{ // 僇儗儞僩僙儖偺憡懳堏摦
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B ns, sw;
  POSI b, c;
  RECT rcc, rct;

  GetClientRect(hwnd, &rcc);
  ns = nscroll(ce, &rcc);
  if (rd) {
    c = *(rPOSI)&ce->cr;
    b = *(rPOSI)&ce->br;
  }
  sw = (((op & MVC_SEL) == 0) != ((ce->flg & TBCS_SEL) == 0));
  tbc_setsel(hwnd, (op & MVC_SEL) != 0, FALSE);
  switch (op & 0x00ff) {
  case MVC_LFT:
    if (ce->cc > 0) { ce->cc--;}
    break;
  case MVC_RGT:
    if (ce->cc < ce->nc - 1) { ce->cc++;}
    break;
  case MVC_HOM:
    ce->cc = 0;
    break;
  case MVC_END:
    ce->cc = ce->nc - 1;
    break;
  }
  switch (op & 0xff00) {
  case MVC_LUP:
    if (ce->cr > 0) { ce->cr--;}
    break;
  case MVC_LDN:
    if (ce->cr < ce->nr - 1) { ce->cr++;}
    break;
  case MVC_PUP:
    if (ce->br > ce->fr + ns) { ce->br -= ns;} else { ce->br = ce->fr;}
    if (ce->cr > ns) { ce->cr -= ns;} else { ce->cr = 0;}
    break;
  case MVC_PDN:
    if (ce->br < ce->nr - ns) { ce->br += ns;} else { ce->br = ce->nr - 1;}
    if (ce->cr < ce->nr - ns) { ce->cr += ns;} else { ce->cr = ce->nr - 1;}
    break;
  case MVC_TOP:
    ce->cr = 0;
    break;
  case MVC_BTM:
    ce->cr = ce->nr - 1;
    break;
  }
  tbc_setsel(hwnd, (op & MVC_SEL) != 0, FALSE);
  if (rd) {
    if (ce->cr >= ce->fr && ce->cr < ce->br) {
      ce->br = ce->cr;
    } else if (ns > 0 && ce->cr >= ce->br + ns) {
      ce->br = ce->cr - ns + 1;
    }
    if (ce->cc >= ce->fc && ce->cc < ce->bc) {
      ce->bc = ce->cc;
    } else {
      while (lastcol(ce, &rcc, ce->bc) < ce->cc) { ce->bc++;}
    }
    if (ce->br != b.ir || ce->bc != b.ic || sw || ((ce->flg & TBCS_LST) && (ce->cr != c.ir))) {
      RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
    } else if (ce->cr != c.ir || ce->cc != c.ic) {
      if (!isremp(&ce->rr)) {
        tbc_getrblkrect(hwnd, &ce->rr, &rct);
        RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
        setremp(&ce->rr);
      }
      tbc_movecellptr(hwnd, (rPOSI)&ce->cr, &c);
    }
  }
  return 0;
}

iANY LOCALF TBC_insertrblk(HWND hwnd);

iANY LOCALF TBC_inputtext(HWND hwnd, rPOSI lc, rSTR bf)
{ // 僥僉僗僩擖椡
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B fmt;
  RBLK r;
  RECT rct;

  if ((ce->flg & (TBCS_DED|TBCS_LST))) return 0;
  fmt = tbc_getcellformat(hwnd, lc); if (fmt & DC_DED) return 0;
  if (fmt & DC_BLA) {
    if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, FALSE);}
    tbc_setsel(hwnd, TRUE, FALSE);
    TBC_insertrblk(hwnd);
    tbc_update(hwnd, FALSE, TRUE);
  }
  SendMessage(hwnd, TBCM_SETCELLTEXT, (uANY)lc, (iANY)bf);
  r.r1 = r.r2 = lc->ir;
  tbc_getrblkrect(hwnd, &r, &rct);
  RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  ParentNotify(hwnd, APPN_CHANGE, OPR_UPDATE);
  return 0;
}

iANY LOCALF TBC_asknrows(HWND hwnd)
{ // 峴悢偺栤偄崌傢偣
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  return ce->vw? NViewRows(ce->vw) + !(ce->flg & (TBCS_DSE|TBCS_LST)): 1;
}

iANY LOCALF TBC_askncolumns(HWND hwnd)
{ // 楍悢偺栤偄崌傢偣
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  return ce->vw? NViewColumns(ce->vw): 1;
}

iANY LOCALF TBC_askcolumnlength(HWND hwnd, I4B ic)
{ // 楍偺寘悢偺栤偄崌傢偣
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  return ce->vw? ViewColumnWidthF(ce->vw, ic): DEFCWID;
}

iANY LOCALF TBC_defcellformat(HWND hwnd, rPOSI lc)
{ // 僙儖偺昤夋懏惈婛掕抣
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B fmt = 0;

  if (lc->ir < 0) {
    fmt |= DC_CHD;
  } else if (lc->ir < ce->nr) {
    if ((ce->flg & TBCS_SEL) && (lc->ir >= ce->rs.r1 && lc->ir <= ce->rs.r2)) { fmt |= DC_SEL;}
    if (!(ce->flg & (TBCS_DSE|TBCS_LST)) && ce->nr > 0 && lc->ir == ce->nr - 1) { fmt |= DC_BLA;}
    if (lc->ir == ce->cr) { fmt |= DC_CUR;}
    if (ce->fr > 0 && lc->ir == ce->fr - 1) { fmt |= DC_FXR;}
  } else if (lc->ir < ce->nr + ce->tr) {
    fmt |= (DC_SMR|DC_DED);
  } else {
    fmt |= (DC_INR|DC_DED);
  }
  if (lc->ic < 0) {
    fmt |= DC_RHD;
  } else if (lc->ic < ce->nc) {
    if (lc->ic == ce->cc) { fmt |= DC_CUC;}
    if (ce->fc > 0 && lc->ic == ce->fc - 1) { fmt |= DC_FXC;}
  } else {
    fmt |= (DC_INC|DC_DED);
  }
  if (fmt == (DC_CHD|DC_RHD) && (ce->flg & TBCS_DED)) { fmt |= DC_RDO;}
  return fmt;
}

iANY LOCALF TBC_askcellformat(HWND hwnd, rPOSI lc)
{ // 僙儖偺昤夋懏惈偺栤偄崌傢偣
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B flg, fmt = 0;

  if (!ce->vw) return 0;
  if (lc->ir < 0) {
    fmt |= DC_CEN;
  } else if (lc->ir < ce->nr + ce->tr) {
    fmt |= ViewColumnTextAlignF(ce->vw, lc->ic);
    flg = ViewColumnFlagsF(ce->vw, lc->ic);
    if ((flg & CF_DDL) && !(ce->flg & TBCS_DDD)) { fmt |= DC_DDL;}
    if ((flg & CF_DDN) && !(ce->flg & TBCS_DDD)) { fmt |= DC_DDN;}
    if (flg & CF_LNK) { fmt |= DC_LNK;}
    if (flg & (CF_HCH|CF_RDO|CF_DED)) { fmt |= DC_DED;}
  }
  return fmt;
}

iANY LOCALF TBC_getcellformat(HWND hwnd, rPOSI lc)
{ // 僙儖偺昤夋懏惈偺庢摼
  return SendMessage(hwnd, TBCM_DEFCELLFORMAT, (uANY)lc, 0) | SendMessage(hwnd, TBCM_ASKCELLFORMAT, (uANY)lc, 0);
}

iANY LOCALF TBC_setcelltext(HWND hwnd, rPOSI lc, rSTR st)
{ // 僙儖僥僉僗僩偺愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (!st || !ce->vw) return 0;
  ScanViewCellValueF(ce->vw, lc->ir, lc->ic, st);
  return 0;
}

iANY LOCALF TBC_getcelltext(HWND hwnd, rPOSI lc, pSTR st)
{ // 僙儖僥僉僗僩偺庢摼
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B flg;

  if (!st) return 0;
  if (!ce->vw) { st[0] = '\0'; return 0;}
  flg = (ce->flg & TBCS_UCN)? PVF_NAM: (ce->flg & TBCS_UCI)? PVF_IDX: PVF_TIT;
  flg |= (ce->flg & TBCS_ZBI)? PVF_ZBI: PVF_OBI;
  PrintViewCellValueF(st, ce->vw, lc->ir, lc->ic, flg);
  return 0;
}

iANY LOCALF TBC_changeview(HWND hwnd, rVIWI pc, BOOL rd)
{ // 價儏乕偺曄峏
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c;

  if (!ce->vw || (ce->flg & TBCS_DCV)) return 0;
  ArrangeViewColumns(ce->vw, pc->arr);
  SelectViewRows(ce->vw, pc->cnd);
  SortViewRows(ce->vw, pc->srt);
  tbc_update(hwnd, TRUE, FALSE);
  c.ir = 0; c.ic = pc->fc;
  tbc_setfix(hwnd, &c, rd);
  return 0;
}

iANY LOCALF TBC_paint(HWND hwnd)
{ // 昤夋
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B bkm, bc, pc, ns;
  POSI c;
  HDC hdc, hmem;
  HBMP horg;
  HFNT hfnt;
  RECT rcc, rct;
  DRWI dri;
  PAINTSTRUCT ps;
  I1B bf[LBUF];

  GetClientRect(hwnd, &rcc);
  bc = ce->fc;
  pc = lastcol(ce, &rcc, bc) + 1;
  while (lastcol(ce, &rcc, bc) < ce->nc - 1) { bc++;}
  SetHScrollBar(hwnd, ce->fc, bc + pc - 1, pc, ce->bc);
  ns = nscroll(ce, &rcc);
  SetVScrollBar(hwnd, ce->fr, ce->nr + ns - 2, ns, ce->br);
  hdc = BeginPaint(hwnd, &ps);
  hmem = CreateCompatibleDC(hdc);
  horg = SelectObject(hmem, CreateCompatibleBitmap(hdc, rcc.rgt, rcc.btm));
  bkm = SetBkMode(hmem, TRANSPARENT);
  hfnt = SelectObject(hmem, ce->hfnt);
  SetDRWI(&dri, bf, hmem, &rct);
  for (c.ir = -ce->hr, rct.top = 0; rct.top < rcc.btm; rct.top += ce->rh, c.ir++) {
    if (c.ir == ce->fr) { c.ir = ce->br;}
    rct.btm = rct.top + ce->rh;
    if (ce->tr > 0 && c.ir < ce->nr && rct.btm + ce->tr * ce->rh >= rcc.btm) { c.ir = ce->nr;}
    for (c.ic = -ce->hc, rct.lft = 0; rct.lft < rcc.rgt; rct.lft += ce->cx[ce->hc + c.ic], c.ic++) {
      if (c.ic == ce->fc) { c.ic = ce->bc;}
      rct.rgt = (c.ic < ce->nc)? rct.lft + ce->cx[ce->hc + c.ic]: rcc.rgt;
      dri.fmt = tbc_getcellformat(hwnd, &c);
      tbc_getcelltext(hwnd, &c, dri.bf);
      tbc_drawcell(hwnd, &c, &dri);
      switch (dri.fmt & (DC_CHD|DC_RHD|DC_PTR)) {
      case DC_PTR: case DC_CHD|DC_CUC: case DC_RHD|DC_CUR:
        tbc_drawcellptr(hwnd, &c, &dri); break;
      }
      if (c.ic >= ce->nc) break;
    }
  }
  SelectObject(hmem, hfnt);
  SetBkMode(hmem, bkm);
  BitBlt(hdc, 0, 0, rcc.rgt, rcc.btm, hmem, 0, 0, SRCCOPY);
  DeleteObject(SelectObject(hmem, horg));
  DeleteDC(hmem);
  EndPaint(hwnd, &ps);
  return 0;
}

iANY LOCALF TBC_setfocus(HWND hwnd, uANY wpa)
{ // 僼僅乕僇僗愝掕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  tbc_movecellptr(hwnd, (rPOSI)&ce->cr, NULL);
  if (IsWindow(ce->hedi) && (HWND)wpa == ce->hedi) return 0;
  ParentNotify(hwnd, APPN_SETFOCUS, 0);
  return 0;
}

iANY LOCALF TBC_killfocus(HWND hwnd, uANY wpa)
{ // 僼僅乕僇僗夝彍
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (IsWindow(ce->hedi) && (HWND)wpa == ce->hedi) return 0;
  ParentNotify(hwnd, APPN_KILLFOCUS, 0);
  return 0;
}

iANY LOCALF TBC_clearcell(HWND hwnd)
{ // 僇儗儞僩僙儖傪僋儕傾
  return tbc_inputtext(hwnd, (rPOSI)&((pTBCE)GetWindowLong(hwnd, 0))->cr, "");
}

iANY LOCALF TBC_copycell(HWND hwnd)
{ // 僇儗儞僩僙儖傪僋儕僢僾儃乕僪偵僐僺乕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  HGLOBAL hg;
  I1B bf[LBUF];

  tbc_getcelltext(hwnd, (rPOSI)&ce->cr, bf);
  hg = GlobalAlloc(GHND, strlen(bf) + 1); if (!hg) return 0;
  strcpys(GlobalLock(hg), bf); GlobalUnlock(hg);
  if (!OpenClipboard(hwnd)) { GlobalFree(hg); return 0;}
  EmptyClipboard();
  SetClipboardData(CF_TEXT, hg);
  CloseClipboard();
  return 0;
}

iANY LOCALF TBC_cutcell(HWND hwnd)
{ // 僇儗儞僩僙儖傪僋儕僢僾儃乕僪偵僐僺乕偟偰僋儕傾
  TBC_copycell(hwnd);
  return TBC_clearcell(hwnd);
}

iANY LOCALF TBC_pastecell(HWND hwnd)
{ // 僋儕僢僾儃乕僪偐傜僇儗儞僩僙儖偵揬傝晅偗
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  HGLOBAL hg;
  I1B bf[LBUF];

  if (ce->flg & (TBCS_DED|TBCS_LST)) return 0;
  if (!OpenClipboard(hwnd)) return 0;
  hg = GetClipboardData(CF_TEXT); if (!hg) { CloseClipboard(); return 0;}
  strcpyn(bf, GlobalLock(hg), sizeof(bf) - 1); GlobalUnlock(hg);
  CloseClipboard();
  return tbc_inputtext(hwnd, (rPOSI)&ce->cr, bf);
}

iANY LOCALF TBC_setcurrow(HWND hwnd, HBUF rb)
{ // 峴僶僢僼傽偺撪梕傪僇儗儞僩峴偵僐僺乕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;
  RECT rct;

  if (!ce->vw || (ce->flg & (TBCS_DED|TBCS_LST))) return 0;
  SetTableRow(ViewHTBL(ce->vw), ViewRowIndex(ce->vw, ce->cr), rb);
  r.r1 = r.r2 = ce->cr;
  tbc_getrblkrect(hwnd, &r, &rct);
  RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  ParentNotify(hwnd, APPN_CHANGE, OPR_UPDATE);
  return 0;
}

iANY LOCALF TBC_getcurrow(HWND hwnd, HBUF rb)
{ // 僇儗儞僩峴偺撪梕傪峴僶僢僼傽偵僐僺乕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;
  RECT rct;

  if (!ce->vw || (ce->flg & (TBCS_DED|TBCS_LST))) return 0;
  if (ce->cr == NViewRows(ce->vw)) {
    if (!InsertViewRow(ce->vw, ce->cr)) return 0;
    tbc_update(hwnd, FALSE, FALSE);
    r.r1 = ce->cr; r.r2 = ce->cr + 1;
    tbc_getrblkrect(hwnd, &r, &rct);
    RedrawWindow(hwnd, &rct, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
    ParentNotify(hwnd, APPN_CHANGE, OPR_INSERT);
  }
  GetTableRow(rb, ViewHTBL(ce->vw), ViewRowIndex(ce->vw, ce->cr));
  return 0;
}

iANY LOCALF TBC_insertrblk(HWND hwnd)
{ // 峴僽儘僢僋偺憓擖
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c;
  RBLK r;

  if (!ce->vw || (ce->flg & TBCS_DSE) || !TBC_getsel(hwnd, &r)) return 0;
  InsertViewRows(ce->vw, r.r1, r.r2 - r.r1 + 1);
  tbc_update(hwnd, FALSE, TRUE);
  c.ir = r.r1; c.ic = ce->cc;
  tbc_setcur(hwnd, &c, TRUE);
  ParentNotify(hwnd, APPN_CHANGE, OPR_INSERT);
  return 0;
}

iANY LOCALF TBC_deleterblk(HWND hwnd)
{ // 峴僽儘僢僋偺嶍彍
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;

  if (!ce->vw || (ce->flg & TBCS_DSE) || !TBC_getsel(hwnd, &r)) return 0;
  DeleteViewRows(ce->vw, r.r1, r.r2 - r.r1 + 1);
  tbc_update(hwnd, FALSE, TRUE);
  ParentNotify(hwnd, APPN_CHANGE, OPR_DELETE);
  return 0;
}

iANY LOCALF TBC_clearrblk(HWND hwnd)
{ // 峴僽儘僢僋偺僋儕傾
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;

  if (!ce->vw || (ce->flg & TBCS_DSE) || !TBC_getsel(hwnd, &r)) { return TBC_clearcell(hwnd);}
  ClearViewRows(ce->vw, r.r1, r.r2 - r.r1 + 1);
  tbc_setsel(hwnd, FALSE, TRUE);
  ParentNotify(hwnd, APPN_CHANGE, OPR_UPDATE);
  return 0;
}

iANY LOCALF TBC_copyrblk(HWND hwnd, BOOL sw)
{ // 峴僽儘僢僋傪僋儕僢僾儃乕僪偵僐僺乕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B nr;
  RBLK r;
  HGLOBAL hg;

  if (!ce->vw || (ce->flg & TBCS_DSE) || !TBC_getsel(hwnd, &r)) { return TBC_copycell(hwnd);}
  nr = NViewRows(ce->vw);
  hg = GlobalAlloc(GHND, RowBlkSize(ce->vw, r.r2 - r.r1 + 1)); if (!hg) goto _10;
  CopyRowBlk(GlobalLock(hg), ce->vw, r.r1, r.r2 - r.r1 + 1); GlobalUnlock(hg);
  if (!OpenClipboard(hwnd)) { GlobalFree(hg); goto _10;}
  EmptyClipboard();
  SetClipboardData(CF_BOLRBLK, hg);
  CloseClipboard(); _10:
  if (sw) { tbc_setsel(hwnd, FALSE, TRUE);}
  return 0;
}

iANY LOCALF TBC_cutrblk(HWND hwnd)
{ // 峴僽儘僢僋傪僋儕僢僾儃乕僪偵僐僺乕偟偰嶍彍
  if (!(((pTBCE)GetWindowLong(hwnd, 0))->flg & TBCS_SEL)) { return TBC_cutcell(hwnd);}
  TBC_copyrblk(hwnd, FALSE);
  return TBC_deleterblk(hwnd);
}

iANY LOCALF TBC_pasterblk(HWND hwnd)
{ // 僋儕僢僾儃乕僪偐傜峴僽儘僢僋傪憓擖僐僺乕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  RBLK r;
  HGLOBAL hg;

  if (!ce->vw || (ce->flg & TBCS_DSE) || !TBC_getsel(hwnd, &r)) { return TBC_pastecell(hwnd);}
  if (!OpenClipboard(hwnd)) return 0;
  hg = GetClipboardData(CF_BOLRBLK); if (!hg) goto _10;
  InsertRowBlk(ce->vw, r.r1, GlobalLock(hg)); GlobalUnlock(hg); _10:
  CloseClipboard();
  tbc_update(hwnd, FALSE, TRUE);
  ParentNotify(hwnd, APPN_CHANGE, OPR_INSERT);
  return 0;
}

iANY LOCALF TBC_search(HWND hwnd, rSTR st, I4B flg, BOOL sw)
{ // 暥帤楍専嶕
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c;

  if (!ce->vw) return 0;
  tbc_setsel(hwnd, FALSE, TRUE);
  c = *(rPOSI)&ce->cr;
  c.ir = SearchViewCellText(ce->vw, c.ir + sw, c.ic, st, flg);
  if (c.ir >= 0) { tbc_setcur(hwnd, &c, TRUE);}
  return 0;
}

iANY LOCALF TBC_hscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悈暯僗僋儘乕儖
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B bc, pc;
  RECT rcc;

  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  GetClientRect(hwnd, &rcc);
  switch (LOU2B(wpa)) {
  case SB_LINELEFT:
  case SB_PAGELEFT:
    if (ce->bc > ce->fc) { ce->bc--;}
    break;
  case SB_LINERIGHT:
  case SB_PAGERIGHT:
    if (lastcol(ce, &rcc, ce->bc) < ce->nc - 1) { ce->bc++;}
    break;
  case SB_THUMBPOSITION: goto _10;
  case SB_THUMBTRACK: rd = FALSE; _10:
    ce->bc = HIU2B(wpa);
    break;
  }
  bc = ce->fc;
  pc = lastcol(ce, &rcc, bc) + 1;
  while (lastcol(ce, &rcc, bc) < ce->nc - 1) { bc++;}
  SetHScrollBar(hwnd, ce->fc, bc + pc - 1, pc, ce->bc);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_vscroll(HWND hwnd, uANY wpa, BOOL rd)
{ // 悅捈僗僋儘乕儖
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B ns;
  RECT rcc;

  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  GetClientRect(hwnd, &rcc);
  ns = nscroll(ce, &rcc);
  switch (LOU2B(wpa)) {
  case SB_LINEUP:
    if (ce->br > ce->fr) { ce->br--;}
    break;
  case SB_LINEDOWN:
    if (ce->br < ce->nr - 1) { ce->br++;}
    break;
  case SB_PAGEUP:
    if (ce->br > ce->fr + ns) { ce->br -= ns;} else { ce->br = ce->fr;}
    break;
  case SB_PAGEDOWN:
    if (ce->br < ce->nr - ns) { ce->br += ns;} else { ce->br = ce->nr - 1;}
    break;
  case SB_THUMBPOSITION: goto _10;
  case SB_THUMBTRACK: rd = FALSE; _10:
    ce->br = HIU2B(wpa);
    break;
  }
  SetVScrollBar(hwnd, ce->fr, ce->nr + ns - 2, ns, ce->br);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_mousewheel(HWND hwnd, uANY wpa)
{ // 儅僂僗儂僀乕儖
  I4B dy, rd = FALSE;

  dy = (I2B)HIU2B(wpa);
  if (dy >= WHEEL_SENS) {
    do { TBC_vscroll(hwnd, SB_LINEUP,   FALSE);} while ((dy -= WHEEL_SENS) >= WHEEL_SENS);
    rd = TRUE;
  } else if (dy <= -WHEEL_SENS) {
    do { TBC_vscroll(hwnd, SB_LINEDOWN, FALSE);} while ((dy += WHEEL_SENS) <= -WHEEL_SENS);
    rd = TRUE;
  }
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TBC_mousemove(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗堏摦
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c, p;

  if ((ce->flg & (TBCS_CAP|TBCS_SEL)) != (TBCS_CAP|TBCS_SEL) || !TBC_hittest(hwnd, &p, lpa)) return 0;
  if (p.ir >= 0 && (p.ir != ce->cr || p.ic != ce->cc)) {
    c = *(rPOSI)&ce->cr;
    if (p.ic >= 0) { *(pPOSI)&ce->cr = p;} else { ce->cr = p.ir;}
    tbc_setsel(hwnd, TRUE, TRUE);
    tbc_movecellptr(hwnd, (rPOSI)&ce->cr, &c);
  }
  return 0;
}

iANY LOCALF TBC_lbuttondown(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗嵍儃僞儞墴壓
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c, p;

  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  ParentNotify(hwnd, APPN_LBUTTONDOWN, lpa);
  if (!TBC_hittest(hwnd, &p, lpa)) return 0;
  if (p.ir == ce->cr && p.ic == ce->cc && TBC_dropbutton(hwnd, &p, lpa)) {
    TBC_editcell(hwnd);
    return 0;
  }
  if (ce->flg & TBCS_LST) {
    if (p.ir >= 0) {
      ce->cr = p.ir;
      tbc_setsel(hwnd, TRUE, TRUE);
    }
    return 0;
  }
  ce->flg |= TBCS_CAP;
  SetCapture(hwnd);
  c = *(rPOSI)&ce->cr;
  if (p.ir >= 0) {
    if (p.ic >= 0) { *(pPOSI)&ce->cr = p;} else { ce->cr = p.ir;}
    if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, FALSE);}
    tbc_setsel(hwnd, (wpa & MK_SHIFT) || p.ic < 0, TRUE);
  } else {
    if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, TRUE);}
  }
  tbc_movecellptr(hwnd, (rPOSI)&ce->cr, &c);
  return 0;
}

iANY LOCALF TBC_lbuttonup(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗嵍儃僞儞夝曻
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (ce->flg & TBCS_CAP) {
    ce->flg &=~TBCS_CAP;
    ReleaseCapture();
  }
  return 0;
}

iANY LOCALF TBC_lbuttondblclk(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗嵍儃僞儞僟僽儖僋儕僢僋
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI p;

  if (!TBC_hittest(hwnd, &p, lpa) || p.ir < 0 || p.ic < 0) return 0;
  if (ce->flg & TBCS_LST) {
    ce->cr = p.ir;
    tbc_setsel(hwnd, TRUE, TRUE);
    ParentNotify(hwnd, APPN_LBUTTONDBLCLK, lpa);
    return 0;
  }
  if (tbc_getcellformat(hwnd, (rPOSI)&ce->cr) & DC_LNK) {
    TBC_openlink(hwnd);
  } else {
    TBC_editcell(hwnd);
  }
  return 0;
}

iANY LOCALF TBC_rbuttondown(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗塃儃僞儞墴壓
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  POSI c, p;

  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  ParentNotify(hwnd, APPN_RBUTTONDOWN, lpa);
  if (!TBC_hittest(hwnd, &p, lpa)) return 0;
  if (p.ir == ce->cr && p.ic == ce->cc && TBC_dropbutton(hwnd, &p, lpa)) {
    TBC_editcell(hwnd);
    return 0;
  }
  if (ce->flg & TBCS_LST) {
    if (p.ir >= 0) {
      ce->cr = p.ir;
      tbc_setsel(hwnd, TRUE, TRUE);
    }
    return 0;
  }
  c = *(rPOSI)&ce->cr;
  if (p.ir >= 0) {
    if (!(ce->flg & TBCS_SEL) || p.ir < ce->rs.r1 || p.ir > ce->rs.r2) {
      if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, TRUE);}
      if (p.ic >= 0) { *(pPOSI)&ce->cr = p;} else { ce->cr = p.ir;}
      if (p.ic < 0) { tbc_setsel(hwnd, TRUE, TRUE);}
    }
  } else {
    if (ce->flg & TBCS_SEL) { tbc_setsel(hwnd, FALSE, TRUE);}
  }
  tbc_movecellptr(hwnd, (rPOSI)&ce->cr, &c);
  SendMessage(hwnd, TBCM_TRACKPOPUP, (uANY)&p, 0);
  return 0;
}

iANY LOCALF TBC_keydown(HWND hwnd, uANY wpa, iANY lpa)
{ // 僉乕憖嶌
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B ks = KEYSTATE();

  if (ce->flg & TBCS_LST) goto _30;
  switch (wpa) {
  case VK_TAB:
    if (!ks) { _10:
    if (ce->cc < ce->nc - 1) { return tbc_movecur(hwnd, MVC_RGT, TRUE);}
      if ((ce->flg & TBCS_UNM) && ce->cr == ce->nr - 1) {
        SendMessage(GetParent(hwnd), WM_NEXTDLGCTL, 0, 0); return 0;
      }
      return tbc_movecur(hwnd, MVC_HOM|MVC_LDN, TRUE);
    } else if (ks = KS_SFT) {
      if (ce->cc > 0) { return tbc_movecur(hwnd, MVC_LFT, TRUE);}
      if ((ce->flg & TBCS_UNM) && ce->cr == 0) {
        SendMessage(GetParent(hwnd), WM_NEXTDLGCTL, 1, 0); return 0;
      }
      return tbc_movecur(hwnd, MVC_END|MVC_LUP, TRUE);
    }
    break;
  case VK_RETURN:
    if (ks & KS_CTL) break;
    if (ks & KS_SFT) { return tbc_setsel(hwnd, TRUE, TRUE);}
    if (ce->flg & TBCS_EMD) { return tbc_movecur(hwnd, MVC_LDN, TRUE);}
    goto _10;
  case VK_LEFT:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_LFT|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_RIGHT:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_RGT|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_UP:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_LUP|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_DOWN:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_LDN|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_HOME:
    return tbc_movecur(hwnd, MVC_HOM|((ks & KS_CTL)? MVC_TOP: 0)|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_END:
    return tbc_movecur(hwnd, MVC_END|((ks & KS_CTL)? MVC_BTM: 0)|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_PRIOR:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_PUP|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_NEXT:
    if (ks & KS_CTL) break;
    return tbc_movecur(hwnd, MVC_PDN|((ks & KS_SFT)? MVC_SEL: 0), TRUE);
  case VK_DELETE:
    if (!ks) { return TBC_clearrblk(hwnd);} else break;
  case '2':
    if (ks == (KS_CTL|KS_SFT)) goto _20; else break;
  case 'C':
    if (ks & KS_CTL) { return TBC_copyrblk(hwnd, TRUE);} else break;
  case 'D':
    if (ks & KS_CTL) { return TBC_deleterblk(hwnd);} else break;
  case 'E':
    if (ks & KS_CTL) { return TBC_insertrblk(hwnd);} else break;
  case 'V':
    if (ks & KS_CTL) { return TBC_pasterblk(hwnd);} else break;
  case 'X':
    if (ks & KS_CTL) { return TBC_cutrblk(hwnd);} else break;
  case VK_F2:
    if (!ks) { return TBC_editcell(hwnd);} else break;
  case VK_F4:
    if (!ks) { _20: return TBC_copyeditcell(hwnd);} else break;
  }
  return 0;

 _30:
  switch (wpa) {
  case VK_LEFT:
  case VK_UP:
    return tbc_movecur(hwnd, MVC_LUP|MVC_SEL, TRUE);
  case VK_RIGHT:
  case VK_DOWN:
    return tbc_movecur(hwnd, MVC_LDN|MVC_SEL, TRUE);
  case VK_HOME:
    return tbc_movecur(hwnd, MVC_TOP|MVC_SEL, TRUE);
  case VK_END:
    return tbc_movecur(hwnd, MVC_BTM|MVC_SEL, TRUE);
  case VK_PRIOR:
    return tbc_movecur(hwnd, MVC_PUP|MVC_SEL, TRUE);
  case VK_NEXT:
    return tbc_movecur(hwnd, MVC_PDN|MVC_SEL, TRUE);
  }
  return 0;
}

iANY LOCALF TBC_char(HWND hwnd, uANY wpa, iANY lpa)
{ // 暥帤擖椡
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  DRWI dri;
  I1B bf[LBUF];
  static U1B zen[2];

  if (ce->flg & (TBCS_DED|TBCS_LST)) return 0;
  SetDRWI(&dri, bf, NULL, NULL);
  dri.fmt = tbc_getcellformat(hwnd, (rPOSI)&ce->cr) &~DC_DDN;
  if (zen[0] && iszen2((rSTR)&wpa)) {
    zen[1] = (U1B)wpa; dri.bf[0] = '\0';
    TBC_openedit(hwnd, *(rU2B)zen, &dri);
    zen[0] = 0;
  } else if (isprn((rSTR)&wpa)) {
    if (wpa == ' ') { wpa = 0; tbc_getcelltext(hwnd, (rPOSI)&ce->cr, dri.bf);}
    TBC_openedit(hwnd, wpa, &dri);
  } else if (iszen1((rSTR)&wpa)) {
    zen[0] = (U1B)wpa;
  }
  return 0;
}

iANY LOCALF TBC_imestart(HWND hwnd)
{ // 俬俵俤擖椡奐巒
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);
  I4B nc;
  HIMC himc;
  DRWI dri;
  I1B bf[LBUF];

  if (ce->flg & (TBCS_DED|TBCS_LST)) return 0;
  SetDRWI(&dri, bf, NULL, NULL);
  dri.fmt = tbc_getcellformat(hwnd, (rPOSI)&ce->cr) &~DC_DDN;
  himc = ImmGetContext(hwnd);
  nc = ImmGetCompositionString(himc, GCS_COMPSTR, NULL, 0);
  ImmReleaseContext(hwnd, himc);
  if (nc == 0) { tbc_getcelltext(hwnd, (rPOSI)&ce->cr, dri.bf);}
  TBC_openedit(hwnd, 0, &dri);
  if (IsWindow(ce->hedi)) { SendMessage(ce->hedi, WM_IME_STARTCOMPOSITION, 0, 0);}
  return 0;
}

iANY LOCALF TBC_destroy(HWND hwnd)
{ // 昞僂傿儞僪僂廔椆張棟
  pTBCE ce = (pTBCE)GetWindowLong(hwnd, 0);

  if (IsWindow(ce->hedi)) { DestroyWindow(ce->hedi);}
  if (ce->vw) { DeleteView(ce->vw);}
  DeleteObject(ce->hfnt);
  hfree(ce->cx);
  hfree(ce);
  return 0;
}

iANY WINAPI DefBOLTBLProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return TBC_create(hwnd, lpa);
  case TBCM_SETMODE:
    return TBC_setmode(hwnd, wpa, lpa);
  case TBCM_GETMODE:
    return ((pTBCE)GetWindowLong(hwnd, 0))->flg;
  case TBCM_SETTABLE:
    return TBC_settable(hwnd, (pANY)wpa, lpa);
  case TBCM_GETTABLE:
    return TBC_gettable(hwnd);
  case TBCM_SETNROWS:
    return TBC_setnrows(hwnd, wpa);
  case TBCM_GETNROWS:
    return ((pTBCE)GetWindowLong(hwnd, 0))->nr;
  case TBCM_SETNCOLUMNS:
    return TBC_setncolumns(hwnd, wpa);
  case TBCM_GETNCOLUMNS:
    return ((pTBCE)GetWindowLong(hwnd, 0))->nc;
  case TBCM_SETCOLUMNWIDTH:
    return TBC_setcolumnwidth(hwnd, wpa, lpa);
  case TBCM_GETCOLUMNWIDTH:
    return TBC_getcolumnwidth(hwnd, wpa);
  case WM_SETFONT:
    return TBC_setfont(hwnd, (HFNT)wpa, lpa);
  case WM_GETFONT:
    return (iANY)((pTBCE)GetWindowLong(hwnd, 0))->hfnt;
  case TBCM_SETAVECHARWIDTH:
    return TBC_setavecharwidth(hwnd, wpa);
  case TBCM_GETAVECHARWIDTH:
    return ((pTBCE)GetWindowLong(hwnd, 0))->cw;
  case TBCM_SETROWHEIGHT:
    return TBC_setrowheight(hwnd, wpa);
  case TBCM_GETROWHEIGHT:
    return ((pTBCE)GetWindowLong(hwnd, 0))->rh;
  case TBCM_GETCELLRECT:
    return TBC_getcellrect(hwnd, (rPOSI)wpa, (pRECT)lpa);
  case TBCM_GETRBLKRECT:
    return TBC_getrblkrect(hwnd, (rRBLK)wpa, (pRECT)lpa);
  case TBCM_DRAWCELL:
    return TBC_drawcell(hwnd, (rPOSI)wpa, (rDRWI)lpa);
  case TBCM_DRAWCELLPTR:
    return TBC_drawcellptr(hwnd, (rPOSI)wpa, (rDRWI)lpa);
  case TBCM_MOVECELLPTR:
    return TBC_movecellptr(hwnd, (rPOSI)wpa, (rPOSI)lpa);
  case TBCM_HITTEST:
    return TBC_hittest(hwnd, (pPOSI)wpa, lpa);
  case TBCM_DROPBUTTON:
    return TBC_dropbutton(hwnd, (rPOSI)wpa, lpa);
  case TBCM_OPENLINK:
    return TBC_openlink(hwnd);
  case TBCM_OPENEDIT:
    return TBC_openedit(hwnd, wpa, (pDRWI)lpa);
  case TBCM_CLOSEEDIT:
    return TBC_closeedit(hwnd, (rSTR)wpa);
  case TBCM_SETCUR:
    return TBC_setcur(hwnd, (rPOSI)wpa, lpa);
  case TBCM_GETCUR:
    *(pPOSI)wpa = *(rPOSI)&((pTBCE)GetWindowLong(hwnd, 0))->cr; return 0;
  case TBCM_SETTOP:
    return TBC_settop(hwnd, (rPOSI)wpa, lpa);
  case TBCM_GETTOP:
    *(pPOSI)wpa = *(rPOSI)&((pTBCE)GetWindowLong(hwnd, 0))->br; return 0;
  case TBCM_SETFIX:
    return TBC_setfix(hwnd, (rPOSI)wpa, lpa);
  case TBCM_GETFIX:
    *(pPOSI)wpa = *(rPOSI)&((pTBCE)GetWindowLong(hwnd, 0))->fr; return 0;
  case TBCM_SETSEL:
    return TBC_setsel(hwnd, wpa, lpa);
  case TBCM_GETSEL:
    return TBC_getsel(hwnd, (pRBLK)wpa);
  case TBCM_UPDATE:
    return TBC_update(hwnd, wpa, lpa);
  case TBCM_CALCSIZE:
    return TBC_calcsize(hwnd, (rPOSI)wpa, (pRECT)lpa);
  case TBCM_EDITCELL:
    return TBC_editcell(hwnd);
  case TBCM_COPYEDITCELL:
    return TBC_copyeditcell(hwnd);
  case TBCM_MOVECUR:
    return TBC_movecur(hwnd, wpa, lpa);
  case TBCM_INPUTTEXT:
    return TBC_inputtext(hwnd, (rPOSI)wpa, (rSTR)lpa);
  case TBCM_ASKNROWS:
    return TBC_asknrows(hwnd);
  case TBCM_ASKNCOLUMNS:
    return TBC_askncolumns(hwnd);
  case TBCM_ASKCOLUMNLENGTH:
    return TBC_askcolumnlength(hwnd, wpa);
  case TBCM_DEFCELLFORMAT:
    return TBC_defcellformat(hwnd, (rPOSI)wpa);
  case TBCM_ASKCELLFORMAT:
    return TBC_askcellformat(hwnd, (rPOSI)wpa);
  case TBCM_GETCELLFORMAT:
    return TBC_getcellformat(hwnd, (rPOSI)wpa);
  case TBCM_SETCELLTEXT:
    return TBC_setcelltext(hwnd, (rPOSI)wpa, (rSTR)lpa);
  case TBCM_GETCELLTEXT:
    return TBC_getcelltext(hwnd, (rPOSI)wpa, (pSTR)lpa);
  case TBCM_CHANGEVIEW:
    return TBC_changeview(hwnd, (rVIWI)wpa, lpa);
  case TBCM_GETVIEW:
    return (iANY)((pTBCE)GetWindowLong(hwnd, 0))->vw;
  case WM_ERASEBKGND:
    return 1;
  case WM_PAINT:
    return TBC_paint(hwnd);
  case WM_SETFOCUS:
    return TBC_setfocus(hwnd, wpa);
  case WM_KILLFOCUS:
    return TBC_killfocus(hwnd, wpa);
  case WM_GETDLGCODE:
    return (((pTBCE)GetWindowLong(hwnd, 0))->flg & TBCS_LST)? DLGC_WANTARROWS: DLGC_WANTALLKEYS;
  case WM_CLEAR:
    return TBC_clearcell(hwnd);
  case WM_COPY:
    return TBC_copycell(hwnd);
  case WM_CUT:
    return TBC_cutcell(hwnd);
  case WM_PASTE:
    return TBC_pastecell(hwnd);
  case TBCM_SETCURROW:
    return TBC_setcurrow(hwnd, (HBUF)wpa);
  case TBCM_GETCURROW:
    return TBC_getcurrow(hwnd, (HBUF)wpa);
  case TBCM_INSERT:
    return TBC_insertrblk(hwnd);
  case TBCM_DELETE:
    return TBC_deleterblk(hwnd);
  case TBCM_CLEAR:
    return TBC_clearrblk(hwnd);
  case TBCM_COPY:
    return TBC_copyrblk(hwnd, TRUE);
  case TBCM_CUT:
    return TBC_cutrblk(hwnd);
  case TBCM_PASTE:
    return TBC_pasterblk(hwnd);
  case TBCM_SEARCH:
    return TBC_search(hwnd, (rSTR)wpa, lpa, 0);
  case TBCM_NSEARCH:
    return TBC_search(hwnd, (rSTR)wpa, lpa, 1);
  case TBCM_TRACKPOPUP:
    return 0;
  case WM_HSCROLL:
    return TBC_hscroll(hwnd, wpa, TRUE);
  case WM_VSCROLL:
    return TBC_vscroll(hwnd, wpa, TRUE);
  case WM_MOUSEWHEEL:
    return TBC_mousewheel(hwnd, wpa);
  case WM_MOUSEMOVE:
    return TBC_mousemove(hwnd, wpa, lpa);
  case WM_LBUTTONDOWN:
    return TBC_lbuttondown(hwnd, wpa, lpa);
  case WM_LBUTTONUP:
    return TBC_lbuttonup(hwnd, wpa, lpa);
  case WM_LBUTTONDBLCLK:
    return TBC_lbuttondblclk(hwnd, wpa, lpa);
  case WM_RBUTTONDOWN:
    return TBC_rbuttondown(hwnd, wpa, lpa);
  case WM_KEYDOWN:
    return TBC_keydown(hwnd, wpa, lpa);
  case WM_CHAR:
    return TBC_char(hwnd, wpa, lpa);
  case WM_IME_CHAR:
    return 0;
  case WM_IME_STARTCOMPOSITION:
    return TBC_imestart(hwnd);
  case WM_CLOSE:
    SendMessage(GetParent(hwnd), FRMM_DESTROYCHILD, (uANY)hwnd, 0); return 0;
  case WM_DESTROY:
    return TBC_destroy(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLTBLClass(HINSTANCE hinst)
{ // 昞僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
  wcx.lpfnWndProc   = DefBOLTBLProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 2 * sizeof(iANY);
  wcx.hInstance     = hinst;
  wcx.hIcon         = NULL;
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_3DFACE + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLTBL";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

  // 僼儗乕儉僂傿儞僪僂忣曬
typedef struct {
  HWND  *pi;  // -+
  I4B   ni;   //  |
  I4B   ca;   //  |= BLKE
  I4B   sz;   // -+
  I4B   tid;
  I4B   tbh;
  I4B   sid;
  I4B   sbh;
  I4B   flg;
  uANY  ext;
  U4B   rsv;
  HCURSOR hcur;
} FRME;
typedef FRME *pFRME, *PFRME;

iANY LOCALF FRM_create(HWND hwnd, iANY lpa)
{ // 僼儗乕儉僂傿儞僪僂奐巒張棟
  pFRMI fi = (pFRMI)((LPCREATESTRUCT)lpa)->lpCreateParams;
  pFRME fe;

  fe = halloc(sizeof(FRME), TRUE); if (!fe) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)fe);
  fe->ca = 16;
  fe->sz = sizeof(HWND);
  fe->pi = halloc(fe->ca * fe->sz, FALSE); if (!fe->pi) { ierr(E_MEM); return -1;}
  if (fi->ms) { SetMenu(hwnd, CreateMenuBar(fi->ms));}
  if (fi->ts) { fe->tid = fi->tid; fe->tbh = TOBWINH; CreateToolBar(hwnd, fi->tid, fi->ts);}
  if (fi->ss) { fe->sid = fi->sid; fe->sbh = STBWINH; CreateStatBar(hwnd, fi->sid, fi->ss);}
  fe->ext = fi->ext;
  fe->hcur = GetCursor();
  PostMessage(hwnd, FRMM_INITTOOL, 0, 0);
  return 0;
}

HWND LOCALF FRM_getchild(HWND hwnd, I4B i)
{ // 巕僂傿儞僪僂偺僀儞僨僢僋僗偐傜僴儞僪儖傪媮傔傞
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  return (i >= 0 && i < fe->ni)? fe->pi[i]: NULL;
}

I4B  LOCALF FRM_getindex(HWND hwnd, HWND hchi)
{ // 巕僂傿儞僪僂偺僴儞僪儖偐傜僀儞僨僢僋僗傪媮傔傞
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B i;

  for (i = 0; i < fe->ni; i++) {
    if (fe->pi[i] == hchi) { return i;}
  }
  return -1;
}

HWND LOCALF FRM_getactive(HWND hwnd)
{ // 傾僋僥傿僽僂傿儞僪僂
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  return (fe->ni > 0)? fe->pi[fe->ni - 1]: NULL;
}

void LOCALF SplitRect(pRECT r1, pRECT r2, rRECT pr, I4B flg)
{ // 夋柺暘妱
  switch (flg & (FRMS_TIL|FRMS_HRZ|FRMS_RGT)) {
  case FRMS_TIL|FRMS_VRT|FRMS_LFT:
    r1->lft = pr->lft; r1->top = pr->top; r1->rgt = (pr->lft + pr->rgt) / 2; r1->btm = pr->btm;
    r2->lft = (pr->lft + pr->rgt) / 2; r2->top = pr->top; r2->rgt = pr->rgt; r2->btm = pr->btm;
    break;
  case FRMS_TIL|FRMS_VRT|FRMS_RGT:
    r1->lft = (pr->lft + pr->rgt) / 2; r1->top = pr->top; r1->rgt = pr->rgt; r1->btm = pr->btm;
    r2->lft = pr->lft; r2->top = pr->top; r2->rgt = (pr->lft + pr->rgt) / 2; r2->btm = pr->btm;
    break;
  case FRMS_TIL|FRMS_HRZ|FRMS_UPR:
    r1->lft = pr->lft; r1->top = pr->top; r1->rgt = pr->rgt; r1->btm = (pr->top + pr->btm) / 2;
    r2->lft = pr->lft; r2->top = (pr->top + pr->btm) / 2; r2->rgt = pr->rgt; r2->btm = pr->btm;
    break;
  case FRMS_TIL|FRMS_HRZ|FRMS_LWR:
    r1->lft = pr->lft; r1->top = (pr->top + pr->btm) / 2; r1->rgt = pr->rgt; r1->btm = pr->btm;
    r2->lft = pr->lft; r2->top = pr->top; r2->rgt = pr->rgt; r2->btm = (pr->top + pr->btm) / 2;
    break;
  default:
    r1->lft = pr->lft; r1->top = pr->top; r1->rgt = pr->rgt; r1->btm = pr->btm;
    r2->lft = r2->rgt = pr->rgt; r2->top = r2->btm = pr->btm;
    break;
  }
}

#define  IsVisible(hwnd)  ((WindowStyle(hwnd) & WS_VISIBLE) != 0)

iANY LOCALF FRM_arrange(HWND hwnd, I4B op, HWND hchi)
{ // 巕僂傿儞僪僂偺嵞攝抲
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B i;
  HWND bact, bdsp, bdel, hact, hdsp;
  RECT rct, rc1, rc2;

  GetClientRect(hwnd, &rct);
  if (fe->tbh) { rct.top += fe->tbh;}
  if (fe->sbh) { rct.btm -= fe->sbh;}
  InflateRect(&rct, -2, -2);
  bact = (fe->ni > 0)? fe->pi[fe->ni - 1]: NULL;
  bdsp = (fe->ni > 1 && IsVisible(fe->pi[fe->ni - 2]))? fe->pi[fe->ni - 2]: NULL;
  bdel = NULL;
  switch (op) {
  case OPR_ACTIVATE:
    if ((i = FRM_getindex(hwnd, hchi)) >= 0) {
      MoveItemToLast((HBLK)fe, i);
    } else if (hchi) {
      AddItem((HBLK)fe, &hchi);
    } else if (fe->ni > 1) {
      MoveItemToFirst((HBLK)fe, fe->ni - 1);
    }
    break;
  case OPR_DESTROY:
    if ((i = FRM_getindex(hwnd, hchi)) >= 0) {
      DeleteItem((HBLK)fe, i);
      bdel = hchi;
    }
    break;
  }
  hact = (fe->ni > 0)? fe->pi[fe->ni - 1]: NULL;
  hdsp = (fe->ni > 1 && (fe->flg & FRMS_TIL))? fe->pi[fe->ni - 2]: NULL;
  SplitRect(&rc1, &rc2, &rct, hdsp? fe->flg: 0);
  if (bact) {
    if (bact != hact && bact != hdsp) { ShowWindow(bact, SW_HIDE);}
    if (bdsp) {
      if (bdsp != hact && bdsp != hdsp) { ShowWindow(bdsp, SW_HIDE);}
    }
  }
  if (bdel) { DestroyWindow(bdel);}
  if (hact) {
    MoveWindow(hact, rc1.lft + 1, rc1.top + 1, rc1.rgt - rc1.lft - 2, rc1.btm - rc1.top - 2, FALSE);
    ShowWindow(hact, SW_SHOW);
    RedrawWindow(hact, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
    SetFocus(hact);
    if (hdsp) {
      MoveWindow(hdsp, rc2.lft + 1, rc2.top + 1, rc2.rgt - rc2.lft - 2, rc2.btm - rc2.top - 2, FALSE);
      ShowWindow(hdsp, SW_SHOWNA);
      RedrawWindow(hdsp, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
    }
  }
  RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
  return 0;
}

iANY LOCALF FRM_activate(HWND hwnd, HWND hchi)
{ // 巕僂傿儞僪僂傪傾僋僥傿僽壔偡傞
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B i;

  if ((i = FRM_getindex(hwnd, hchi)) < 0) return 0;
  if (fe->ni > 1 && (fe->flg & FRMS_TIL) && i == fe->ni - 2) {
    if (!(fe->flg & FRMS_RGT)) { fe->flg |= FRMS_RGT;} else { fe->flg &=~FRMS_RGT;}
  }
  return FRM_arrange(hwnd, OPR_ACTIVATE, hchi);
}

iANY LOCALF FRM_createchild(HWND hwnd, rCREI ci, WNDPROC prc)
{ // 巕僂傿儞僪僂傪奐偔
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  HWND hchi;

  hchi = CreateWindowEx(
    0,
    ci->cls,
    ci->tit,
    WS_CHILD|WS_VISIBLE|ci->sty,
    0, 0,
    0, 0,
    hwnd,
    (HMENU)ci->id,
    WindowInstance(hwnd),
    NULL
  );
  if (!hchi) return 0;
  if (prc) { SubclassWindow(hchi, prc);}
  SendMessage(hchi, APPM_SETDATA, ci->pa, FALSE);
  fe->flg &=~(FRMS_TIL|FRMS_HRZ|FRMS_RGT);
  FRM_arrange(hwnd, OPR_ACTIVATE, hchi);
  return (iANY)hchi;
}

iANY LOCALF FRM_destroychild(HWND hwnd, HWND hchi)
{ // 巕僂傿儞僪僂偺嶍彍
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B i;

  if ((i = FRM_getindex(hwnd, hchi)) < 0) return 0;
  if (fe->ni <= 2 || i >= fe->ni - 2) { fe->flg &=~(FRMS_TIL|FRMS_HRZ|FRMS_RGT);}
  return FRM_arrange(hwnd, OPR_DESTROY, hchi);
}

iANY LOCALF FRM_getnewid(HWND hwnd, I4B id0)
{ // 枹巊梡偺巕僂傿儞僪僂ID傪媮傔傞
  I4B id;

  for (id = id0; GetDlgItem(hwnd, id); id++) {}
  return id;
}

HWND LOCALF FRM_getchildbyname(HWND hwnd, rSTR nam)
{ // 巕僂傿儞僪僂偺柤慜偐傜僴儞僪儖傪媮傔傞
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B i;

  for (i = 0; i < fe->ni; i++) {
    if (!_stricmp(basnam(WindowText(fe->pi[i])), nam)) { return fe->pi[i];}
  }
  return NULL;
}

iANY LOCALF FRM_size(HWND hwnd, uANY wpa, iANY lpa)
{ // 僒僀僘愝掕
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  if (fe->tbh) { SendDlgItemMessage(hwnd, fe->tid, WM_SIZE, wpa, lpa);}
  if (fe->sbh) { SendDlgItemMessage(hwnd, fe->sid, WM_SIZE, wpa, lpa);}
  if (fe->ni > 0) { FRM_arrange(hwnd, OPR_TILE, NULL);}
  return 0;
}

iANY LOCALF FRM_paint(HWND hwnd)
{ // 昤夋
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  HDC hdc;
  HPEN hpen;
  HBRS hbrs;
  RECT rct, rc1, rc2;
  PAINTSTRUCT ps;

  hdc = BeginPaint(hwnd, &ps);
  GetClientRect(hwnd, &rct);
  if (fe->tbh) { rct.top += fe->tbh;}
  if (fe->sbh) { rct.btm -= fe->sbh;}
  hpen = SelectObject(hdc, CreatePen(PS_INSIDEFRAME, 2, AppColor(CID_3DF)));
  hbrs = SelectObject(hdc, CreateSolidBrush(AppColor(CID_WRK)));
  Rectangle(hdc, rct.lft, rct.top, rct.rgt, rct.btm);
  InflateRect(&rct, -2, -2);
  SplitRect(&rc1, &rc2, &rct, (fe->ni > 1)? fe->flg: 0);
  DeleteObject(SelectObject(hdc, GetStockObject(NULL_BRUSH)));
  if (fe->ni > 0) {
    DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 0, AppColor(CID_ACT))));
    Rectangle(hdc, rc1.lft, rc1.top, rc1.rgt, rc1.btm);
    if (fe->ni > 1 && (fe->flg & FRMS_TIL)) {
      DeleteObject(SelectObject(hdc, CreatePen(PS_SOLID, 0, AppColor(CID_INA))));
      Rectangle(hdc, rc2.lft, rc2.top, rc2.rgt, rc2.btm);
    }
  }
  SelectObject(hdc, hbrs);
  DeleteObject(SelectObject(hdc, hpen));
  EndPaint(hwnd, &ps);
  return 0;
}

iANY LOCALF FRM_setfocus(HWND hwnd, uANY wpa)
{ // 僼僅乕僇僗愝掕
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  if (fe->ni > 0) { SetFocus(fe->pi[fe->ni - 1]);}
  return 0;
}

iANY LOCALF FRM_getplacement(HWND hwnd, pWPOS wp)
{ // 僂僀儞僪僂攝抲忣曬偺曐懚
  WINDOWPLACEMENT wpl;

  wpl.length = sizeof(WINDOWPLACEMENT);
  GetWindowPlacement(hwnd, &wpl);
  wp->wx = wpl.rcNormalPosition.lft;
  wp->wy = wpl.rcNormalPosition.top;
  wp->ww = wpl.rcNormalPosition.rgt - wpl.rcNormalPosition.lft;
  wp->wh = wpl.rcNormalPosition.btm - wpl.rcNormalPosition.top;
  wp->mx = (wpl.showCmd == SW_SHOWMAXIMIZED);
  return 0;
}

iANY LOCALF FRM_statmsg(HWND hwnd, I4B id, rSTR st)
{ // 僗僥乕僞僗儊僢僙乕僕
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  HWND hstb;

  if (fe->sbh && IsWindow(hstb = GetDlgItem(hwnd, fe->sid))) {
    SetDlgItemText(hstb, id, st);
    UpdateWindow(hstb);
  }
  return 0;
}

iANY LOCALF FRM_busymsg(HWND hwnd, I4B id, rSTR st)
{ // 價僕乕儊僢僙乕僕
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  FRM_statmsg(hwnd, id, st);
  fe->hcur = GetCursor();
  SetCursor(LoadCursor(NULL, IDC_WAIT));
  return 0;
}

iANY LOCALF FRM_endbusy(HWND hwnd, I4B id)
{ // 價僕乕儊僢僙乕僕廔椆
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  SetCursor(fe->hcur);
  FRM_statmsg(hwnd, id, "");
  return 0;
}

iANY LOCALF FRM_appstatus(HWND hwnd)
{ // 忬懺偺庢摼
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);
  I4B sta = 0;
  HWND hact;

  if (!!(hact = FRM_getactive(hwnd))) {
    if      (!_stricmp(ClassName(hact), "BOLTXT")) { sta = APPS_TXT;}
    else if (!_stricmp(ClassName(hact), "BOLPRN")) { sta = APPS_PRN;}
    else if (!_stricmp(ClassName(hact), "BOLDIB")) { sta = APPS_DIB;}
    else if (!_stricmp(ClassName(hact), "BOLTBL")) { sta = APPS_TBL;}
    else                                           { sta = APPS_ACT;}
    if (fe->ni > 1) { sta |= APPS_MUL;}
    sta |= (SendMessage(hact, APPM_GETMODE, 0, 0) & APPS_COM);
    if (IsClipboardFormatAvailable(CF_TEXT)) { sta |= APPS_CFT;}
    if (IsClipboardFormatAvailable(CF_BOLRBLK)) { sta |= APPS_CFB;}
  }
  return sta;
}

iANY LOCALF FRM_destroy(HWND hwnd)
{ // 僼儗乕儉僂傿儞僪僂廔椆張棟
  pFRME fe = (pFRME)GetWindowLong(hwnd, 0);

  hfree(fe->pi);
  hfree(fe);
  PostQuitMessage(0);
  return 0;
}

iANY WINAPI DefBOLFRMProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僼儗乕儉僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return FRM_create(hwnd, lpa);
  case FRMM_GETNCHILDREN:
    return ((pFRME)GetWindowLong(hwnd, 0))->ni;
  case FRMM_GETCHILD:
    return (iANY)FRM_getchild(hwnd, wpa);
  case FRMM_GETINDEX:
    return FRM_getindex(hwnd, (HWND)wpa);
  case FRMM_GETACTIVE:
    return (iANY)FRM_getactive(hwnd);
  case FRMM_ARRANGE:
    return FRM_arrange(hwnd, wpa, (HWND)lpa);
  case FRMM_ACTIVATE:
    return FRM_activate(hwnd, (HWND)wpa);
  case FRMM_CREATECHILD:
    return FRM_createchild(hwnd, (rCREI)wpa, (WNDPROC)lpa);
  case FRMM_DESTROYCHILD:
    return FRM_destroychild(hwnd, (HWND)wpa);
  case FRMM_GETNEWID:
    return FRM_getnewid(hwnd, wpa);
  case FRMM_GETCHILDBYNAME:
    return (iANY)FRM_getchildbyname(hwnd, (rSTR)wpa);
  case WM_SIZE:
    return FRM_size(hwnd, wpa, lpa);
  case WM_ERASEBKGND:
    return 1;
  case WM_PAINT:
    return FRM_paint(hwnd);
  case WM_SETFOCUS:
    return FRM_setfocus(hwnd, wpa);
  case FRMM_SETFLAGS:
    ((pFRME)GetWindowLong(hwnd, 0))->flg = wpa; return 0;
  case FRMM_GETFLAGS:
    return ((pFRME)GetWindowLong(hwnd, 0))->flg;
  case FRMM_SETEXTRA:
    ((pFRME)GetWindowLong(hwnd, 0))->ext = wpa; return 0;
  case FRMM_GETEXTRA:
    return ((pFRME)GetWindowLong(hwnd, 0))->ext;
  case FRMM_GETPLACEMENT:
    return FRM_getplacement(hwnd, (pWPOS)wpa);
  case FRMM_STATMSG:
    return FRM_statmsg(hwnd, wpa, (rSTR)lpa);
  case FRMM_BUSYMSG:
    return FRM_busymsg(hwnd, wpa, (rSTR)lpa);
  case FRMM_ENDBUSY:
    return FRM_endbusy(hwnd, wpa);
  case FRMM_INITTOOL:
    return 0;
  case FRMM_APPSTATUS:
    return FRM_appstatus(hwnd);
  case WM_DESTROY:
    set_error_message_box_owner(NULL);
    return FRM_destroy(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLFRMClass(HINSTANCE hinst)
{ // 僼儗乕儉僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = CS_HREDRAW|CS_VREDRAW;
  wcx.lpfnWndProc   = DefBOLFRMProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 2 * sizeof(iANY);
  wcx.hInstance     = hinst;
  wcx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_APPWORKSPACE + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLFRM";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

HWND WINAPI CreateBOLFRMWindow(HINSTANCE hinst, rFRMI fi)
{ // 僼儗乕儉僂傿儞僪僂偺嶌惉
  HWND hwnd;
  static WPOS wpo = { 0, 0, 1200, 730, FALSE }; pWPOS wp;

  wp = fi->wp? fi->wp: &wpo;
  hwnd = CreateWindowEx(
    0,
    "BOLFRM",
    fi->nam,
    WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
    wp->wx, wp->wy,
    wp->ww, wp->wh,
    NULL,
    NULL,
    hinst,
    (pANY)fi
  );
  set_error_message_box_owner(hwnd);
  return hwnd;
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//

U4B WINAPI BOLGUIVer(void)
{ // 僶乕僕儑儞忣曬
  return MODVER;
}

BOOL WINAPI InitBOLGUI(uANY pa)
{ // 奐巒張棟
  RegisterBOLTXTClass(NULL);
  RegisterBOLPRNClass(NULL);
  RegisterBOLDIBClass(NULL);
  RegisterBOLTBLClass(NULL);
  RegisterBOLFRMClass(NULL);
  CF_BOLRBLK = RegisterClipboardFormat("BOLRBLK");
  return TRUE;
}

void WINAPI TermBOLGUI(void)
{ // 廔椆張棟
}

//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//
