/*乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗//
    bolfro.c
//乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗乗*/

#include <windows.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 "bolfro.h"

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

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

#define  DIB_72DPI    2835
#define  DIB_96DPI    3780
#define  DIB_300DPI  11811

#define  DIB_72D  DIB_72DPI
#define  DIB_96D  DIB_96DPI
#define  DIB_300  DIB_300DPI

#define  BMIHSZ  sizeof(BITMAPINFOHEADER)
#define  BMFHSZ  sizeof(BITMAPFILEHEADER)

HDIB WINAPI CreateDIB(I4B w, I4B h, I4B flg)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偺嶌惉
  I4B bc, sz;
  HDIB bm;
  BITMAPINFOHEADER *bi;

  if (w <= 0 || h <= 0) { return ierr(E_PAR);}
  bc = ((flg & 0x3f) == DIB_32B)? 32: 24;
  sz = ((w * bc + 31) / 32) * 4 * h;
  bm = halloc(sizeof(P4B), FALSE); if (!bm) { return ierr(E_MEM);}
  bi = halloc(BMIHSZ + sz, TRUE); if (!bi) { return ierr(E_MEM);}
  bi->biSize = BMIHSZ;
  bi->biWidth = w;
  bi->biHeight = (flg & DIB_TDN)? -h: h;
  bi->biPlanes = 1;
  bi->biBitCount = bc;
  bi->biSizeImage = sz;
  bi->biXPelsPerMeter = bi->biYPelsPerMeter = DIB_96D;
  bm->bi = bi;
  return bm;
}

I4B  WINAPI DIB_WID(HDIB bm)
{ // 墶僺僋僙儖悢
  return ((BITMAPINFOHEADER *)bm->bi)->biWidth;
}

I4B  WINAPI DIB_HEI(HDIB bm)
{ // 廲僺僋僙儖悢(忋偐傜壓偺偲偒偼晧悢)
  return ((BITMAPINFOHEADER *)bm->bi)->biHeight;
}

I4B  WINAPI DIB_BTS(HDIB bm)
{ // 僺僋僙儖摉偨傝偺價僢僩悢
  return ((BITMAPINFOHEADER *)bm->bi)->biBitCount;
}

I4B  WINAPI DIB_ISZ(HDIB bm)
{ // 僺僋僙儖僨乕僞偺僒僀僘
  return ((BITMAPINFOHEADER *)bm->bi)->biSizeImage;
}

I4B  WINAPI DIB_LSZ(HDIB bm)
{ // 峴偺僒僀僘
  return ((DIB_WID(bm) * DIB_BTS(bm) + 31) / 32) * 4;
}

pBIN WINAPI DIB_IMG(HDIB bm)
{ // 僺僋僙儖僨乕僞偺傾僪儗僗
  return (pBIN)bm->bi + BMIHSZ;
}

HDIB WINAPI CreateCompatibleDIB(HDIB bm)
{ // 屳姺惈偺偁傞僨僶僀僗撈棫價僢僩儅僢僾偺嶌惉
  I4B w, h, flg;

  w = DIB_WID(bm);
  h = abs(DIB_HEI(bm));
  flg = ((DIB_HEI(bm) < 0)? DIB_TDN: 0) | ((DIB_BTS(bm) == 32)? DIB_32B: 0);
  return CreateDIB(w, h, flg);
}

HDIB WINAPI DuplicateDIB(HDIB bm)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偺暋惢
  HDIB bx;

  bx = CreateCompatibleDIB(bm); if (!bx) return NULL;
  memcpy(bx->bi, bm->bi, BMIHSZ + DIB_ISZ(bm));
  return bx;
}

void WINAPI DeleteDIB(HDIB bm)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偺嶍彍
  if (!bm) return;
  hfree(bm->bi);
  hfree(bm);
}

HDIB WINAPI MoveDIB(HDIB bm, HDIB bx)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偺堏摦
  hfree(bm->bi);
  bm->bi = bx->bi;
  hfree(bx);
  return bm;
}

pSIZE WINAPI GetDIBSize(pSIZE sz, HDIB bm)
{ // 夋憸僒僀僘偺庢摼
  sz->cx = DIB_WID(bm);
  sz->cy = abs(DIB_HEI(bm));
  return sz;
}

HDIB WINAPI LoadDIB(HDIB bm, rSTR nam)
{ // BMP僼傽僀儖撉崬
  I4B sz, re = FALSE;
  HDIB bx;
  HFIL hf;
  BITMAPFILEHEADER *bf;

  bx = halloc(sizeof(P4B), FALSE); if (!bx) { return ierr(E_MEM);}
  hf = open_file(nam, OP_RDO); if (!hf) { ferr(E_FIR, nam); goto _30;}
  sz = get_file_size(hf); if (sz < BMFHSZ + BMIHSZ) { ferr(E_FIR, nam); goto _30;}
  bf = halloc(sz, TRUE); if (!bf) { ierr(E_MEM); goto _20;}
  if (!read_file(hf, bf, sz)) { ferr(E_FIR, nam); goto _10;}
  if (bf->bfType != 0x4d42) { ferr(E_DAT, nam); goto _10;}
  bx->bi = (pANY)((pBIN)bf + BMFHSZ);
  if (BMIHSZ + DIB_ISZ(bx) > sz - BMFHSZ) { bx->bi = NULL; ferr(E_DAT, nam); goto _10;}
  bx->bi = halloc(sz - BMFHSZ, FALSE); if (!bx->bi) { ierr(E_MEM); goto _10;}
  memcpy(bx->bi, (rBIN)bf + BMFHSZ, sz - BMFHSZ);
  re = TRUE; _10:
  hfree(bf); _20:
  close_file(hf); _30:
  if (!re) { hfree(bx->bi); hfree(bx); bx = NULL;}
  return bm? MoveDIB(bm, bx): bx;
}

BOOL WINAPI SaveDIB(HDIB bm, rSTR nam)
{ // BMP僼傽僀儖彂弌
  I4B sz, re = FALSE;
  HFIL hf;
  BITMAPFILEHEADER *bf;

  sz = BMIHSZ + DIB_ISZ(bm);
  bf = halloc(BMFHSZ + sz, TRUE); if (!bf) { return (BOOL)ierr(E_MEM);}
  bf->bfType = 0x4d42;
  bf->bfSize = BMFHSZ + sz;
  bf->bfOffBits = BMFHSZ + BMIHSZ;
  memcpy((pBIN)bf + BMFHSZ, bm->bi, sz);
  hf = open_file(nam, OP_WRI); if (!hf) { ferr(E_FIW, nam); goto _10;}
  re = write_file(hf, bf, bf->bfSize);
  close_file(hf); _10:
  hfree(bf);
  return re;
}

BOOL WINAPI ConvertDIB(HDIB bm, I4B flg)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偺僼僅乕儅僢僩曄姺
  I4B i, j, k, w, h, n, sw, bc1, bc2;
  pBIN p1, p2;
  pRGBC q1, q2;
  HDIB bx;

  bc1 = DIB_BTS(bm); if (bc1 != 24 && bc1 != 32) { return (BOOL)ierr(E_DAT);}
  bc2 = ((flg & 0x3f) == DIB_32B)? 32: 24;
  w = DIB_WID(bm);
  h = abs(DIB_HEI(bm));
  bx = CreateDIB(w, h, flg); if (!bx) return FALSE;
  sw = (DIB_HEI(bm) < 0) != ((flg & DIB_TDN) != 0);
  switch (MKU4B(bc1, bc2)) {
  case MKU4B(32, 32):
    q1 = (pANY)DIB_IMG(bm);
    q2 = (pANY)DIB_IMG(bx); n = DIB_LSZ(bx);
    for (i = 0; i < h; i++) {
      k = sw? h - 1 - i: i;
      memcpy(&q2[k * w], &q1[i * w], n);
    }
    break;
  case MKU4B(32, 24):
    q1 = (pANY)DIB_IMG(bm);
    p2 = (pANY)DIB_IMG(bx); n = DIB_LSZ(bx);
    for (i = 0; i < h; i++) {
      k = sw? h - 1 - i: i;
      for (j = 0; j < w; j++) {
        memcpy(&p2[k * n + j * 3], &q1[i * w + j], 3);
      }
    }
    break;
  case MKU4B(24, 32):
    p1 = (pANY)DIB_IMG(bm); n = DIB_LSZ(bm);
    q2 = (pANY)DIB_IMG(bx);
    for (i = 0; i < h; i++) {
      k = sw? h - 1 - i: i;
      for (j = 0; j < w; j++) {
        memcpy(&q2[k * w + j], &p1[i * n + j * 3], 3);
      }
    }
    break;
  case MKU4B(24, 24):
    p1 = (pANY)DIB_IMG(bm); n = DIB_LSZ(bm);
    p2 = (pANY)DIB_IMG(bx);
    for (i = 0; i < h; i++) {
      k = sw? h - 1 - i: i;
      memcpy(&p2[k * n], &p1[i * n], n);
    }
    break;
  }
  MoveDIB(bm, bx);
  return TRUE;
}

HDIB WINAPI LoadBMP(HDIB bm, rSTR nam)
{ // BMP僼傽僀儖撉崬
  bm = LoadDIB(bm, nam); if (!bm) return NULL;
  if (!ConvertDIB(bm, DIB_32B|DIB_TDN)) { DeleteDIB(bm); bm = NULL;}
  return bm;
}

BOOL WINAPI SaveBMP(HDIB bm, rSTR nam)
{ // BMP僼傽僀儖彂弌
  I4B re = FALSE;
  HDIB bx;

  bx = DuplicateDIB(bm); if (!bx) return FALSE;
  if (ConvertDIB(bx, DIB_24B)) { re = SaveDIB(bx, nam);}
  DeleteDIB(bx);
  return re;
}

HDIB WINAPI CreateDIBFromIMG(HIMG im)
{ // 價僢僩儅僢僾夋憸偐傜僨僶僀僗撈棫價僢僩儅僢僾傪嶌惉
  HDIB bm;

  bm = CreateDIB(im->w, im->h, DIB_32B|DIB_TDN); if (!bm) return NULL;
  memcpy(DIB_IMG(bm), im->bi, im->w * im->h * sizeof(RGBC));
  return bm;
}

HIMG WINAPI CreateIMGFromDIB(HDIB bm)
{ // 價僢僩儅僢僾夋憸偐傜僨僶僀僗撈棫價僢僩儅僢僾傪嶌惉
  HIMG im;

  if (DIB_BTS(bm) != 32 || DIB_HEI(bm) > 0) { return ierr(E_DAT);}
  im = CreateIMG(DIB_WID(bm), abs(DIB_HEI(bm)), 0); if (!im) return NULL;
  memcpy(im->bi, DIB_IMG(bm), im->w * im->h * sizeof(RGBC));
  return im;
}

BOOL WINAPI ChangeDIBColor(HDIB bm, FCVT fcvt, uANY pa)
{ // 怓曄姺
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  ChangeIMGColor(im, fcvt, pa);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI SuperposeDIB(HDIB bm, HDIB bx, I4B x, I4B y, FOPR fopr, uANY pa)
{ // 廳偹崌傢偣
  HIMG im, ix;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  ix = CreateIMGFromDIB(bx); if (!ix) { DeleteIMG(im); return FALSE;}
  SuperposeIMG(im, ix, x, y, fopr, pa); DeleteIMG(ix);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI PasteDIB(HDIB bm, HDIB bx, I4B x, I4B y)
{ // 揬傝晅偗
  return SuperposeDIB(bm, bx, x, y, foprMIX, 0);
}

BOOL WINAPI TrimDIB(HDIB bm, I4B x, I4B y, I4B w, I4B h, RGBC cb)
{ // 僩儕儈儞僌
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  TrimIMG(im, x, y, w, h, cb);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI TransformDIBX(HDIB bm, I4B w, I4B h, FXFM fxfm, uANY pa, RGBC cb)
{ // 帺桼曄宍
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  TransformIMGX(im, w, h, fxfm, pa, cb);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI TransformDIB(HDIB bm, rXFMQ q, RGBC cb)
{ // 帺桼曄宍(巐嬿揰(0,0),(w-1,0),(0,h-1),(w-1,h-1)偺堏摦愭巜掕)
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  TransformIMG(im, q, cb);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI InvertDIB(HDIB bm, I4B sw)
{ // 嬀塮斀揮
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  InvertIMG(im, sw);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI RotateDIB(HDIB bm, F8B dg, RGBC cb)
{ // 擟堄妏搙夞揮(dg:搙丄斀帪寁夞傝惓)
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  RotateIMG(im, dg, cb);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

BOOL WINAPI ResizeDIBX(HDIB bm, I4B w, I4B h, I4B sw)
{ // 奼戝弅彫
  HIMG im;
  HDIB bx;

  im = CreateIMGFromDIB(bm); if (!im) return FALSE;
  ResizeIMGX(im, w, h, sw);
  bx = CreateDIBFromIMG(im); DeleteIMG(im); if (!bx) return FALSE;
  MoveDIB(bm, bx);
  return TRUE;
}

HDIB WINAPI CaptureDIB(HDIB bm, HDC hdc, rRECT pr)
{ // 價僢僩儅僢僾偺庢摼
  I4B x, y, w, h;
  HDIB bx;
  HDC hmem;
  HBMP hbmp, horg;
  BITMAP bmp;

  if (!pr) {
    hbmp = GetCurrentObject(hdc, OBJ_BITMAP);
    GetObject(hbmp, sizeof(BITMAP), &bmp);
    x = y = 0;
    w = bmp.bmWidth;
    h = bmp.bmHeight;
  } else {
    if (IsRectEmpty(pr)) { return ierr(E_DAT);}
    x = pr->lft; y = pr->top;
    w = pr->rgt - pr->lft;
    h = pr->btm - pr->top;
  }
  bx = CreateDIB(w, h, DIB_32B|DIB_TDN); if (!bx) return NULL;
  hmem = CreateCompatibleDC(hdc);
  horg = SelectObject(hmem, hbmp = CreateCompatibleBitmap(hdc, w, h));
  BitBlt(hmem, 0, 0, w, h, hdc, x, y, SRCCOPY);
  SelectObject(hmem, horg);
  GetDIBits(hmem, hbmp, 0, h, DIB_IMG(bx), bx->bi, DIB_RGB_COLORS);
  DeleteObject(hbmp);
  DeleteDC(hmem);
  return bm? MoveDIB(bm, bx): bx;
}

HDIB WINAPI CreateDIBFromDDB(HBMP hbmp)
{ // 夋柺昞帵梡價僢僩儅僢僾偐傜僨僶僀僗撈棫價僢僩儅僢僾傪嶌惉
  HDIB bm;
  HDC hdc;
  BITMAP bmp;

  GetObject(hbmp, sizeof(BITMAP), &bmp);
  bm = CreateDIB(bmp.bmWidth, bmp.bmHeight, DIB_32B|DIB_TDN); if (!bm) return NULL;
  hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  GetDIBits(hdc, hbmp, 0, bmp.bmHeight, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS);
  DeleteDC(hdc);
  return bm;
}

HBMP WINAPI CreateDDBFromDIB(HDIB bm)
{ // 僨僶僀僗撈棫價僢僩儅僢僾偐傜夋柺昞帵梡價僢僩儅僢僾傪嶌惉
  HDC hdc;
  HBMP hbmp;

  hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  hbmp = CreateDIBitmap(hdc, bm->bi, CBM_INIT, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS);
  DeleteDC(hdc);
  return hbmp;
}

BOOL WINAPI DrawDIB(HDC hdc, pRECT pr, HDIB bm, I4B fmt)
{ // 價僢僩儅僢僾偺昤夋
  I4B xd, yd, wd, hd, ws, hs, wt, ht, re;
  HDIB bx;
  HRGN hrgn;
  RECT rct;

  if (fmt & DT_GRY) {
    bx = DuplicateDIB(bm); if (!bx) return FALSE;
    ChangeDIBColor(bx, fcvtGRY, BGR2RGB(AppColor(CID_3DF)));
    re = DrawDIB(hdc, pr, bx, fmt &~DT_GRY);
    DeleteDIB(bx);
    return re;
  }
  ws = DIB_WID(bm);
  hs = abs(DIB_HEI(bm));
  xd = pr->lft;
  yd = pr->top;
  wd = pr->rgt - pr->lft; if (wd <= 0) return FALSE;
  hd = pr->btm - pr->top; if (hd <= 0) return FALSE;
  switch (fmt & (DT_AJW|DT_AJH)) {
  case 0:
    if (fmt & DT_RGT) { xd += (wd - ws);} else if (fmt & DT_CEN) { xd += (wd - ws) / 2;}
    if (fmt & DT_BTM) { yd += (hd - hs);} else if (DTisMID(fmt)) { yd += (hd - hs) / 2;}
    wd = ws;
    hd = hs;
    break;
  case DT_AJH:
    wt = hd * ws / hs;
    if (fmt & DT_RGT) { xd += (wd - wt);} else if (fmt & DT_CEN) { xd += (wd - wt) / 2;}
    wd = wt;
    break;
  case DT_AJW:
    ht = wd * hs / ws;
    if (fmt & DT_BTM) { yd += (hd - ht);} else if (DTisMID(fmt)) { yd += (hd - ht) / 2;}
    hd = ht;
    break;
  }
  if (fmt & DT_CAL) {
    SetRect(&rct, xd, yd, xd + wd, yd + hd);
    if (fmt & DT_CLP) { IntersectRect(&rct, pr, &rct);}
    CopyRect(pr, &rct);
    return TRUE;
  }
  if (fmt & DT_CLP) {
    SelectClipRgn(hdc, hrgn = CreateRectRgnIndirect(pr));
  }
  re = StretchDIBits(hdc, xd, yd, wd, hd, 0, 0, ws, hs, DIB_IMG(bm), bm->bi, DIB_RGB_COLORS, SRCCOPY) > 0;
  if (fmt & DT_CLP) {
    SelectClipRgn(hdc, NULL); DeleteObject(hrgn);
  }
  return re;
}

BOOL WINAPI DrawDDB(HDC hdc, pRECT pr, HBMP hbmp, I4B fmt)
{ // 價僢僩儅僢僾偺昤夋
  I4B re;
  HDIB bm;

  bm = CreateDIBFromDDB(hbmp); if (!bm) return FALSE;
  re = DrawDIB(hdc, pr, bm, fmt);
  DeleteDIB(bm);
  return re;
}

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

RGBC WINAPI BGR2RGB(BGRC cr)
{ // COLORREF佁RGBQUAD曄姺
  return fcvtRBX(cr, 0);
}

BGRC WINAPI BKG2TXT(BGRC cr)
{ // 攚宨怓偵崌偆暥帤怓
  return fcvtTXT(cr, 0);
}

BGRC WINAPI lighten(BGRC cr, uANY pa)
{ // 柧埫挷惍(pa:0乣255偱崟仺敀)
  return fcvtLGT(cr, pa);
}

typedef struct {
  U1B   R;
  U1B   G;
  U1B   B;
  U1B   A;
} PALI;
  // 婛掕偺僷儗僢僩
static PALI PAL[] = {
  { 0x00, 0x00, 0x00, 'K' }, { 0x00, 0x00, 0xff, 'B' }, { 0xff, 0x00, 0x00, 'R' }, { 0xff, 0x00, 0xff, 'F' },
  { 0x00, 0xff, 0x00, 'L' }, { 0x00, 0xff, 0xff, 'A' }, { 0xff, 0xff, 0x00, 'Y' }, { 0xff, 0xff, 0xff, 'W' },
  { 0xa0, 0xa0, 0xa0, 's' }, { 0x00, 0x00, 0xc0, 'b' }, { 0xc0, 0x00, 0x00, 'r' }, { 0xc0, 0x00, 0xc0, 'f' },
  { 0x00, 0xc0, 0x00, 'l' }, { 0x00, 0xc0, 0xc0, 'a' }, { 0xc0, 0xc0, 0x00, 'y' }, { 0xf0, 0xf0, 0xf0, ' ' },
  { 0x69, 0x69, 0x69, 'D' }, { 0x00, 0x00, 0x80, 'N' }, { 0x80, 0x00, 0x00, 'M' }, { 0x80, 0x00, 0x80, 'P' },
  { 0x00, 0x80, 0x00, 'G' }, { 0x00, 0x80, 0x80, 'T' }, { 0x80, 0x80, 0x00, 'O' }, { 0xff, 0xff, 0xff, 'H' },
  { 0xd0, 0xff, 0xe0, 'd' }, { 0x00, 0x00, 0x40, 'n' }, { 0x40, 0x00, 0x00, 'm' }, { 0x40, 0x00, 0x40, 'p' },
  { 0x00, 0x40, 0x00, 'g' }, { 0x00, 0x40, 0x40, 't' }, { 0x40, 0x40, 0x00, 'o' }, { 0xd0, 0xd0, 0xd0, 'h' },
  { 0x00, 0x78, 0xd7, 'E' }, { 0xc0, 0xd0, 0xff, 'U' }, { 0xff, 0xc0, 0xd0, 'I' }, { 0xff, 0xd0, 0xff, 'V' },
  { 0xd0, 0xff, 0xd0, 'J' }, { 0xd0, 0xff, 0xff, 'C' }, { 0xff, 0xff, 0xd0, 'Z' }, { 0xff, 0xe0, 0xc0, 'Q' },
  { 0xff, 0xff, 0xff, 'e' }, { 0x90, 0xa0, 0xff, 'u' }, { 0xff, 0x90, 0xa0, 'i' }, { 0xff, 0xa0, 0xff, 'v' },
  { 0xa0, 0xff, 0xa0, 'j' }, { 0xa0, 0xff, 0xff, 'c' }, { 0xff, 0xff, 0xa0, 'z' }, { 0xff, 0xb0, 0x90, 'q' },
  { 0xe3, 0xe3, 0xe3, 'S' }, { 0x00, 0x00, 0x00, '0' }, { 0x20, 0x20, 0x20, '1' }, { 0x40, 0x40, 0x40, '!' },
  { 0x50, 0x50, 0x50, '2' }, { 0x60, 0x60, 0x60, '#' }, { 0x70, 0x70, 0x70, '3' }, { 0x80, 0x80, 0x80, '$' },
  { 0x90, 0x90, 0x90, '4' }, { 0xa0, 0xa0, 0xa0, '%' }, { 0xb0, 0xb0, 0xb0, '5' }, { 0xc0, 0xc0, 0xc0, '6' },
  { 0xd0, 0xd0, 0xd0, '7' }, { 0xe0, 0xe0, 0xe0, '8' }, { 0xf0, 0xf0, 0xf0, '9' }, { 0xff, 0xff, 0xff, 'w' },
};

  // 儁儞僴儞僪儖
static HPEN PEN[_countof(PAL)];
  // 僽儔僔僴儞僪儖
static HBRS BRS[_countof(PAL)];

I4B  WINAPI NAppColors(void)
{ // 婛掕偺僷儗僢僩偺怓悢
  return _countof(PAL);
}

void WINAPI SetAppColor(I4B cid, BGRC col)
{ // 僷儗僢僩怓愝掕
  I4B bk;

  if ((U4B)cid >= _countof(PAL)) { ierr(E_CAP); return;}
  bk = *(BGRC *)&PAL[cid];
  *(BGRC *)&PAL[cid] = (bk & 0xff000000) | (col & 0xffffff);
  if (PEN[cid]) { DeleteObject(PEN[cid]); PEN[cid] = NULL;}
  if (BRS[cid]) { DeleteObject(BRS[cid]); BRS[cid] = NULL;}
}

BGRC WINAPI AppColor(I4B cid)
{ // 怓(COLORREF)
  if ((U4B)cid >= _countof(PAL)) return 0;
  return *(BGRC *)&PAL[cid] & 0xffffff;
}

I1B  WINAPI AppColorChar(I4B cid)
{ // 怓傪昞偡暥帤
  if ((U4B)cid >= _countof(PAL)) { return '*';}
  return PAL[cid].A;
}

I4B  WINAPI AppColorIndex(I1B ch)
{ // 暥帤偑昞偡怓偺僀儞僨僢僋僗
  I4B i;

  for (i = 0; i < _countof(PAL); i++) {
    if (PAL[i].A == ch) { return i;}
  }
  return 0;
}

U1B  LOCALF fdstEUC(BGRC c1, BGRC c2)
{ // 儐乕僋儕僢僪嫍棧
  I4B r, g, b;

  r = ((PALI *)&c2)->R - ((PALI *)&c1)->R;
  g = ((PALI *)&c2)->G - ((PALI *)&c1)->G;
  b = ((PALI *)&c2)->B - ((PALI *)&c1)->B;
  return (I4B)(sqrt((r * r + g * g + b * b) / 3.0) + 0.5);
}

I4B  WINAPI NearestAppColorIndex(BGRC col)
{ // 嵟傕嬤偄怓偺僀儞僨僢僋僗
  I4B i, k, d, f;

  k = 0; f = 255;
  for (i = 0; i < _countof(PAL); i++) {
    d = fdstEUC(col, AppColor(i));
    if (d < f) { k = i; f = d;}
  }
  return k;
}

HIMG WINAPI CreateIMGFromSTR(I4B w, I4B h, rSTR bi)
{ // 暥帤攝楍偵傛傞價僢僩儅僢僾夋憸偺嶌惉
  I4B i;
  HIMG im;

  im = CreateIMG(w, h, 0); if (!im) return NULL;
  if (bi) {
    for (i = 0; i < w * h; i++) {
      im->bi[i] = BGR2RGB(AppColor(AppColorIndex(bi[i])));
    }
  }
  return im;
}

HDIB WINAPI CreateDIBFromSTR(I4B w, I4B h, rSTR bi)
{ // 暥帤攝楍偵傛傞僨僶僀僗撈棫價僢僩儅僢僾偺嶌惉
  HIMG im;
  HDIB bm;

  im = CreateIMGFromSTR(w, h, bi); if (!im) return NULL;
  bm = CreateDIBFromIMG(im); DeleteIMG(im);
  return bm;
}

HBMP WINAPI CreateDDBFromSTR(I4B w, I4B h, rSTR bi)
{ // 暥帤攝楍偵傛傞夋柺昞帵梡價僢僩儅僢僾偺嶌惉
  HDIB bm;
  HBMP hbmp;

  bm = CreateDIBFromSTR(w, h, bi); if (!bm) return NULL;
  hbmp = CreateDDBFromDIB(bm); DeleteDIB(bm);
  return hbmp;
}

HPEN WINAPI AppPen(I4B cid)
{ // 儁儞
  if ((U4B)cid >= _countof(PEN)) { return PEN[0];}
  if (!PEN[cid]) { PEN[cid] = CreatePen(PS_SOLID, 0, AppColor(cid));}
  return PEN[cid];
}

HBRS WINAPI AppBrush(I4B cid)
{ // 僽儔僔
  if ((U4B)cid >= _countof(BRS)) { return BRS[0];}
  if (!BRS[cid]) { BRS[cid] = CreateSolidBrush(AppColor(cid));}
  return BRS[cid];
}

pLOGFONT WINAPI SetLOGFONT(pLOGFONT lf, rSTR face, I4B ch, I4B flg)
{ // 榑棟僼僅儞僩偺愝掕
  lf->lfHeight = -ch;
  lf->lfWidth = 0;
  lf->lfEscapement = ((flg & TFF_VRT) != 0) * -900;
  lf->lfOrientation = lf->lfEscapement;
  lf->lfWeight = ((flg & 0x00f0) >> 4) * 100;
  lf->lfItalic = ((flg & TFF_ITA) != 0);
  lf->lfUnderline = ((flg & TFF_UND) != 0);
  lf->lfStrikeOut = ((flg & TFF_STO) != 0);
  lf->lfCharSet = DEFAULT_CHARSET;
  lf->lfOutPrecision = 0;
  lf->lfClipPrecision = 0;
  lf->lfQuality = 0;
  lf->lfPitchAndFamily = 0;
  strcpyx(lf->lfFaceName, face? face: "", sizeof(lf->lfFaceName) - 1);
  return lf;
}

void WINAPI GetTextSize(pSIZE sz, HDC hdc, rLOGFONT lf, rSTR st, I4B cb)
{ // 暥帤楍偺僒僀僘庢摼
  I4B sw = FALSE;
  HFNT hfnt;

  if (!hdc) {
    hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
    sw = TRUE;
  }
  if (lf) { hfnt = SelectObject(hdc, CreateFontIndirect(lf));}
  GetTextExtentPoint32(hdc, st, (cb > 0)? cb: strlen(st), sz);
  if (lf) { DeleteObject(SelectObject(hdc, hfnt));}
  if (sw) { DeleteDC(hdc);}
}

#define  AVESTR  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

#define  AVEWID(cx)  (((cx) / 26 + 1) / 2)

void WINAPI GetAveCharSize(pSIZE sz, HDC hdc, rLOGFONT lf)
{ // 暯嬒暥帤僒僀僘庢摼
  SIZE siz;

  GetTextSize(&siz, hdc, lf, AVESTR, -1);
  sz->cx = AVEWID(siz.cx);
  sz->cy = siz.cy;
}

void WINAPI GetZenCharSize(pSIZE sz, HDC hdc, rLOGFONT lf)
{ // 慡妏暥帤僒僀僘庢摼
  SIZE siz;

  GetTextSize(&siz, hdc, lf, "娍帤", -1);
  sz->cx = siz.cx / 2;
  sz->cy = siz.cy;
}

  // 僼僅儞僩僴儞僪儖
static HFNT FNT[64];

I4B  WINAPI NAppFonts(void)
{ // 婛掕偺僼僅儞僩偺悢
  return _countof(FNT);
}

void WINAPI SetAppFont(I4B fid, HFNT hfnt)
{ // 僼僅儞僩偺搊榐
  if ((U4B)fid >= _countof(FNT)) { ierr(E_CAP); return;}
  if (FNT[fid]) { DeleteObject(FNT[fid]);}
  FNT[fid] = hfnt;
}

HFNT WINAPI AppFont(I4B fid)
{ // 僼僅儞僩
  if ((U4B)fid >= _countof(FNT) || !FNT[fid]) { return FNT[0];}
  return FNT[fid];
}

  // 夋柺昞帵梡價僢僩儅僢僾僴儞僪儖
static HBMP BMP[64];

I4B  WINAPI NAppDDBs(void)
{ // 婛掕偺夋柺昞帵梡價僢僩儅僢僾偺悢
  return _countof(BMP);
}

void WINAPI SetAppDDB(I4B bid, HBMP hbmp)
{ // 夋柺昞帵梡價僢僩儅僢僾偺搊榐
  if ((U4B)bid >= _countof(BMP)) { ierr(E_CAP); return;}
  if (BMP[bid]) { DeleteObject(BMP[bid]);}
  BMP[bid] = hbmp;
}

HBMP WINAPI AppDDB(I4B bid)
{ // 夋柺昞帵梡價僢僩儅僢僾
  if ((U4B)bid >= _countof(BMP) || !BMP[bid]) { return BMP[0];}
  return BMP[bid];
}

typedef struct {
  I4B   idm;
  HBMP  hbmp;
} CBMI;
  // 儊僯儏乕梡價僢僩儅僢僾
static CBMI CBI[64];

void WINAPI SetMenuItemDDB(I4B idm, HBMP hbmp)
{ // 儊僯儏乕梡價僢僩儅僢僾偺愝掕
  I4B i;

  for (i = 0; i < _countof(CBI); i++) {
    if (CBI[i].idm == idm) { CBI[i].hbmp = hbmp; return;}
  }
  for (i = 0; i < _countof(CBI); i++) {
    if (CBI[i].idm == 0) { CBI[i].idm = idm; CBI[i].hbmp = hbmp; return;}
  }
  ierr(E_CAP);
}

HBMP WINAPI MenuItemDDB(I4B idm)
{ // 儊僯儏乕梡價僢僩儅僢僾
  I4B i;

  for (i = 0; i < _countof(CBI); i++) {
    if (CBI[i].idm == idm) { return CBI[i].hbmp;}
  }
  return NULL;
}

  // 16x16價僢僩儅僢僾僀儊乕僕
static I1B MBI[][MNUBMPW * MNUBMPH] = {
  //  0 BLANK
    "                " "                " "                " "                "
    "                " "                " "                " "                "
    "                " "                " "                " "                "
    "                " "                " "                " "                "
  ,
  //  1 NEW
    "                " "  $$$$$$$$$5    " "  $wwwwwww$!5   " "  $wwwwwww$9!5  "
    "  $wwwwwww$!!!  " "  $wwwwwww888!  " "  $wwwwwwwww8!  " "  $wwwwwwmmm8!  "
    "  $wwwwwwmQm8!  " "  $wwwwwwmQm8!  " "  $wwwwwwmQmmm  " "  $wwwwwmqQqqqm "
    "  $wwwwwmQQQQQQm" "  $wwwwwmQQQQQQm" "  $98888mQQQQQQm" "  $!!!!!!mQQQQm "
  ,
  //  2 OPEN
    "                " "                " "                " "OOOOOO5         "
    "OYYYYyO5        " "OYYYYYyOOOOOO   " "OYYYYYYYYYYY!   " "OYYYOOOOOOOOOOOO"
    "OYYyOYYYYYYYYYy!" "OYYOYYYYYYYYYY!5" "OYyOYYYYYYYYYy! " "OYOYYYYYYYYYY!5 "
    "OyOYYYYYYYYYy!  " "OOYYYYYYYYYY!5  " "O!!!!!!!!!!!!   " "                "
  ,
  //  3 CLOSE
    "                " "                " "                " "   15      51   "
    "   505    505   " "    505  505    " "     505505     " "      5005      "
    "      5005      " "     505505     " "    505  505    " "   505    505   "
    "   15      51   " "                " "                " "                "
  ,
  //  4 SAVE
    "                " " ####333333###u " " #uuu666666uuu# " " #uuu6666!6uuu! "
    " #uuu6666!6uuu! " " #uuu666666uuu! " " #uuuuuuuuuuuu! " " #uu########uu! "
    " #u#wwwwwwww#u! " " #u#wwwwwwww#u! " " #u#wwwwwwww#u! " " #u#wwwwwwww#u! "
    " #!#wwwwwwww#u! " " #u#wwwwwwww#u! " " #!!########!!! " "                "
  ,
  //  5 SAVEAS
    "                " " ####333333###u " " #uuu666666uuu# " " #uuu6666!6uuu! "
    " #uuu6666!6uuu! " " #uuu666666uuu! " " #uuuuuuuuuuuu! " " #uu#####mmmuu! "
    " #u#wwwwwmQm#u! " " #u#wwwwwmQm#u! " " #u#wwwwwmQmmm! " " #u#wwwwmqQqqqm "
    " #!#wwwwmQQQQQQm" " #u#wwwwmQQQQQQm" " #!!####mQQQQQQm" "         mQQQQm "
  ,
  //  6 PRINT
    "    %%%%%%%%    " "    %9999994    " "    %9999994    " "    %wwwwww4    "
    "    %wwwwww4    " " 53$$$$$$$$$$34 " "%37$$$$$$$$$$73$" "377##########77!"
    "366222222222266!" "35522222222225j!" "344888888888844!" "39914%#$22%$199!"
    "4!!0%wB83Tw40!!#" "    %wB5!Nw4    " "    %wwwwww4    " "    %4444444    "
  ,
  //  7 SETUP
    "                " "0  00000000000  " "                " "                "
    "0  00000000000  " "                " "                " "0  000000mmm00  "
    "         mQm    " "         mQm    " "0  000000mQm00  " "        mqQqqqm "
    "        mQQQQQQm" "        mQQQQQQm" "        mQQQQQQm" "         mQQQQm "
  ,
  //  8 CUT
    "   746    647   " "   6$4    4$6   " "   6$$6  6$$6   " "    5$$  $$5    "
    "     4$66$4     " "     5$$$$5     " "      4$$4      " "      5$#5      "
    "      63#6      " "     BB##BB     " "   ubBBBBBBbu   " "  BBBBBuuBBBBB  "
    " uB  Bb  bB  Bu " " uB uBu  uB uBu " "  BBBB    BBBB  " "                "
  ,
  //  9 COPY
    "                " " $$$$$$5        " " $wwww$!5       " " $wwww$9!5      "
    " $w%%7$NNNNNN5  " " $wwwwwNwwwwNn5 " " $w%%%%NwwwwN9n5" " $wwwwwNwuuUNnnn"
    " $w%%%%Nwwwwwwwn" " $wwwwwNwuuuuuwn" " $!!!!!Nwwwwwwwn" "       Nwuuuuuwn"
    "       Nwwwwwwwn" "       Nnnnnnnnn" "                " "                "
  ,
  // 10 PASTE
    "                " "     !11!       " " OOOO1OO1OOOO   " "Oyyy17!!71yyy!  "
    "Oyy17777771yy!  " "Oyy!111111!yy!  " "Oyyyyyyyyyyyy!  " "OyyyyyNNNNNNN!  "
    "OyyyyyNwwwwwNn5 " "OyyyyyNwwwwwN9n5" "OyyyyyNwuuuUNnnn" "OyyyyyNwwwwwwwwn"
    "OyyyyyNwuuuuuuwn" " !!!!!Nwwwwwwwwn" "      Nnnnnnnnnn" "                "
  ,
  // 11 SEARCH
    "                " "   !!!   !!!    " "   !$0   !$0    " "  !!!!! !!!!!   "
    "  !w430 !w430   " " !!!!!01!!!!!!  " " !%w4301!%w430  " " !%w430 !%w430  "
    "!!!!!0111!!!!!! " "!%w430   !%w430 " "!%w430   !%w430 " "!%w430   !%w430 "
    "!%w430   !%w430 " "!00000   !00000 " "                " "                "
  ,
  // 12 SORT
    "                " "             0  " "  NNN        0  " " NN NN       0  "
    "NN   NN      0  " "NNNNNNN      0  " "NN   NN      0  " "NN   NN      0  "
    "             0  " "MMMMMMM      0  " "    MM       0  " "   MM        0  "
    "  MM       05050" " MM         000 " "MMMMMMM      0  " "                "
  ,
  // 13 FILTER
    "                " "                " " !!!###!!!!!!!! " " !5788875555550 "
    "  !57887555550  " "   !578855550   " "    !5785550    " "     !68550     "
    "      !850      " "      !850      " "      !850      " "      !850      "
    "      !850      " "      !850      " "      !000      " "                "
  ,
  // 14 SUMMARY
    "                " "                " "   00000000000  " "   5005     50  "
    "    5005        " "     5005       " "      5005      " "       500      "
    "      5005      " "     5005       " "    5005        " "   5005     50  "
    "   00000000000  " "                " "                " "                "
  ,
  // 15 CHECK
    "                " "                " "              II" "             IMI"
    "            IMMI" "           IMMI " "          IMMI  " "  I      IMMI   "
    " IMI    IMMI    " "IMMMI  IMMI     " " IMMMIIMMI      " "  IMMMMMI       "
    "   IMMMI        " "    IMI         " "     I          " "                "
  ,
  // 16 PREV
    "                " "       44       " "      4nn4      " "     4nBBn4     "
    "    4nBBBBn4    " "   4nBBBBBBn4   " "  4nBBBBBBBBn4  " " 40000BBBB00004 "
    "     0BBBB0     " "     0BBBB0     " "     0BBBB0     " "     0BBBB0     "
    "     0BBBB0     " "     000000     " "                " "                "
  ,
  // 17 NEXT
    "                " "                " "     000000     " "     0BBBB0     "
    "     0BBBB0     " "     0BBBB0     " "     0BBBB0     " "     0BBBB0     "
    " 40000BBBB00004 " "  4nBBBBBBBBn4  " "   4nBBBBBBn4   " "    4nBBBBn4    "
    "     4nBBn4     " "      4nn4      " "       44       " "                "
  ,
  // 18 INVERT
    "                " "    bb          " "    BB      70  " "  bBBBBb   707  "
    "  bBBBBb  707   " "    BB   707    " "    bb  707     " "       707      "
    "      707       " "     707        " "    707         " "   707  bBBBBb  "
    "  707   bBBBBb  " "  07            " "                " "                "
  ,
  // 19 ZOOMIN
    "   5!11!5       " "  !4    4!      " " !7      7!     " "54   bb   45    "
    "!    BB    !    " "1  bBBBBb  1    " "1  bBBBBb  1    " "!    BB    !    "
    "54   bb   45    " " !7      7!     " "  !4    4!13    " "   5!11!5 303   "
    "           303  " "            303 " "             303" "              36"
  ,
  // 20 ZOOMOUT
    "   5!11!5       " "  !4    4!      " " !7      7!     " "54        45    "
    "!          !    " "1  bBBBBb  1    " "1  bBBBBb  1    " "!          !    "
    "54        45    " " !7      7!     " "  !4    4!13    " "   5!11!5 303   "
    "           303  " "            303 " "             303" "              36"
  ,
  // 21 SAME
    "   5!11!5       " "  !4wwww4!      " " !7wwwwww7!     " "54wwwwwwww45    "
    "!ww000000ww!    " "1wwwwwwwwww1    " "1wwwwwwwwww1    " "!ww000000ww!    "
    "54wwwwwwww45    " " !7wwwwww7!     " "  !4wwww4!13    " "   5!11!5 303   "
    "           303  " "            303 " "             303" "              36"
  ,
  // 22 WHOLE
    "                " " 00000000000000 " " 0wwwww55wwwww0 " " 0wwww0ww0wwww0 "
    " 0wwwwwwwwwwww0 " " 0wwwwwwwwwwww0 " " 0w0wwwwwwww0w0 " " 05wwwwwwwwww50 "
    " 05wwwwwwwwww50 " " 0w0wwwwwwww0w0 " " 0wwwwwwwwwwww0 " " 0wwwwwwwwwwww0 "
    " 0wwww0ww0wwww0 " " 0wwwww55wwwww0 " " 00000000000000 " "                "
  ,
  // 23 PREVWIN
    "      8!8       " "     817        " "    817         " "   817          "
    "  817           " " 817            " "817             " "100000000000001 "
    "817             " " 817            " "  817           " "   817          "
    "    817         " "     817        " "      8!8       " "                "
  ,
  // 24 NEXTWIN
    "      8!8       " "       718      " "        718     " "         718    "
    "          718   " "           718  " "            718 " "100000000000001 "
    "            718 " "           718  " "          718   " "         718    "
    "        718     " "       718      " "      8!8       " "                "
  ,
  // 25 VIEW
    "                " "wwwwwwwwwww  0  " "w0000000000  0  " "w0AA0ww0www  0  "
    "w00000000ww  0  " "w0ww0ww0www  0  " "w0ww0wwwwww  0  " "w!!##!!!!!w  0  "
    "w!57875550w  0  " "  !577550    0  " "   !6750     0  " "    !60      0  "
    "    !60    05050" "    !60     000 " "    !00      0  " "                "
  ,
  // 26 ARRANGE
    "                " "                " "wwwwwwwwwwwwwwww" "w000000000000000"
    "w0AAAA0wwww0wwww" "w0AAAA0wwww0wwww" "w000000000000www" "w0wwww0wwww0wwww"
    "w0wwww0wwwwwwwww" "w0wwww0wwwwwwwww" "w0wwww0wwwwwwwww" "w0wwwwwwwwwwwwww"
    "w0wwwwwwwwwwwwww" "w0wwwwwwwwwwwwww" "                " "                "
  ,
  // 27 EDIT
    "  !             " "  !!!!!!!!!!!!!!" "  !             " "  !             "
    "  00000000000000" "  0AAAAAAAAAAAAA" "  0AAAAAAAAAAAAA" "  0000000mmm0000"
    "  !      mQm    " "  !      mQm    " "  !!!!!!!mQmmm!!" "  !     mqQqqqm "
    "  !     mQQQQQQm" "  !!!!!!mQQQQQQm" "  !     mQQQQQQm" "  !      mQQQQm "
  ,
  // 28 ADD
    "  !             " "  !!!!!!!!!!!!!!" "  !             " "  !             "
    "  !!!!!!!!!!!!!!" "  !             " "  !      r      " "  !!!!!!rRr!!!!!"
    "  !    rRiRr    " "  !   rRiiiRr   " "  !!!rrrrirrrr!!" "        rir     "
    "00000000rir000  " "AAAAAAAArrrAA0  " "AAAAAAAAAAAAA0  " "00000000000000  "
  ,
  // 29 INSERT
    "  !             " "  !!!!!!!!!!!!!!" "  !             " "  !             "
    "  !!!!!!!!!!!!!!" "                " "0000000r000000  " "AAAAAAArrAAAA0  "
    "AAAAAAArRrAAA0  " "0000rrrriRr000  " "    riiiiiRr    " "  !!rrrriRr!!!!!"
    "  !    rRr      " "  !    rr       " "  !!!!!r!!!!!!!!" "  !             "
  ,
  // 30 DELETE
    "  !             " "  !!!!!!!!!!!!!!" "  ! rR    Rr    " "  ! RrR  RrR    "
    "  000RrRRrR00000" "  0AAARrrRAAAAAA" "  0AAARrrRAAAAAA" "  000RrRRrR00000"
    "  ! RrR  RrR    " "  ! rR    Rr    " "  !!!!!!!!!!!!!!" "  !             "
    "  !             " "  !!!!!!!!!!!!!!" "  !             " "  !             "
  ,
  // 31 COMPILE
    "                " "     000000     " "     0BBBB0     " "     0BBBB0     "
    "     0BBBB0     " "     0BBBB0     " "  4000BBBB0004  " "   4nBBBBBBn4   "
    "    4nBBBBn4    " "$$$$$$nBBn$$$$$!" "$wwwww%nn%wwwww!" "$wwwwww%%wwwwww!"
    "$wwwwwwwwwwwwww!" "$wwwwwwwwwwwwww!" "$!!!!!!!!!!!!!!!" "                "
};

  // 32x32價僢僩儅僢僾僀儊乕僕
static I1B OBI[][MNDBMPW * MNDBMPH] = {
  //  0 DUMMY
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                " "                                "
    "                                " "                                "
  ,
  //  1 INPUT
    "    $$$$$$$$$$$$$$$$$$$         " "    $wwwwwwwwwwwwwwwww$0        " "    $wwwwwwwwwwwwwwwww$$0       "
    "    $wwwwwwwwwwwwwwwww$6$0      " "    $wwwwwwwwYwwwwwwww$w6$0     " "    $wwwwwwwwqwwwwwwww$ww6$0    "
    "    $wwwYwwwwYwwwwYwww$000000   " "    $wwwwqwwzqzwwqwwwwwwwww60   " "    $wwwwwqzqYqzqwwwwwwwwww60   "
    "    $wwwwwzqYqYqzwwwwwwwwww60   " "    $wwwwzqYmmqYqzwwwwwwwww60   " "    $wYqYqYmQQmqYqYqYwwwwww60   "
    "    $wwwwzqmQQmYqzwwwwwwwww60   " "    $wwwwwzmQQmqzwwwwwwwwww60   " "    $wwwwwqmQQmzqwwwwwwwwww60   "
    "    $wwwwqwmQQmmmqwwwwwwwww60   " "    $wwwYwwmQQmQQmmmwwwwwww60   " "    $wwwwwwmQQmQQmQQmmwwwww60   "
    "    $wwwwwwmQQmQQmQQmQmwwww60   " "    $wwmmmwmQQmQQmQQmQQmwww60   " "    $wwmQQmmQQQQQQQQmQQmwww60   "
    "    $wwmQQQmQQQQQQQQQQQmwww60   " "    $wwwmQQmQQQQQQQQQQQmwww60   " "    $wwwwmQmQQQQQQQQQQQmwww60   "
    "    $wwwwmQQQQQQQQQQQQQmwww60   " "    $wwwwwmQQQQQQQQQQQQmwww60   " "    $wwwwwmQQQQQQQQQQQmwwww60   "
    "    $wwwwwwmQQQQQQQQQQmwwww60   " "    $wwwwwwmQQQQQQQQQQmwwww60   " "    $wwwwwwwmQQQQQQQQmwwwww60   "
    "    $6666666mQQQQQQQQm6666660   " "    00000000mQQQQQQQQm0000000   "
  ,
  //  2 TABLE
    "    $$$$$$$$$$$$$$$$$$$         " "    $wwwwwwwwwwwwwwwww$0        " "    $wwwwwwwwwwwwwwwww$$0       "
    "    $wwwwwwwwwwwwwwwww$6$0      " "    $wwwwwwwwwwwwwwwww$w6$0     " "    $wwwwwwwwwwwwwwwww$ww6$0    "
    "    $wwwwwwwwwwwwwwwww$000000   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   "
    "    $wwbbbbbbbbbbbbbbbbbbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbbbbbbbbbbbbbbbbbbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbbbbbbbbbbbbbbbbbbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   " "    $wwbwwwwwwwbwwwwwwwwbww60   "
    "    $wwbbbbbbbbbbbbbbbbbbww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   "
    "    $666666666666666666666660   " "    0000000000000000000000000   "
  ,
  //  3 EXECUTE
    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" "%wwwwwwwwwwwwwwwwwwwwwwwwwwwwww%" "%wwwwwwwwwwwwwwwwwwwwwwwwwwwwww%"
    "%wwwwwwwwwwwwwwwwww%%%wwwwwwwww%" "%wwwwwwwwwwwwwwwww%ww9owwwwwwww%" "%wwwwwwwwwwwwwwyy%%9%%o%y%wwwww%"
    "%wwwwwwwwwwwwwywYY%w9%oywYowwww%" "%wwwwwwwwwwwwwoyww%w%%owYyowwww%" "%wwwwwwwwwwwyyyyw%%w9%o%Y9oowww%"
    "%wwwwwwwwwwwywywY%%w%%oywYwYoww%" "%wwwwwwwwwwwoyyywYooooo9Yoyyoww%" "%wwwwwwwwwwwoyyoywwYYwYYyoyyoww%"
    "%wwwwwwwwwww%ooYYoyy9yoyw9oo9ww%" "%wwwwwwwwwwwwwyYoyyywoYyyyowwww%" "%wwwwwwwwwwwwwyYoyoyyoooyyowwww%"
    "%wwwwwwwww%%%w9oo9woYow9oowwwww%" "%wwwwwwww%ww9owwwwwooowwwwwwwww%" "%wwwwwyy%%9%%o%y%wwwwwwwwwwwwww%"
    "%wwwwywYY%w9%oywYowwwwwwwwwwwww%" "%wwwwoyww%w%%owYyowwwwwwwwwwwww%" "%wwyyyyw%%w9%o%Y9oowwwwwwwwwwww%"
    "%wwywywY%%w%%oywYwYowwwwwwwwwww%" "%wwoyyywYooooo9Yoyyowwwwwwwwwww%" "%wwoyyoywwYYwYYyoyyowwwwwwwwwww%"
    "%ww%ooYYoyy9yoyw9oo9wwwwwwwwwww%" "%wwwwyYoyyywoYyyyowwwwwwwwwwwww%" "%wwwwyYoyoyyoooyyowwwwwwwwwwwww%"
    "%wwww9oo9woYow9oowwwwwwwwwwwwww%" "%wwwwwwwwwooowwwwwwwwwwwwwwwwww%" "%wwwwwwwwwwwwwwwwwwwwwwwwwwwwww%"
    "%wwwwwwwwwwwwwwwwwwwwwwwwwwwwww%" "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
  ,
  //  4 REPORT
    "              3333              " "            33333333            " "       %%%%%%%%%%%%%%%%%%       "
    "       %wwwwwwwwwwwwwwww%       " "       %wwwwwwwwwwwwwwww%       " "       %wwwwwwwwwwwwwwww%       "
    "       %wwwwwwwwwwwwwwww%       " "       %wwwwwwwwwwwwwwww%       " "       %wwwwwwwwwwwwwwww%       "
    "       %wwwwwwwwwwwwwwww%       " "   5553%wwwwwwwwwwwwwwww%3555   " "   497$%9999999999999999%$794   "
    "   49%$344444444444444443$%94   " "  559$3$$$$$$$$$$$$$$$$$$3$955  " "  4883#222222222222222222#3884  "
    "  497#!!!!!!!!!!!!!!!!!!!!#794  " "  4972111111111111111111112794  " " 5597$#222222222222222222#$7955 "
    " 489987777777777777777777789984 " " 489999999999999999999999999984 " " 499999999999999999999999999994 "
    " 488888888888888888888888888884 " " 477777777777777777777777777774 " " 477777777777777777777777777774 "
    " 477775555555555555555555577774 " " 477757888888888888888888757774 " " 477758999999999999999999857774 "
    " 477758999999999999999999857774 " " 477758888888888888888888857774 " " 557757877777777777777778757755 "
    "  4444444444444444444444444444  " "                                "
  ,
  //  5 TEXT
    "    $$$$$$$$$$$$$$$$$$$         " "    $wwwwwwwwwwwwwwwww$0        " "    $wwwwwwwwwwwwwwwww$$0       "
    "    $wwwwwwwwwwwwwwwww$6$0      " "    $wwwwwwwwwwwwwwwww$w6$0     " "    $wwwwwwwwwwwwwwwww$ww6$0    "
    "    $wwwwwwwwwwwwwwwww$000000   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www000000000000wwwwwww60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www0000000000000000www60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www0000000000000000www60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www0000000000000000www60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www0000000000000000www60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www000000000000wwwwwww60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $www000000000000wwwwwww60   "
    "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   " "    $wwwwwwwwwwwwwwwwwwwwww60   "
    "    $666666666666666666666660   " "    0000000000000000000000000   "
  ,
  //  6 SYSTEM
    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%"
    "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%"
    "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaCwwCaaaaaaaaaaaaaaaaaaaa%" "%aaaacwwwwwcaaaaaaaaaaaaaaaaaaa%"
    "%aaaCwwwwwwwaaaaaaaaaaaaaaaaaaa%" "%aacwwwwwwwwwaaaaaaaaaaaaaaaaaa%" "%aaaaaaawwwwwaaaaaaaaaaaaaaaaaa%"
    "%aaaaaaawwwwwwaaaaaaaaaaaaaaaaa%" "%aaaaaaawaatwwwaaaaaaaaaaaaaaaa%" "%aaaaaaawtaawwwwaaaaaaaaaaaaaaa%"
    "%aacwwwwwaatwwwwwaaaaaaaaaaaaaa%" "%aaaCwwwwtaawwwwwwwaaaaaaaaaaaa%" "%aaaacwwwwwwwwwwwwwwwaaaaaaaaaa%"
    "%aaaaacwwwaaaawwwwwwwwwaaaaaaaa%" "%aaaaaaaaaaaaaaawwwwwwwwwaaaaaa%" "%aaaaaaaaaaaaaaaaawwwwwwwwwcaaa%"
    "%aaaaaaaaaaaaaaaaaaawwwwwwCwCaa%" "%aaaaaaaaaaaaaaaaaaaaawwwCaCwaa%" "%aaaaaaaaaaaaaaaaaaaaaacwwCwCaa%"
    "%aaaaaaaaaaaaaaaaaaaaaaaaCwCaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%"
    "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%"
    "%aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%" "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
  ,
  //  7 EXIT
    "      RRRRRRRRRRRRRRRRRRRR      " "     RRRRRRRRRRRRRRRRRRRRRR     " "    RRRRRRRRRRRRRRRRRRRRRRRR    "
    "   RRRRRRRRRRRRRRRRRRRRRRRRRR   " "  RRRRRRRRRRRRRRRRRRRRRRRRRRRR  " " RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR "
    "RRRRRRRiwiRRRRRRRRRRRRiwiRRRRRRR" "RRRRRRiwwwiRRRRRRRRRRiwwwiRRRRRR" "RRRRRiwwwwwiRRRRRRRRiwwwwwiRRRRR"
    "RRRRRRiwwwwwiRRRRRRiwwwwwiRRRRRR" "RRRRRRRiwwwwwiRRRRiwwwwwiRRRRRRR" "RRRRRRRRiwwwwwiRRiwwwwwiRRRRRRRR"
    "RRRRRRRRRiwwwwwiiwwwwwiRRRRRRRRR" "RRRRRRRRRRiwwwwwwwwwwiRRRRRRRRRR" "RRRRRRRRRRRiwwwwwwwwiRRRRRRRRRRR"
    "RRRRRRRRRRRRiwwwwwwiRRRRRRRRRRRR" "RRRRRRRRRRRRiwwwwwwiRRRRRRRRRRRR" "RRRRRRRRRRRiwwwwwwwwiRRRRRRRRRRR"
    "RRRRRRRRRRiwwwwwwwwwwiRRRRRRRRRR" "RRRRRRRRRiwwwwwiiwwwwwiRRRRRRRRR" "RRRRRRRRiwwwwwiRRiwwwwwiRRRRRRRR"
    "RRRRRRRiwwwwwiRRRRiwwwwwiRRRRRRR" "RRRRRRiwwwwwiRRRRRRiwwwwwiRRRRRR" "RRRRRiwwwwwiRRRRRRRRiwwwwwiRRRRR"
    "RRRRRRiwwwiRRRRRRRRRRiwwwiRRRRRR" "RRRRRRRiwiRRRRRRRRRRRRiwiRRRRRRR" " RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR "
    "  RRRRRRRRRRRRRRRRRRRRRRRRRRRR  " "   RRRRRRRRRRRRRRRRRRRRRRRRRR   " "    RRRRRRRRRRRRRRRRRRRRRRRR    "
    "     RRRRRRRRRRRRRRRRRRRRRR     " "      RRRRRRRRRRRRRRRRRRRR      "
  ,
  //  8 BACK
    "      llllllllllllllllllll      " "     llllllllllllllllllllll     " "    llllllllllllllllllllllll    "
    "   llllllllllllllllllllllllll   " "  llllllllllllllllllllllllllll  " " llllllllllllllllllllllllllllll "
    "llllllllllllllllllllllllllllllll" "llllllllllllllwwwlllllllllllllll" "lllllllllllllwwwwlllllllllllllll"
    "llllllllllllwwwwwlllllllllllllll" "lllllllllllwwwwwllllllllllllllll" "llllllllllwwwwwlllllllllllllllll"
    "lllllllllwwwwwllllllllllllllllll" "llllllllwwwwwlllllllllllllllllll" "lllllllwwwwwwwwwwwwwwwwwwwllllll"
    "llllllwwwwwwwwwwwwwwwwwwwwllllll" "llllllwwwwwwwwwwwwwwwwwwwwllllll" "lllllllwwwwwwwwwwwwwwwwwwwllllll"
    "llllllllwwwwwlllllllllllllllllll" "lllllllllwwwwwllllllllllllllllll" "llllllllllwwwwwlllllllllllllllll"
    "lllllllllllwwwwwllllllllllllllll" "llllllllllllwwwwwlllllllllllllll" "lllllllllllllwwwwlllllllllllllll"
    "llllllllllllllwwwlllllllllllllll" "llllllllllllllllllllllllllllllll" " llllllllllllllllllllllllllllll "
    "  llllllllllllllllllllllllllll  " "   llllllllllllllllllllllllll   " "    llllllllllllllllllllllll    "
    "     llllllllllllllllllllll     " "      llllllllllllllllllll      "
};

static rSTR SYSFACE = DLGFACE;
static I4B  SYSPTSZ = DLGPTSZ;
static rSTR TMPFACE = DLGFACE;
static I4B  TMPPTSZ = DLGPTSZ;

void LOCALF InitGraphicObjects(void)
{ // GDI僆僽僕僃僋僩偺嶌惉
  I4B i;
  LOGFONT lof;
  OSVERSIONINFO osvi;

  SetAppColor(CID_TXT, GetSysColor(COLOR_WINDOWTEXT));
  SetAppColor(CID_WIN, GetSysColor(COLOR_WINDOW));
  SetAppColor(CID_3DF, GetSysColor(COLOR_3DFACE));
  SetAppColor(CID_HIL, GetSysColor(COLOR_HIGHLIGHT));
  SetAppColor(CID_HIT, GetSysColor(COLOR_HIGHLIGHTTEXT));
  PEN[0] = CreatePen(PS_SOLID, 0, AppColor(0));
  BRS[0] = CreateSolidBrush(AppColor(0));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osvi);
  if (osvi.dwMajorVersion >=10) { SYSFACE = TMPFACE = "Yu Gothic UI";}
  else if (osvi.dwMajorVersion >= 6) { SYSFACE = TMPFACE = "Meiryo UI";}
  SetAppFont(FID_DLG, CreateFontIndirect(SetLOGFONT(&lof, DLGFACE,     PT2DOTS(DLGPTSZ), 0)));
  SetAppFont(FID_SYS, CreateFontIndirect(SetLOGFONT(&lof, SYSFACE,     PT2DOTS(SYSPTSZ), 0)));
  SetAppFont(FID_DEF, CreateFontIndirect(SetLOGFONT(&lof, DEFFACE,     PT2DOTS(DEFPTSZ), 0)));
  SetAppFont(FID_MON, CreateFontIndirect(SetLOGFONT(&lof, MONFACE,     PT2DOTS(MONPTSZ), 0)));
  SetAppFont(FID_WEB, CreateFontIndirect(SetLOGFONT(&lof, "Webdings",  PT2DOTS(SYSPTSZ), 0)));
  SetAppFont(FID_WIN, CreateFontIndirect(SetLOGFONT(&lof, "WingDings", PT2DOTS(SYSPTSZ), 0)));
  for (i = 0; i < _countof(MBI); i++) {
    SetAppDDB(BID_BLANK + i, CreateDDBFromSTR(MNUBMPW, MNUBMPH, MBI[i]));
  }
  for (i = 0; i < _countof(OBI); i++) {
    SetAppDDB(BID_DUMMY + i, CreateDDBFromSTR(MNDBMPW, MNDBMPH, OBI[i]));
  }
}

void LOCALF TermGraphicObjects(void)
{ // GDI僆僽僕僃僋僩偺嶍彍
  I4B i;

  for (i = 0; i < _countof(PEN); i++) {
    if (PEN[i]) { DeleteObject(PEN[i]);}
  }
  for (i = 0; i < _countof(BRS); i++) {
    if (BRS[i]) { DeleteObject(BRS[i]);}
  }
  for (i = 0; i < _countof(FNT); i++) {
    if (FNT[i]) { DeleteObject(FNT[i]);}
  }
  for (i = 0; i < _countof(BMP); i++) {
    if (BMP[i]) { DeleteObject(BMP[i]);}
  }
}

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

  // 戅旔椞堟
typedef struct {
  HPEN  hpen;
  HFNT  hfnt;
  I4B   bkm;
  BGRC  tco;
  I4B   tal;
  I4B   tcx;
} CVSP;
typedef CVSP *pCVSP;

  // 昤夋僐儞僥僉僗僩
typedef struct {
  HDC   hdc;
  I4B   dpi;
  F8B   Dx, Dy;
  F8B   Mx, My;
  I4B   xorg, yorg;
  I4B   xscl, yscl;
  I4B   lst;
  BGRC  lco;
  I1B   tfa[32];
  I4B   tcw, tch;
  I4B   tcd;
  I4B   tst;
  BGRC  tco;
  I4B   hcm, vcm;
  U4B   rsv;
  HDC   bak;
  HDC   hic;
  CVSP  org;
  CVSP  inf;
} CVSE;
typedef CVSE *pCVSE;

#define  hDC(cv)  (((pCVSE)cv)->hdc)
#define  hIC(cv)  (((pCVSE)cv)->hic)
#define  hBK(cv)  (((pCVSE)cv)->bak)

#define  iW(cv, w)  iround(fabs(((pCVSE)cv)->Mx) * (w))
#define  iH(cv, h)  iround(fabs(((pCVSE)cv)->My) * (h))
#define  iX(cv, x)  iround(((pCVSE)cv)->Mx * (x) + ((pCVSE)cv)->Dx)
#define  iY(cv, y)  iround(((pCVSE)cv)->My * (y) + ((pCVSE)cv)->Dy)

#define  rW(cv, w)  ((w) / fabs(((pCVSE)cv)->Mx))
#define  rH(cv, h)  ((h) / fabs(((pCVSE)cv)->My))
#define  rX(cv, x)  (((x) - ((pCVSE)cv)->Dx) / ((pCVSE)cv)->Mx)
#define  rY(cv, y)  (((y) - ((pCVSE)cv)->Dy) / ((pCVSE)cv)->My)

#define  PENSTY(cv)  ((((pCVSE)cv)->lst & 0x0f)? PS_SOLID: (((pCVSE)cv)->lst == 0)? PS_NULL: ((pCVSE)cv)->lst >> 4)
#define  PENWID(cv)  ((I4B)((((pCVSE)cv)->lst & 0x0f) * 0.1 * ((pCVSE)cv)->dpi / MMPI))
#define  PENCOL(cv)  ((pCVSE)cv)->lco)

pLOGFONT LOCALF canvaslof(pLOGFONT lf, pCVSE cv)
{ // 榑棟僼僅儞僩
  SetLOGFONT(lf, cv->tfa, iH(cv, cv->tch * 0.001), cv->tst);
  lf->lfWidth = iW(cv, cv->tcw * 0.001);
  return lf;
}

void LOCALF saveparams(pCVSE cv)
{ // 僷儔儊乕僞戅旔
  LOGFONT lof;

  if (cv->hdc) {
    cv->org.bkm = SetBkMode(cv->hdc, TRANSPARENT);
    cv->org.tco = SetTextColor(cv->hdc, cv->tco);
    cv->org.tal = SetTextAlign(cv->hdc, TA_LEFT|TA_TOP|TA_NOUPDATECP);
    cv->org.tcx = SetTextCharacterExtra(cv->hdc, iW(cv, cv->tcd * 0.001));
    cv->org.hpen = SelectObject(cv->hdc, CreatePen(PENSTY(cv), PENWID(cv), cv->lco));
    cv->org.hfnt = SelectObject(cv->hdc, CreateFontIndirect(canvaslof(&lof, cv)));
  }
  if (cv->hic) {
    cv->inf.tal = SetTextAlign(cv->hic, TA_LEFT|TA_TOP|TA_NOUPDATECP);
    cv->inf.tcx = SetTextCharacterExtra(cv->hic, iW(cv, cv->tcd * 0.001));
    cv->inf.hfnt = SelectObject(cv->hic, CreateFontIndirect(canvaslof(&lof, cv)));
  }
}

void LOCALF restoreparams(pCVSE cv)
{ // 僷儔儊乕僞暅婣
  if (cv->hdc) {
    DeleteObject(SelectObject(cv->hdc, cv->org.hfnt));
    DeleteObject(SelectObject(cv->hdc, cv->org.hpen));
    SetTextCharacterExtra(cv->hdc, cv->org.tcx);
    SetTextAlign(cv->hdc, cv->org.tal);
    SetTextColor(cv->hdc, cv->org.tco);
    SetBkMode(cv->hdc, cv->org.bkm);
  }
  if (cv->hic) {
    DeleteObject(SelectObject(cv->hdc, cv->inf.hfnt));
    SetTextCharacterExtra(cv->hdc, cv->inf.tcx);
    SetTextAlign(cv->hdc, cv->inf.tal);
  }
}

HCVS WINAPI CreateCanvas(HDC hdc, U4B xsz)
{ // 昤夋僐儞僥僉僗僩偺嶌惉
  pCVSE cv;

  cv = halloc(sizeof(CVSE) + xsz, TRUE); if (!cv) { return ierr(E_MEM);}
  cv->hdc = hdc;
  cv->dpi = hdc? GetDeviceCaps(hdc, LOGPIXELSX): DEFDPI;
  cv->Mx = cv->My = cv->dpi / MMPI;
  cv->xscl = cv->yscl = 1000;
  cv->lst = LST_REG;
  strcpyx(cv->tfa, DEFFACE, sizeof(cv->tfa) - 1);
  cv->tch = iround(DEFPTSZ * MMPI * 1000.0 / PTPI);
  cv->hcm = cv->tch / 6;
  cv->hic = CreateIC("DISPLAY", NULL, NULL, NULL);
  saveparams(cv);
  return (HCVS)cv;
}

void WINAPI DeleteCanvas(HCVS cv)
{ // 昤夋僐儞僥僉僗僩偺嶍彍
  if (!cv) return;
  restoreparams((pCVSE)cv);
  DeleteDC(hIC(cv));
  hDC(cv) = NULL;
  hfree(cv);
}

HDC  WINAPI SetCanvasHDC(HCVS cv, HDC hdc, I4B dpi)
{ // 僨僶僀僗僐儞僥僉僗僩偺愝掕
  HDC pre = hDC(cv);

  restoreparams((pCVSE)cv);
  hDC(cv) = hdc;
  ((pCVSE)cv)->dpi = dpi? dpi: hdc? GetDeviceCaps(hdc, LOGPIXELSX): DEFDPI;
  ((pCVSE)cv)->Dx = ((pCVSE)cv)->xorg * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  ((pCVSE)cv)->Dy = ((pCVSE)cv)->yorg * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  ((pCVSE)cv)->Mx = ((pCVSE)cv)->xscl * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  ((pCVSE)cv)->My = ((pCVSE)cv)->yscl * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  saveparams((pCVSE)cv);
  return pre;
}

HDC  WINAPI CanvasHDC(HCVS cv)
{ // 僨僶僀僗僐儞僥僉僗僩
  return hDC(cv);
}

HDC  WINAPI CanvasHIC(HCVS cv)
{ // 忣曬僐儞僥僉僗僩
  return hIC(cv);
}

BOOL WINAPI EnableCanvas(HCVS cv)
{ // 昤夋偺桳岠壔
  I4B pre = !!hDC(cv);

  if (!hDC(cv) && hBK(cv)) { hDC(cv) = hBK(cv);}
  return pre;
}

BOOL WINAPI DisableCanvas(HCVS cv)
{ // 昤夋偺柍岠壔
  I4B pre = !!hDC(cv);

  if (hDC(cv)) { hBK(cv) = hDC(cv); hDC(cv) = NULL;}
  return pre;
}

pLOGFONT WINAPI CanvasLOGFONT(pLOGFONT lf, HCVS cv)
{ // 榑棟僼僅儞僩
  return canvaslof(lf, (pCVSE)cv);
}

void WINAPI SetOrigin(HCVS cv, F8B xorg, F8B yorg)
{ // 尨揰偺愝掕
  ((pCVSE)cv)->xorg = iround(xorg * 1000.0);
  ((pCVSE)cv)->yorg = iround(yorg * 1000.0);
  ((pCVSE)cv)->Dx = ((pCVSE)cv)->xorg * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  ((pCVSE)cv)->Dy = ((pCVSE)cv)->yorg * 0.001 * ((pCVSE)cv)->dpi / MMPI;
}

F8B  WINAPI OriginX(HCVS cv)
{ // 尨揰X嵗昗
  return ((pCVSE)cv)->xorg * 0.001;
}

F8B  WINAPI OriginY(HCVS cv)
{ // 尨揰Y嵗昗
  return ((pCVSE)cv)->yorg * 0.001;
}

void WINAPI SetScale(HCVS cv, F8B xscl, F8B yscl)
{ // 攞棪偺愝掕
  if (xscl == 0.0) { xscl = 1.0;}
  if (yscl == 0.0) { yscl = xscl;}
  ((pCVSE)cv)->xscl = iround(xscl * 1000.0);
  ((pCVSE)cv)->yscl = iround(yscl * 1000.0);
  ((pCVSE)cv)->Mx = ((pCVSE)cv)->xscl * 0.001 * ((pCVSE)cv)->dpi / MMPI;
  ((pCVSE)cv)->My = ((pCVSE)cv)->yscl * 0.001 * ((pCVSE)cv)->dpi / MMPI;
}

F8B  WINAPI ScaleX(HCVS cv)
{ // X曽岦攞棪
  return ((pCVSE)cv)->xscl * 0.001;
}

F8B  WINAPI ScaleY(HCVS cv)
{ // Y曽岦攞棪
  return ((pCVSE)cv)->yscl * 0.001;
}

I4B  WINAPI c2dW(HCVS cv, F8B w)
{ // 幚悺嵗昗忋偺暆仺僺僋僙儖嵗昗忋偺暆
  return iW(cv, w);
}

I4B  WINAPI c2dH(HCVS cv, F8B h)
{ // 幚悺嵗昗忋偺崅偝仺僺僋僙儖嵗昗忋偺崅偝
  return iH(cv, h);
}

I4B  WINAPI c2dX(HCVS cv, F8B x)
{ // 幚悺嵗昗忋偺X嵗昗仺僺僋僙儖嵗昗忋偺X嵗昗
  return iX(cv, x);
}

I4B  WINAPI c2dY(HCVS cv, F8B y)
{ // 幚悺嵗昗忋偺Y嵗昗仺僺僋僙儖嵗昗忋偺Y嵗昗
  return iY(cv, y);
}

F8B  WINAPI d2cW(HCVS cv, I4B w)
{ // 僺僋僙儖嵗昗忋偺暆仺幚悺嵗昗忋偺暆
  return rW(cv, w);
}

F8B  WINAPI d2cH(HCVS cv, I4B h)
{ // 僺僋僙儖嵗昗忋偺崅偝仺幚悺嵗昗忋偺崅偝
  return rH(cv, h);
}

F8B  WINAPI d2cX(HCVS cv, I4B x)
{ // 僺僋僙儖嵗昗忋偺X嵗昗仺幚悺嵗昗忋偺X嵗昗
  return rX(cv, x);
}

F8B  WINAPI d2cY(HCVS cv, I4B y)
{ // 僺僋僙儖嵗昗忋偺Y嵗昗仺幚悺嵗昗忋偺Y嵗昗
  return rY(cv, y);
}

pCELL WINAPI SetCell(pCELL pc, F8B x1, F8B y1, F8B x2, F8B y2)
{ // 僙儖嬮宍偺愝掕
  pc->x1 = x1; pc->y1 = y1; pc->x2 = x2; pc->y2 = y2;
  return pc;
}

pRECT WINAPI c2dRect(pRECT pr, HCVS cv, rCELL pc)
{ // 幚悺嵗昗忋偺僙儖嬮宍偵懳墳偡傞僺僋僙儖嵗昗忋偺RECT嬮宍
  I4B t;

  SetRect(pr, iX(cv, pc->x1), iY(cv, pc->y1), iX(cv, pc->x2), iY(cv, pc->y2));
  if (pr->lft > pr->rgt) { t = pr->lft; pr->lft = pr->rgt; pr->rgt = t;}
  if (pr->top > pr->btm) { t = pr->top; pr->top = pr->btm; pr->btm = t;}
  return pr;
}

pCELL WINAPI d2cCell(pCELL pc, HCVS cv, rRECT pr)
{ // 僺僋僙儖嵗昗忋偺RECT嬮宍偵懳墳偡傞幚悺嵗昗忋偺僙儖嬮宍
  F8B t;

  SetCell(pc, rX(cv, pr->lft), rY(cv, pr->top), rX(cv, pr->rgt), rY(cv, pr->btm));
  if (pc->x1 > pc->x2) { t = pc->x1; pc->x1 = pc->x2; pc->x2 = t;}
  if (pc->y1 > pc->y2) { t = pc->y1; pc->y1 = pc->y2; pc->y2 = t;}
  return pc;
}

pCELL WINAPI MoveCell(pCELL pc, F8B dx, F8B dy)
{ // 僙儖嬮宍偺堏摦
  pc->x1 += dx; pc->y1 += dy;
  pc->x2 += dx; pc->y2 += dy;
  return pc;
}

pCELL WINAPI ResizeCell(pCELL pc, F8B dx, F8B dy)
{ // 僙儖嬮宍偺僒僀僘曄峏
  pc->x2 += dx;
  pc->y2 += dy;
  return pc;
}

pCELL WINAPI ReshapeCell(pCELL pc, F8B lm, F8B tm, F8B rm, F8B bm)
{ // 僙儖嬮宍偺曄宍
  pc->x1 += lm; pc->y1 += tm;
  pc->x2 -= rm; pc->y2 -= bm;
  return pc;
}

void WINAPI SetCellMargin(HCVS cv, F8B hcmg, F8B vcmg)
{ // 僙儖撪僷僨傿儞僌偺愝掕
  ((pCVSE)cv)->hcm = iround(hcmg * 1000.0);
  ((pCVSE)cv)->vcm = iround(vcmg * 1000.0);
}

F8B  WINAPI CellMarginH(HCVS cv)
{ // 僙儖撪嵍塃僷僨傿儞僌
  return ((pCVSE)cv)->hcm * 0.001;
}

F8B  WINAPI CellMarginV(HCVS cv)
{ // 僙儖撪忋壓僷僨傿儞僌
  return ((pCVSE)cv)->vcm * 0.001;
}

I4B  WINAPI SetLineStyle(HCVS cv, I4B lst)
{ // 慄庬愝掕
  I4B bst = ((pCVSE)cv)->lst;

  ((pCVSE)cv)->lst = lst;
  if (hDC(cv)) { DeleteObject(SelectObject(hDC(cv), CreatePen(PENSTY(cv), PENWID(cv), PENCOL(cv)));}
  return bst;
}

BGRC WINAPI SetLineColor(HCVS cv, BGRC col)
{ // 慄怓愝掕
  I4B lco = ((pCVSE)cv)->lco;

  ((pCVSE)cv)->lco = col;
  if (hDC(cv)) { DeleteObject(SelectObject(hDC(cv), CreatePen(PENSTY(cv), PENWID(cv), PENCOL(cv)));}
  return lco;
}

void WINAPI SetTextFont(HCVS cv, rSTR face, F8B ch, I4B flg, BGRC col)
{ // 僥僉僗僩僼僅儞僩愝掕
  LOGFONT lof;

  if (face) { strcpyx(((pCVSE)cv)->tfa, face, sizeof(((pCVSE)cv)->tfa) - 1);}
  ((pCVSE)cv)->tcw = 0;
  if (ch > 0.0) { ((pCVSE)cv)->tch = iround(ch * 1000.0);}
  ((pCVSE)cv)->tcd = 0;
  ((pCVSE)cv)->tst = flg;
  ((pCVSE)cv)->tco = col;
  if (hDC(cv)) {
    DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
    SetTextCharacterExtra(hDC(cv), iW(cv, ((pCVSE)cv)->tcd * 0.001));
    SetTextColor(hDC(cv), ((pCVSE)cv)->tco);
  }
  if (hIC(cv)) {
    DeleteObject(SelectObject(hIC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
    SetTextCharacterExtra(hIC(cv), iW(cv, ((pCVSE)cv)->tcd * 0.001));
  }
}

void WINAPI SetTextStyle(HCVS cv, F8B cw, F8B ch, F8B cd, rSTR face)
{ // 僥僉僗僩暥帤僒僀僘丄僼僅儞僩愝掕
  LOGFONT lof;

  if (face) { strcpyx(((pCVSE)cv)->tfa, face, sizeof(((pCVSE)cv)->tfa) - 1);}
  ((pCVSE)cv)->tcw = (cw > 0.0)? iround(cw * 1000.0): 0;
  if (ch > 0.0) { ((pCVSE)cv)->tch = iround(ch * 1000.0);}
  ((pCVSE)cv)->tcd = (cd > 0.0)? iround(cd * 1000.0): 0;
  if (hDC(cv)) {
    DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
    SetTextCharacterExtra(hDC(cv), iW(cv, ((pCVSE)cv)->tcd * 0.001));
  }
  if (hIC(cv)) {
    DeleteObject(SelectObject(hIC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
    SetTextCharacterExtra(hIC(cv), iW(cv, ((pCVSE)cv)->tcd * 0.001));
  }
}

pWHSZ WINAPI TextSize(pWHSZ sz, HCVS cv, rSTR st, I4B cb)
{ // 暥帤楍偺僒僀僘
  SIZE siz;

  GetTextSize(&siz, hDC(cv)? hDC(cv): hIC(cv), NULL, st, cb);
  sz->w = d2cW(cv, siz.cx);
  sz->h = d2cH(cv, siz.cy);
  return sz;
}

pSIZE WINAPI TextSizeD(pSIZE sz, HCVS cv, rSTR st, I4B cb)
{ // 暥帤楍偺僒僀僘
  GetTextSize(sz, hDC(cv)? hDC(cv): hIC(cv), NULL, st, cb); return sz;
}

pWHSZ WINAPI AveCharSize(pWHSZ sz, HCVS cv)
{ // 暯嬒暥帤僒僀僘
  SIZE siz;

  GetAveCharSize(&siz, hDC(cv)? hDC(cv): hIC(cv), NULL);
  sz->w = d2cW(cv, siz.cx);
  sz->h = d2cH(cv, siz.cy);
  return sz;
}

pSIZE WINAPI AveCharSizeD(pSIZE sz, HCVS cv)
{ // 暯嬒暥帤僒僀僘
  GetAveCharSize(sz, hDC(cv)? hDC(cv): hIC(cv), NULL); return sz;
}

pWHSZ WINAPI ZenCharSize(pWHSZ sz, HCVS cv)
{ // 慡妏暥帤僒僀僘
  SIZE siz;

  GetZenCharSize(&siz, hDC(cv)? hDC(cv): hIC(cv), NULL);
  sz->w = d2cW(cv, siz.cx);
  sz->h = d2cH(cv, siz.cy);
  return sz;
}

pSIZE WINAPI ZenCharSizeD(pSIZE sz, HCVS cv)
{ // 慡妏暥帤僒僀僘
  GetZenCharSize(sz, hDC(cv)? hDC(cv): hIC(cv), NULL); return sz;
}

void WINAPI DrawLineD(HCVS cv, I4B x1, I4B y1, I4B x2, I4B y2)
{ // 慄暘偺昤夋
  if (!hDC(cv)) return;
  MoveTo(hDC(cv), x1, y1); LineTo(hDC(cv), x2, y2);
}

void WINAPI DrawLine(HCVS cv, F8B x1, F8B y1, F8B x2, F8B y2)
{ // 慄暘偺昤夋
  if (!hDC(cv)) return;
  MoveTo(hDC(cv), iX(cv, x1), iY(cv, y1)); LineTo(hDC(cv), iX(cv, x2), iY(cv, y2));
}

void WINAPI DrawCirc(HCVS cv, F8B xc, F8B yc, F8B rc, F8B t1, F8B t2)
{ // 墌(墌屖)偺昤夋
  I4B cx, cy, rx, ry, sx, sy, ex, ey;

  if (!hDC(cv)) return;
  cx = iX(cv, xc); cy = iY(cv, yc);
  rx = iW(cv, rc); ry = iH(cv, rc);
  sx = iX(cv, xc + rc * cos(t1 * RPD));
  sy = iY(cv, yc - rc * sin(t1 * RPD));
  ex = iX(cv, xc + rc * cos(t2 * RPD));
  ey = iY(cv, yc - rc * sin(t2 * RPD));
  Arc(hDC(cv), cx - rx, cy - ry, cx + rx + 1, cy + ry + 1, sx, sy, ex, ey);
}

void WINAPI DrawCellD(HCVS cv, rRECT pr, I4B rst)
{ // 嬮宍偺昤夋
  I4B lst;

  if (!hDC(cv)) return;
  lst = ((pCVSE)cv)->lst;
  if (rst == RST_DEF) { rst = RST(lst, lst, lst, lst);}
  SetLineStyle(cv, ((rU1B)&rst)[0]); DrawLineD(cv, pr->lft, pr->top, pr->lft, pr->btm);
  SetLineStyle(cv, ((rU1B)&rst)[1]); DrawLineD(cv, pr->lft, pr->top, pr->rgt, pr->top);
  SetLineStyle(cv, ((rU1B)&rst)[2]); DrawLineD(cv, pr->rgt, pr->btm, pr->rgt, pr->top);
  SetLineStyle(cv, ((rU1B)&rst)[3]); DrawLineD(cv, pr->lft, pr->btm, pr->rgt, pr->btm);
  SetLineStyle(cv, lst);
}

void WINAPI DrawCell(HCVS cv, rCELL pc, I4B rst)
{ // 嬮宍偺昤夋
  RECT rct; DrawCellD(cv, c2dRect(&rct, cv, pc), rst);
}

void WINAPI FillCellD(HCVS cv, rRECT pr, I4B rst, BGRC col)
{ // 嬮宍偺揾傝偮傇偟
  HBRS hbrs;
  RECT rct;

  if (!hDC(cv)) return;
  SetRect(&rct, pr->lft, pr->top, pr->rgt + 1, pr->btm + 1);
  hbrs = CreateSolidBrush(col);
  FillRect(hDC(cv), &rct, hbrs);
  DeleteObject(hbrs);
  if (rst) { DrawCellD(cv, pr, rst);}
}

void WINAPI FillCell(HCVS cv, rCELL pc, I4B rst, BGRC col)
{ // 嬮宍偺揾傝偮傇偟
  RECT rct; FillCellD(cv, c2dRect(&rct, cv, pc), rst, col);
}

void WINAPI FillPolyD(HCVS cv, rPOINT pt, I4B np, BGRC col)
{ // 懡妏宍偺揾傝偮傇偟
  HBRS hbrs;

  if (!hDC(cv) || np < 3) return;
  hbrs = SelectObject(hDC(cv), CreateSolidBrush(col));
  Polygon(hDC(cv), pt, np);
  DeleteObject(SelectObject(hDC(cv), hbrs));
}

void WINAPI FillPoly(HCVS cv, rXYPT pt, I4B np, BGRC col)
{ // 懡妏宍偺揾傝偮傇偟
  I4B i;
  POINT ap[256];

  if (np > _countof(ap)) return;
  for (i = 0; i < np; i++) {
    ap[i].x = iX(cv, pt[i].x);
    ap[i].y = iY(cv, pt[i].y);
  }
  FillPolyD(cv, ap, np, col);
}

void WINAPI FillCirc(HCVS cv, F8B xc, F8B yc, F8B rc, F8B t1, F8B t2, BGRC col)
{ // 墌(愵宍)偺揾傝偮傇偟
  I4B cx, cy, rx, ry, sx, sy, ex, ey;
  HBRS hbrs;

  if (!hDC(cv)) return;
  cx = iX(cv, xc); cy = iY(cv, yc);
  rx = iW(cv, rc); ry = iH(cv, rc);
  sx = iX(cv, xc + rc * cos(t1 * RPD));
  sy = iY(cv, yc - rc * sin(t1 * RPD));
  ex = iX(cv, xc + rc * cos(t2 * RPD));
  ey = iY(cv, yc - rc * sin(t2 * RPD));
  hbrs = SelectObject(hDC(cv), CreateSolidBrush(col));
  Pie(hDC(cv), cx - rx, cy - ry, cx + rx + 1, cy + ry + 1, sx, sy, ex, ey);
  DeleteObject(SelectObject(hDC(cv), hbrs));
}

void LOCALF stext(HCVS cv, pRECT pr, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋
  DrawText(hDC(cv), st, -1, pr, fmt);
}

void LOCALF atext(HCVS cv, pRECT pr, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋(弅彫偟偰慡懱傪昞帵)
  I4B tcx;
  RECT rct = *pr;
  SIZE siz;
  LOGFONT lof;

  DrawText(hDC(cv), st, -1, &rct, fmt | DT_CAL);
  if (rct.rgt - rct.lft <= pr->rgt - pr->lft) {
    stext(cv, pr, st, fmt); return;
  }
  tcx = SetTextCharacterExtra(hDC(cv), 0);
  GetAveCharSize(&siz, hDC(cv), CanvasLOGFONT(&lof, cv));
  for (lof.lfWidth = siz.cx; lof.lfWidth > 2; lof.lfWidth--) {
    DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(&lof)));
    DrawText(hDC(cv), st, -1, &rct, fmt | DT_CAL);
    if (rct.rgt - rct.lft <= pr->rgt - pr->lft) break;
  }
  DrawText(hDC(cv), st, -1, pr, fmt);
  DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
  SetTextCharacterExtra(hDC(cv), tcx);
}

void LOCALF mtext(HCVS cv, pRECT pr, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋(暋悢峴)
  I4B tcx;
  RECT rct = *pr;
  SIZE siz;
  LOGFONT lof;

  DrawText(hDC(cv), st, -1, &rct, fmt | DT_CAL);
  if (rct.btm - rct.top <= pr->btm - pr->top) {
    OffsetRect(&rct, 0, (fmt & 0x0c) * (pr->btm - pr->top - rct.btm + rct.top) / 8);
    DrawText(hDC(cv), st, -1, &rct, fmt); if (fmt & DT_CAL) { *pr = rct;}
    return;
  }
  tcx = SetTextCharacterExtra(hDC(cv), 0);
  GetAveCharSize(&siz, hDC(cv), CanvasLOGFONT(&lof, cv));
  for ( ; lof.lfHeight < -8; lof.lfHeight++) {
    lof.lfWidth = 0;
    DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(&lof)));
    DrawText(hDC(cv), st, -1, &rct, fmt | DT_CAL);
    rct.lft = pr->lft; rct.rgt = pr->rgt;
    if (rct.btm - rct.top <= pr->btm - pr->top) break;
  }
  OffsetRect(&rct, 0, (fmt & 0x0c) * (pr->btm - pr->top - rct.btm + rct.top) / 8);
  DrawText(hDC(cv), st, -1, &rct, fmt); if (fmt & DT_CAL) { *pr = rct;}
  DeleteObject(SelectObject(hDC(cv), CreateFontIndirect(CanvasLOGFONT(&lof, cv))));
  SetTextCharacterExtra(hDC(cv), tcx);
}

void LOCALF jtext(HCVS cv, pRECT pr, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋(嬒摍妱晅)
  I4B nc, tcx;
  RECT rct = *pr;

  if ((nc = mbslen(st)) < 2) {
    stext(cv, pr, st, DT_CEN); return;
  }
  DrawText(hDC(cv), st, -1, &rct, fmt | DT_CAL);
  if (rct.rgt - rct.lft > pr->rgt - pr->lft) {
    atext(cv, pr, st, fmt); return;
  }
  tcx = SetTextCharacterExtra(hDC(cv), (pr->rgt - pr->lft - rct.rgt + rct.lft) / (nc - 1));
  DrawText(hDC(cv), st, -1, pr, fmt);
  SetTextCharacterExtra(hDC(cv), tcx);
}

I4B  LOCALF DT2DT(I4B fmt)
{ // 惍宍僼儔僌偺曄姺
  if (!(fmt & DT_PRE)) { fmt |= DT_NOPREFIX;}
  if (fmt & DT_MUL) { fmt |= (DT_WORDBREAK|DT_EDITCONTROL);} else { fmt |= DT_SINGLELINE;}
  if (fmt & DT_FRC) { fmt &=~DT_FRC;} else if (!(fmt & DT_BTM)) { fmt |= DT_VCENTER;}
  if (!(fmt & DT_CLP)) { fmt |= DT_NOCLIP;}
  return fmt &~0xff000000;
}

void WINAPI CellTextD(HCVS cv, pRECT pc, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋
  RECT rct = *pc;

  if (!hDC(cv) || st[0] == '\0') return;
  InflateRect(&rct, -CellMarginHD(cv), -CellMarginVD(cv)); if (IsRectEmpty(&rct)) return;
  switch (fmt & 0xff000003) {
  case DT_LFT: case DT_CEN: case DT_RGT:
    stext(cv, &rct, st, DT2DT(fmt)); break;
  case DT_AUT: case DT_AUT|DT_CEN: case DT_AUT|DT_RGT:
    atext(cv, &rct, st, DT2DT(fmt)); break;
  case DT_MUL: case DT_AUT|DT_MUL:
    mtext(cv, &rct, st, DT2DT(fmt)); break;
  case DT_JST: case DT_JST|DT_CEN: case DT_JST|DT_RGT:
  case DT_AUT|DT_JST: case DT_AUT|DT_JST|DT_CEN: case DT_AUT|DT_JST|DT_RGT:
    jtext(cv, &rct, st, DT2DT(fmt)); break;
  }
  if (fmt & DT_CAL) { *pc = rct;}
}

void WINAPI CellText(HCVS cv, pCELL pc, rSTR st, I4B fmt)
{ // 暥帤楍偺昤夋
  RECT rct; CellTextD(cv, c2dRect(&rct, cv, pc), st, fmt); if (fmt & DT_CAL) { d2cCell(pc, cv, &rct);}
}

void LOCALF vtext(HCVS cv, pRECT pr, rSTR st, I4B fmt)
{ // 廲彂偒暥帤楍偺昤夋
  I4B n;
  SIZE siz;
  RECT rct;

  n = mbslen(st);
  GetZenCharSize(&siz, hDC(cv), NULL);
  rct.lft = pr->lft + ((fmt & VT_RGT)? 2: (fmt & VT_LFT)? 0: 1) * (pr->rgt - pr->lft - siz.cx) / 2;
  rct.top = pr->top + ((fmt & VT_BTM)? 2: (fmt & VT_MID)? 1: 0) * (pr->btm - pr->top - n * siz.cy) / 2;
  rct.rgt = rct.lft + siz.cx;
  rct.btm = rct.top + n * siz.cy;
  if (rct.btm - rct.top > pr->btm - pr->top) {
    rct.top = pr->top; rct.btm = pr->btm;
  }
  if (fmt & VT_CAL) { *pr = rct; return;}
  SetRect(&rct, rct.rgt, rct.top, rct.rgt + rct.btm - rct.top, rct.top + rct.rgt - rct.lft);
  atext(cv, &rct, st, DT2DT(DT_CEN));
}

void WINAPI VCellTextD(HCVS cv, pRECT pc, rSTR st, I4B fmt)
{ // 廲彂偒暥帤楍偺昤夋
  RECT rct = *pc;

  if (!hDC(cv) || st[0] == '\0') return;
  InflateRect(&rct, -CellMarginHD(cv), -CellMarginVD(cv)); if (IsRectEmpty(&rct)) return;
  vtext(cv, &rct, st, fmt); if (fmt & VT_CAL) { *pc = rct;}
}

void WINAPI VCellText(HCVS cv, pCELL pc, rSTR st, I4B fmt)
{ // 廲彂偒暥帤楍偺昤夋
  RECT rct; VCellTextD(cv, c2dRect(&rct, cv, pc), st, fmt); if (fmt & VT_CAL) { d2cCell(pc, cv, &rct);}
}

void WINAPI SetGrid0(pGRID gr, F8B x0, F8B y0, I4B nc, I4B nr, F8B dcw, F8B drh)
{ // 僌儕僢僪偺愝掕
  gr->x0 = x0; gr->y0 = y0; gr->dcw = dcw; gr->drh = drh; gr->cw = NULL; gr->nc = nc; gr->rh = NULL; gr->nr = nr;
}

void WINAPI SetGrid1(pGRID gr, F8B x0, F8B y0, I4B nc, I4B nr, F8B *cw, F8B drh)
{ // 僌儕僢僪偺愝掕
  gr->x0 = x0; gr->y0 = y0; gr->dcw = 0.0; gr->drh = drh; gr->cw = cw; gr->nc = nc; gr->rh = NULL; gr->nr = nr;
}

void WINAPI SetGrid2(pGRID gr, F8B x0, F8B y0, I4B nc, I4B nr, F8B dcw, F8B *rh)
{ // 僌儕僢僪偺愝掕
  gr->x0 = x0; gr->y0 = y0; gr->dcw = dcw; gr->drh = 0.0; gr->cw = NULL; gr->nc = nc; gr->rh = rh; gr->nr = nr;
}

void WINAPI SetGrid3(pGRID gr, F8B x0, F8B y0, I4B nc, I4B nr, F8B *cw, F8B *rh)
{ // 僌儕僢僪偺愝掕
  gr->x0 = x0; gr->y0 = y0; gr->dcw = 0.0; gr->drh = 0.0; gr->cw = cw; gr->nc = nc; gr->rh = rh; gr->nr = nr;
}

pGRID WINAPI AdjustGrid(HCVS cv, pGRID gr)
{ // 僌儕僢僪偺挷惍
  I4B i;

  if (gr->cw) {
    for (i = 0; i < gr->nc; i++) {
      gr->cw[i] = rW(cv, iW(cv, gr->cw[i]));
    }
  } else {
    gr->dcw = rW(cv, iW(cv, gr->dcw));
  }
  if (gr->rh) {
    for (i = 0; i < gr->nr; i++) {
      gr->rh[i] = rH(cv, iH(cv, gr->rh[i]));
    }
  } else {
    gr->drh = rH(cv, iH(cv, gr->drh));
  }
  return gr;
}

pCELL WINAPI GridCell(pCELL pc, rGRID gr, I4B ir, I4B ic)
{ // 僌儕僢僪偺僙儖嬮宍
  I4B i;

  if (gr->cw) {
    pc->x1 = gr->x0;
    for (i = 0; i < ic; i++) {
      pc->x1 += gr->cw[i];
    }
    pc->x2 = pc->x1 + gr->cw[i];
  } else {
    pc->x1 = gr->x0 + ic * gr->dcw;
    pc->x2 = pc->x1 + gr->dcw;
  }
  if (gr->rh) {
    pc->y1 = gr->y0;
    for (i = 0; i < ir; i++) {
      pc->y1 += gr->rh[i];
    }
    pc->y2 = pc->y1 + gr->rh[i];
  } else {
    pc->y1 = gr->y0 + ir * gr->drh;
    pc->y2 = pc->y1 + gr->drh;
  }
  return pc;
}

I4B  LOCALF RST2(rGRID gr, I4B ir, I4B ic, I4B s1, I4B s2)
{ // 僌儕僢僪偺僙儖嬮宍偺慄庬
  return RST((ic == 0)? s2: 0, (ir == 0)? s2: 0, (ic < gr->nc-1)? s1: s2, (ir < gr->nr-1)? s1: s2);
}

I4B  LOCALF GridRST(rGRID gr, I4B ir, I4B ic, I4B rst)
{ // 僌儕僢僪偺僙儖嬮宍偺慄庬
  switch (rst) {
  case RST_I_R: rst = RST2(gr, ir, ic, lstI, lstR); break;
  case RST_I_M: rst = RST2(gr, ir, ic, lstI, lstM); break;
  case RST_I_B: rst = RST2(gr, ir, ic, lstI, lstB); break;
  case RST_R_M: rst = RST2(gr, ir, ic, lstR, lstM); break;
  case RST_R_B: rst = RST2(gr, ir, ic, lstR, lstB); break;
  case RST_R_X: rst = RST2(gr, ir, ic, lstR, lstX); break;
  }
  return rst;
}

void WINAPI DrawGridCell(HCVS cv, rGRID gr, I4B ir, I4B ic, I4B rst)
{ // 僌儕僢僪偺僙儖嬮宍偺昤夋
  CELL cel; GridCell(&cel, gr, ir, ic); DrawCell(cv, &cel, GridRST(gr, ir, ic, rst));
}

void WINAPI GridCellText(HCVS cv, rGRID gr, I4B ir, I4B ic, I4B rst, rSTR st, I4B fmt)
{ // 僌儕僢僪偺僙儖嬮宍偲暥帤楍偺昤夋
  CELL cel; GridCell(&cel, gr, ir, ic); DrawCell(cv, &cel, GridRST(gr, ir, ic, rst)); CellText(cv, &cel, st, fmt);
}

void WINAPI SetStamp0(pSTMP ps, F8B dc, rSTR st)
{ // 報塭偺愝掕
  ps->sty = 0; ps->st1 = st; ps->st2 = NULL; ps->st3 = NULL; ps->dc = dc;
}

void WINAPI SetStamp1(pSTMP ps, F8B dc, rSTR st)
{ // 報塭偺愝掕
  ps->sty = 1; ps->st1 = st; ps->st2 = NULL; ps->st3 = NULL; ps->dc = dc;
}

void WINAPI SetStamp2(pSTMP ps, F8B dc, rSTR st1, rSTR st2)
{ // 報塭偺愝掕
  ps->sty = 2; ps->st1 = st1; ps->st2 = st2; ps->st3 = NULL; ps->dc = dc;
}

void WINAPI SetStamp3(pSTMP ps, F8B dc, rSTR st1, rSTR st2, rSTR st3)
{ // 報塭偺愝掕
  ps->sty = 3; ps->st1 = st1; ps->st2 = st2; ps->st3 = st3; ps->dc = dc;
}

void LOCALF stmp0(HCVS cv, F8B xc, F8B yc, F8B rc, rSTR st)
{ // 報塭偺昤夋(廲彂偒)
  RECT rct;
  CELL cel;

  DrawCirc(cv, xc, yc, rc, 0.0, 0.0);
  SetCell(&cel, xc - 0.5 * rc, yc - rc, xc + 0.5 * rc, yc + rc);
  vtext(cv, c2dRect(&rct, cv, &cel), st, VT_MID);
}

void LOCALF stmp1(HCVS cv, F8B xc, F8B yc, F8B rc, rSTR st)
{ // 報塭偺昤夋(墶彂偒)
  RECT rct;
  CELL cel;

  DrawCirc(cv, xc, yc, rc, 0.0, 0.0);
  SetCell(&cel, xc - rc, yc - 0.5 * rc, xc + rc, yc + 0.5 * rc);
  atext(cv, c2dRect(&rct, cv, &cel), st, DT2DT(DT_CEN));
}

void LOCALF stmp2(HCVS cv, F8B xc, F8B yc, F8B rc, rSTR st1, rSTR st2)
{ // 報塭偺昤夋(擇抜)
  RECT rct;
  CELL cel;

  DrawCirc(cv, xc, yc, rc, 0.0, 0.0);
  DrawLine(cv, xc - rc, yc, xc + rc, yc);
  SetCell(&cel, xc - 0.9 * rc, yc - 0.75 * rc, xc + 0.9 * rc, yc);
  atext(cv, c2dRect(&rct, cv, &cel), st1, DT2DT(DT_CEN));
  SetCell(&cel, xc - 0.9 * rc, yc, xc + 0.9 * rc, yc + 0.75 * rc);
  atext(cv, c2dRect(&rct, cv, &cel), st2, DT2DT(DT_CEN));
}

void LOCALF stmp3(HCVS cv, F8B xc, F8B yc, F8B rc, rSTR st1, rSTR st2, rSTR st3)
{ // 報塭偺昤夋(嶰抜)
  RECT rct;
  CELL cel;

  DrawCirc(cv, xc, yc, rc, 0.0, 0.0);
  DrawLine(cv, xc - 0.95 * rc, yc - 0.3 * rc, xc + 0.95 * rc, yc - 0.3 * rc);
  DrawLine(cv, xc - 0.95 * rc, yc + 0.3 * rc, xc + 0.95 * rc, yc + 0.3 * rc);
  SetCell(&cel, xc - 0.8 * rc, yc - 0.9 * rc, xc + 0.8 * rc, yc - 0.3 * rc);
  atext(cv, c2dRect(&rct, cv, &cel), st1, DT2DT(DT_CEN));
  SetCell(&cel, xc - 0.95 * rc, yc - 0.3 * rc, xc + 0.95 * rc, yc + 0.3 * rc);
  atext(cv, c2dRect(&rct, cv, &cel), st2, DT2DT(DT_CEN));
  SetCell(&cel, xc - 0.8 * rc, yc + 0.3 * rc, xc + 0.85 * rc, yc + 0.9 * rc);
  atext(cv, c2dRect(&rct, cv, &cel), st3, DT2DT(DT_CEN));
}

void WINAPI CellStampD(HCVS cv, rRECT pr, rSTMP ps)
{ // 報塭偺昤夋
  CELL cel; CellStamp(cv, d2cCell(&cel, cv, pr), ps);
}

void WINAPI CellStamp(HCVS cv, rCELL pc, rSTMP ps)
{ // 報塭偺昤夋
  I4B tcw, tch, tcd, tst, tco, lst, lco;
  HFNT hfnt;
  F8B xc, yc, rc;
  I1B tfa[32];

  if (!hDC(cv)) return;
  xc = (pc->x1 + pc->x2) / 2;
  yc = (pc->y1 + pc->y2) / 2;
  rc = ps->dc / 2;
  strcpyx(tfa, ((pCVSE)cv)->tfa, sizeof(tfa) - 1);
  tcw = ((pCVSE)cv)->tcw;
  tch = ((pCVSE)cv)->tch;
  tcd = ((pCVSE)cv)->tcd; ((pCVSE)cv)->tcd = 0;
  tst = ((pCVSE)cv)->tst;
  tco = ((pCVSE)cv)->tco;
  hfnt = GetCurrentObject(hDC(cv), OBJ_FONT);
  lst = SetLineStyle(cv, 0x06);
  lco = SetLineColor(cv, tco);
  switch (ps->sty) {
  case 0: SetTextFont(cv, strconc("@", tfa), rc, TFF_BLD|TFF_VRT, tco); break;
  case 1: SetTextFont(cv, NULL, rc, TFF_BLD, tco); break;
  case 2: SetTextFont(cv, NULL, 0.54 * rc, TFF_BLD, tco); break;
  case 3: SetTextFont(cv, NULL, 0.40 * rc, TFF_BLD, tco); break;
  }
  switch (ps->sty) {
  case 0: stmp0(cv, xc, yc, rc, ps->st1); break;
  case 1: stmp1(cv, xc, yc, rc, ps->st1); break;
  case 2: stmp2(cv, xc, yc, rc, ps->st1, ps->st2); break;
  case 3: stmp3(cv, xc, yc, rc, ps->st1, ps->st2, ps->st3); break;
  }
  SetLineColor(cv, lco);
  SetLineStyle(cv, lst);
  SetTextFont(cv, tfa, tch * 0.001, tst, tco);
  DeleteObject(SelectObject(hDC(cv), hfnt)); ((pCVSE)cv)->tcw = tcw;
  SetTextCharacterExtra(hDC(cv), iW(cv, tcd * 0.001)); ((pCVSE)cv)->tcd = tcd;
}

void WINAPI CellImageD(HCVS cv, pRECT pc, HDIB bm, I4B fmt)
{ // 夋憸偺揬傝晅偗
  RECT rct = *pc;

  if (!hDC(cv) || !bm) return;
  InflateRect(&rct, -CellMarginHD(cv), -CellMarginVD(cv)); if (IsRectEmpty(&rct)) return;
  DrawDIB(hDC(cv), &rct, bm, fmt);
  if (fmt & DT_CAL) { *pc = rct;}
}

void WINAPI CellImage(HCVS cv, pCELL pc, HDIB bm, I4B fmt)
{ // 夋憸偺揬傝晅偗
  RECT rct; CellImageD(cv, c2dRect(&rct, cv, pc), bm, fmt); if (fmt & DT_CAL) { d2cCell(pc, cv, &rct);}
}

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

iANY WINAPI ParentNotify(HWND hwnd, I4B nc, iANY lpa)
{ // 恊僂傿儞僪僂偵捠抦
  return SendMessage(GetParent(hwnd), WM_COMMAND, MKU4B(GetDlgCtrlID(hwnd), nc), lpa);
}

rSTR WINAPI WindowText(HWND hwnd)
{ // 僂傿儞僪僂僥僉僗僩
  I1B bf[LBUF]; GetWindowText(hwnd, bf, sizeof(bf)); return strcpys(talloc(strlen(bf) + 1), bf);
}

rSTR WINAPI ClassName(HWND hwnd)
{ // 僂傿儞僪僂僋儔僗柤
  I1B bf[LBUF]; GetClassName(hwnd, bf, sizeof(bf)); return strcpys(talloc(strlen(bf) + 1), bf);
}

void WINAPI CenterWindow(HWND hwnd, HWND hown)
{ // 僂傿儞僪僂傪拞墰偵抲偔
  I4B x1, y1, w1, h1, w2, h2;
  RECT rct;

  GetWindowRect(hown, &rct);
  x1 = rct.lft;
  y1 = rct.top;
  w1 = rct.rgt - rct.lft;
  h1 = rct.btm - rct.top;
  GetWindowRect(hwnd, &rct);
  w2 = rct.rgt - rct.lft;
  h2 = rct.btm - rct.top;
  MoveWindow(hwnd, x1 + (w1 - w2) / 2, y1 + (h1 - h2) / 2, w2, h2, FALSE);
}

void WINAPI AdjustWindow(HWND hwnd, rRECT pr)
{ // 僋儔僀傾儞僩椞堟偺僒僀僘偱僂傿儞僪僂偺僒僀僘傪愝掕
  I4B mnu, sty;
  RECT rct = *pr;

  sty = WindowStyle(hwnd);
  mnu = (!(sty & WS_CHILD) && !!GetMenu(hwnd));
  AdjustWindowRectEx(&rct, sty, mnu, WindowExStyle(hwnd));
  if (sty & WS_VSCROLL) { rct.rgt += GetSystemMetrics(SM_CXVSCROLL);}
  if (sty & WS_HSCROLL) { rct.btm += GetSystemMetrics(SM_CYHSCROLL);}
  ResizeWindow(hwnd, rct.rgt - rct.lft, rct.btm - rct.top);
}

I4B  WINAPI SetHScrollBar(HWND hwnd, I4B min, I4B max, I4B psz, I4B pos)
{ // 悈暯僗僋儘乕儖僶乕偺愝掕
  static SCROLLINFO scr = { sizeof(SCROLLINFO), SIF_ALL|SIF_DISABLENOSCROLL, };

  if (!(WindowStyle(hwnd) & WS_HSCROLL)) return 0;
  scr.nMin = min; scr.nMax = max; scr.nPage = psz; scr.nPos = pos;
  return SetScrollInfo(hwnd, SB_HORZ, &scr, TRUE);
}

I4B  WINAPI SetVScrollBar(HWND hwnd, I4B min, I4B max, I4B psz, I4B pos)
{ // 悅捈僗僋儘乕儖僶乕偺愝掕
  static SCROLLINFO scr = { sizeof(SCROLLINFO), SIF_ALL|SIF_DISABLENOSCROLL, };

  if (!(WindowStyle(hwnd) & WS_VSCROLL)) return 0;
  scr.nMin = min; scr.nMax = max; scr.nPage = psz; scr.nPos = pos;
  return SetScrollInfo(hwnd, SB_VERT, &scr, TRUE);
}

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

#define  NPOP  32

BOOL LOCALF insmenuitems(HMENU hmnu, I4B pos, rMNUS ms)
{ // 儊僯儏乕偺嶌惉
  I4B n, po[NPOP];
  rMNUI mi, me;
  HMENU hm[NPOP];
  rSTR tx[NPOP];
  static MENUITEMINFO mni = { sizeof(MENUITEMINFO), };

  n = 0;
  hm[0] = hmnu;
  po[0] = pos;
  for (mi = ms->mi, me = mi + ms->ni; mi < me; mi++) {
    if (mi->flg & MF_POPUP) {
      n++; if (n >= NPOP) { return (BOOL)ierr(E_CAP);}
      po[n] = 0;
      hm[n] = CreatePopupMenu();
      tx[n] = mi->txt? mi->txt: "";
    } else {
      if (mi->idm) {
        mni.fMask = MIIM_STATE|MIIM_ID|MIIM_STRING;
        mni.fState = (mi->flg & mfG)? MFS_GRAYED: (mi->flg & mfC)? MFS_CHECKED: MFS_ENABLED;
        mni.wID = mi->idm;
        mni.dwTypeData = (LPTSTR)(mi->txt? mi->txt: "");
        mni.cch = strlen(mni.dwTypeData);
        if (!!(mni.hbmpItem = MenuItemDDB(mi->idm))) { mni.fMask |= MIIM_BITMAP;}
        InsertMenuItem(hm[n], po[n]++, TRUE, &mni);
      } else {
        mni.fMask = MIIM_FTYPE;
        mni.fType = MFT_SEPARATOR;
        InsertMenuItem(hm[n], po[n]++, TRUE, &mni);
      }
      if (mi->flg & MF_END) {
        if (n <= 0) { return (BOOL)ierr(E_DAT);}
        mni.fMask = MIIM_SUBMENU|MIIM_STRING;
        mni.hSubMenu = hm[n];
        mni.dwTypeData = (LPTSTR)tx[n];
        mni.cch = strlen(mni.dwTypeData);
        InsertMenuItem(hm[n-1], po[n-1]++, TRUE, &mni);
        n--;
      }
    }
  }
  if (n != 0) { return (BOOL)ierr(E_DAT);}
  return TRUE;
}

HMENU WINAPI CreateMenuBar(rMNUS ms)
{ // 儊僯儏乕偺嶌惉
  HMENU hmnu; return insmenuitems(hmnu = CreateMenu(), 0, ms)? hmnu: NULL;
}

BOOL WINAPI ChangeMenuBar(HMENU hmnu, I4B pos, rMNUS ms)
{ // 儊僯儏乕偺曄峏
  if (!DeleteMenu(hmnu, pos, MF_BYPOSITION)) return FALSE;
  if (!insmenuitems(hmnu, pos, ms)) return FALSE;
  return TRUE;
}

void WINAPI MenuSlice(pI4B p1, pI4B p2, rMNUS ms, I4B pos)
{ // 儊僯儏乕偺斖埻
  I4B c, i, i1, i2, n;

  i1 = 0; i2 = ms->ni;
  for (c = n = i = 0; i < ms->ni; i++) {
    if (ms->mi[i].flg & mfP) {
      if (c == pos) { i1 = i;} else if (c == pos + 1) { i2 = i;}
      if (n == 0) { c++;}
      n++;
    }
    if (ms->mi[i].flg & mfE) {
      n--;
    }
  }
  *p1 = i1; *p2 = i2;
}

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

iANY LOCALF TIP_paint(HWND hwnd)
{ // 僣乕儖僠僢僾偺昤夋
  I4B bkm, tco;
  HDC hdc;
  HFNT hfnt;
  RECT rct;
  PAINTSTRUCT ps;

  GetClientRect(hwnd, &rct);
  hdc = BeginPaint(hwnd, &ps);
  bkm = SetBkMode(hdc, TRANSPARENT);
  FillRect(hdc, &rct, AppBrush(CID_INF));
  tco = SetTextColor(hdc, AppColor(CID_BLK));
  hfnt = SelectObject(hdc, AppFont(FID_SYS));
  OffsetRect(&rct, 1, 1);
  DrawText(hdc, WindowText(hwnd), -1, &rct, DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  SelectObject(hdc, hfnt);
  SetTextColor(hdc, tco);
  SetBkMode(hdc, bkm);
  EndPaint(hwnd, &ps);
  return 0;
}

iANY LOCALF TIP_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僣乕儖僠僢僾偺僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_ERASEBKGND:
    return 1;
  case WM_PAINT:
    return TIP_paint(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLTIPClass(HINSTANCE hinst)
{ // 僣乕儖僠僢僾僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = 0;
  wcx.lpfnWndProc   = TIP_WndProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 0;
  wcx.hInstance     = hinst;
  wcx.hIcon         = NULL;
  wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wcx.hbrBackground = (HBRS)(COLOR_WINDOW + 1);
  wcx.lpszMenuName  = NULL;
  wcx.lpszClassName = "BOLTIP";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

HWND WINAPI CreateToolTip(HWND hwnd, rTIPI pi)
{ // 僣乕儖僠僢僾偺嶌惉
  HWND htip;
  HDC hdc;
  HFNT hfnt;
  SIZE siz;

  hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  hfnt = SelectObject(hdc, AppFont(FID_SYS));
  GetTextExtentPoint32(hdc, pi->txt, strlen(pi->txt), &siz);
  SelectObject(hdc, hfnt);
  DeleteDC(hdc);
  htip = CreateWindowEx(
    0,
    "BOLTIP",
    pi->txt,
    WS_POPUP|WS_BORDER,
    pi->x, pi->y,
    siz.cx + 7, siz.cy + 7,
    hwnd,
    NULL,
    WindowInstance(hwnd),
    NULL
  );
  ShowWindow(htip, SW_SHOWNA);
  return htip;
}

#define  IDHOVER  101

  // 僣乕儖僶乕忣曬
typedef struct {
  pTOBI pi;
  I4B   ni;
  I4B   wh;
  I4B   ht;
  TIPI  tip;
  HWND  htip;
} TOBE;
typedef TOBE *pTOBE;

static WNDPROC OrgBtnProc;

iANY LOCALF AltBtnProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僆乕僫乕昤夋儃僞儞僂傿儞僪僂僾儘僔乕僕儍
  HWND hown;
  POINT pnt;

  switch (umsg) {
  case WM_MOUSEMOVE:
    pnt.x = LOU2B(lpa); pnt.y = HIU2B(lpa);
    ClientToScreen(hwnd, &pnt);
    ScreenToClient(hown = GetParent(hwnd), &pnt);
    SendMessage(hown, umsg, wpa, MKU4B(pnt.x, pnt.y));
    break;
  }
  return CallWindowProc(OrgBtnProc, hwnd, umsg, wpa, lpa);
}

void LOCALF ctlpos(pI4B px, pI4B py, pI4B pw, pI4B ph, pTOBE te, I4B i)
{ // 僐儞僩儘乕儖偺埵抲
  I4B x, j, w, h;
  pTOBI pi, pe;

  x = TOBMGNW;
  for (pi = te->pi, pe = pi + i + 1; pi < pe; pi++) {
    j = 0;
    switch (LOU2B(pi->flg)) {
    case TOBI_SPACE:
      w = (I2B)HIU2B(pi->flg); h = 0; break;
    case TOBI_VLINE:
      x += TOBSEPW; w = TOBSEPW; h = te->wh - 4; break;
    case TOBI_BUTTON:
      x += TOBSEPW; w = TOBBTNW; h = TOBBTNH; break;
    case TOBI_SLEFT:   j = TOBMGNW; goto _10;
    case TOBI_SCENTER: goto _10;
    case TOBI_SRIGHT:  j = -TOBMGNW; _10:
      x += TOBSEPW; w = HIU2B(pi->flg); h = TOBSTAH; break;
    }
    *px = x + j; x += w;
  }
  *py = (te->wh - h) / 2 + 1; *pw = w; *ph = h;
}

void LOCALF createctls(HWND hwnd, pTOBE te)
{ // 怴婯嶌惉
  I4B x, y, w, h, sty;
  rSTR cls;
  pTOBI pi, pe;
  HWND hctl;

  for (pi = te->pi, pe = pi + te->ni; pi < pe; pi++) {
    switch (LOU2B(pi->flg)) {
    case TOBI_BUTTON:  cls = "button"; sty = BS_OWNERDRAW;             goto _10;
    case TOBI_SLEFT:   cls = "static"; sty = SS_CENTERIMAGE|SS_LEFT;   goto _10;
    case TOBI_SCENTER: cls = "static"; sty = SS_CENTERIMAGE|SS_CENTER; goto _10;
    case TOBI_SRIGHT:  cls = "static"; sty = SS_CENTERIMAGE|SS_RIGHT;  _10:
      ctlpos(&x, &y, &w, &h, te, pi - te->pi); break;
    default:
      continue;
    }
    hctl = CreateWindowEx(
      0,
      cls,
      pi->txt,
      WS_CHILD|WS_VISIBLE|sty,
      x, y,
      w, h,
      hwnd,
      (HMENU)pi->idm,
      WindowInstance(hwnd),
      NULL
    );
    switch (LOU2B(pi->flg)) {
    case TOBI_BUTTON:
      OrgBtnProc = SubclassWindow(hctl, AltBtnProc); break;
    }
    SendMessage(hctl, WM_SETFONT, (uANY)AppFont(FID_SYS), FALSE);
  }
}

void LOCALF drawitem(HWND hwnd, I4B id, U4B typ, U4B sta)
{ // 僆乕僫乕昤夋
  HWND hctl;
  DRAWITEMSTRUCT dri;

  hctl = GetDlgItem(hwnd, id);
  dri.CtlType = typ;
  dri.CtlID = id;
  dri.itemID = 0;
  dri.itemAction = ODA_DRAWENTIRE;
  dri.itemState = IsWindowEnabled(hctl)? sta: ODS_DISABLED;
  dri.hwndItem = hctl;
  dri.hDC = GetDC(hctl);
  GetClientRect(hctl, &dri.rcItem);
  dri.itemData = 0;
  SendMessage(hwnd, WM_DRAWITEM, id, (uANY)&dri);
  ReleaseDC(hctl, dri.hDC);
}

iANY LOCALF TOB_create(HWND hwnd, iANY lpa)
{ // 僣乕儖僶乕僂傿儞僪僂奐巒張棟
  pTOBS ts = (pTOBS)((LPCREATESTRUCT)lpa)->lpCreateParams;
  pTOBE te;

  te = halloc(sizeof(TOBE) + ts->ni * sizeof(TOBI), TRUE); if (!te) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)te);
  te->pi = (pANY)((pBIN)te + sizeof(TOBE));
  te->ni = ts->ni;
  te->wh = TOBWINH;
  memcpy(te->pi, ts->pi, ts->ni * sizeof(TOBI));
  createctls(hwnd, te);
  return 0;
}

iANY LOCALF TOB_resetitems(HWND hwnd, pTOBS ts, BOOL rd)
{ // 嵞愝掕
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0), tx;
  pTOBI pi, pe;

  tx = halloc(sizeof(TOBE) + ts->ni * sizeof(TOBI), TRUE); if (!tx) { ierr(E_MEM); return -1;}
  *(pTOBE)tx = *(pTOBE)te;
  if (IsWindow(te->htip)) { DestroyWindow(te->htip);}
  for (pi = te->pi, pe = pi + te->ni; pi < pe; pi++) {
    switch (LOU2B(pi->flg)) {
    case TOBI_BUTTON:
    case TOBI_SLEFT:
    case TOBI_SCENTER:
    case TOBI_SRIGHT:
      DestroyWindow(GetDlgItem(hwnd, pi->idm)); break;
    default:
      continue;
    }
  }
  hfree(te);
  SetWindowLong(hwnd, 0, (iANY)tx);
  tx->pi = (pANY)((pBIN)tx + sizeof(TOBE));
  tx->ni = ts->ni;
  memcpy(tx->pi, ts->pi, ts->ni * sizeof(TOBI));
  createctls(hwnd, tx);
  if (rd) { RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);}
  return 0;
}

iANY LOCALF TOB_size(HWND hwnd, uANY wpa, iANY lpa)
{ // 僒僀僘愝掕
  MoveWindow(hwnd, 0, 0, LOU2B(lpa), ((pTOBE)GetWindowLong(hwnd, 0))->wh, TRUE);
  return 0;
}

iANY LOCALF TOB_paint(HWND hwnd)
{ // 昤夋
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0);
  I4B x, y, w, h;
  pTOBI pi, pe;
  HDC hdc;
  RECT rct;
  PAINTSTRUCT ps;

  hdc = BeginPaint(hwnd, &ps);
  for (pi = te->pi, pe = pi + te->ni; pi < pe; pi++) {
    switch (LOU2B(pi->flg)) {
    case TOBI_VLINE:
      ctlpos(&x, &y, &w, &h, te, pi - te->pi);
      SetRect(&rct, x + w / 2 - 1, y, x + w, y + h);
      DrawEdge(hdc, &rct, EDGE_ETCHED, BF_LEFT);
      break;
    }
  }
  EndPaint(hwnd, &ps);
  return 0;
}

iANY LOCALF TOB_drawitem(HWND hwnd, I4B id, LPDRAWITEMSTRUCT lp)
{ // 僆乕僫乕昤夋
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0);
  HBMP hbmp;
  RECT rct;

  switch (lp->CtlType) {
  case ODT_BUTTON:
    rct = lp->rcItem;
    FillRect(lp->hDC, &rct, AppBrush(CID_3DF));
    if (lp->itemState & ODS_HOTLIGHT) {
      DrawEdge(lp->hDC, &rct, BDR_RAISEDOUTER, BF_RECT);
    } else if (lp->itemState & ODS_SELECTED) {
      DrawEdge(lp->hDC, &rct, BDR_SUNKENOUTER, BF_RECT);
      OffsetRect(&rct, 1, 1);
      te->ht = 0;
    }
    if (!!(hbmp = MenuItemDDB(id))) {
      if (lp->itemState & ODS_DISABLED) {
        DrawDDB(lp->hDC, &rct, hbmp, DT_GRY|DT_CEN);
      } else {
        DrawDDB(lp->hDC, &rct, hbmp, DT_CEN);
      }
    }
    return TRUE;
  }
  return FALSE;
}

iANY LOCALF TOB_mousemove(HWND hwnd, uANY wpa, iANY lpa)
{ // 儅僂僗堏摦
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0);
  I4B x, y, w, h, ht = 0;
  pTOBI pi, pe;
  POINT pnt;

  pnt.x = LOU2B(lpa); pnt.y = HIU2B(lpa);
  for (pi = te->pi, pe = pi + te->ni; pi < pe; pi++) {
    ctlpos(&x, &y, &w, &h, te, pi - te->pi);
    if (pnt.x >= x && pnt.x < x + w && pnt.y >= y && pnt.y < y + h) {
      ht = MKU4B(LOU2B(pi->flg), pi - te->pi); break;
    }
  }
  if (ht != te->ht) {
    if (LOU2B(te->ht) == TOBI_BUTTON) {
      pi = &te->pi[HIU2B(te->ht)];
      drawitem(hwnd, pi->idm, ODT_BUTTON, 0);
    }
    te->tip.txt = NULL;
    if (LOU2B(ht) == TOBI_BUTTON) {
      pi = &te->pi[HIU2B(ht)];
      drawitem(hwnd, pi->idm, ODT_BUTTON, ODS_HOTLIGHT);
      te->tip.txt = stostr(WindowText(GetDlgItem(hwnd, pi->idm)));
    }
    te->ht = ht;
  }
  ClientToScreen(hwnd, &pnt);
  pnt.y += GetSystemMetrics(SM_CYCURSOR) / 2 + 2;
  if (te->tip.x != pnt.x || te->tip.y != pnt.y) {
    te->tip.x = pnt.x;
    te->tip.y = pnt.y;
    SetTimer(hwnd, IDHOVER, 500, NULL);
  }
  return 0;
}

iANY LOCALF TOB_timer(HWND hwnd, uANY wpa)
{ // 僞僀儅乕
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0);

  if (wpa == IDHOVER) {
    KillTimer(hwnd, IDHOVER);
    if (IsWindow(te->htip)) { DestroyWindow(te->htip);}
    if (te->tip.txt) { te->htip = CreateToolTip(hwnd, &te->tip);}
  }
  return 0;
}

iANY LOCALF TOB_command(HWND hwnd, uANY wpa, iANY lpa)
{ // 僐儅儞僪
  pTOBE te = (pTOBE)GetWindowLong(hwnd, 0);
  HWND hown;

  if (IsWindow(te->htip)) { DestroyWindow(te->htip);}
  te->tip.txt = NULL;
  SetFocus(hown = GetParent(hwnd));
  SendMessage(hown, WM_COMMAND, wpa, lpa);
  return 0;
}

iANY LOCALF TOB_destroy(HWND hwnd)
{ // 僣乕儖僶乕僂傿儞僪僂廔椆張棟
  hfree((pTOBE)GetWindowLong(hwnd, 0));
  return 0;
}

iANY LOCALF TOB_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僣乕儖僶乕偺僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return TOB_create(hwnd, lpa);
  case TOBM_GETNITEMS:
    return ((pTOBE)GetWindowLong(hwnd, 0))->ni;
  case TOBM_GETITEMINFO:
    return (iANY)&((pTOBE)GetWindowLong(hwnd, 0))->pi[wpa];
  case TOBM_RESETITEMS:
    return TOB_resetitems(hwnd, (pTOBS)wpa, lpa);
  case WM_SIZE:
    return TOB_size(hwnd, wpa, lpa);
  case WM_PAINT:
    return TOB_paint(hwnd);
  case WM_DRAWITEM:
    return TOB_drawitem(hwnd, wpa, (LPDRAWITEMSTRUCT)lpa);
  case WM_MOUSEMOVE:
    return TOB_mousemove(hwnd, wpa, lpa);
  case WM_TIMER:
    return TOB_timer(hwnd, wpa);
  case WM_COMMAND:
    return TOB_command(hwnd, wpa, lpa);
  case WM_DESTROY:
    return TOB_destroy(hwnd);
  }
  return DefWindowProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLTOBClass(HINSTANCE hinst)
{ // 僣乕儖僶乕僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = 0;
  wcx.lpfnWndProc   = TOB_WndProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 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 = "BOLTOB";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

HWND WINAPI CreateToolBar(HWND hwnd, I4B id, rTOBS ts)
{ // 僣乕儖僶乕偺嶌惉
  return CreateWindowEx(
    0,
    "BOLTOB",
    "",
    WS_CHILD|WS_VISIBLE,
    0, 0,
    0, 0,
    hwnd,
    (HMENU)id,
    WindowInstance(hwnd),
    (pANY)ts
  );
}

iANY LOCALF STB_create(HWND hwnd, iANY lpa)
{ // 僗僥乕僞僗僶乕僂傿儞僪僂奐巒張棟
  pTOBS ss = (pTOBS)((LPCREATESTRUCT)lpa)->lpCreateParams;
  pTOBE te;

  te = halloc(sizeof(TOBE) + ss->ni * sizeof(TOBI), TRUE); if (!te) { ierr(E_MEM); return -1;}
  SetWindowLong(hwnd, 0, (iANY)te);
  te->pi = (pANY)((pBIN)te + sizeof(TOBE));
  te->ni = ss->ni;
  te->wh = STBWINH;
  memcpy(te->pi, ss->pi, ss->ni * sizeof(TOBI));
  createctls(hwnd, te);
  return 0;
}

iANY LOCALF STB_size(HWND hwnd, uANY wpa, iANY lpa)
{ // 僒僀僘愝掕
  MoveWindow(hwnd, 0, HIU2B(lpa) - ((pTOBE)GetWindowLong(hwnd, 0))->wh, LOU2B(lpa), HIU2B(lpa), TRUE);
  return 0;
}

iANY LOCALF STB_WndProc(HWND hwnd, U4B umsg, uANY wpa, iANY lpa)
{ // 僗僥乕僞僗僶乕偺僂傿儞僪僂僾儘僔乕僕儍
  switch (umsg) {
  case WM_CREATE:
    return STB_create(hwnd, lpa);
  case WM_SIZE:
    return STB_size(hwnd, wpa, lpa);
  }
  return TOB_WndProc(hwnd, umsg, wpa, lpa);
}

ATOM LOCALF RegisterBOLSTBClass(HINSTANCE hinst)
{ // 僗僥乕僞僗僶乕僂傿儞僪僂僋儔僗偺搊榐
  WNDCLASSEX wcx;

  wcx.cbSize        = sizeof(WNDCLASSEX);
  wcx.style         = 0;
  wcx.lpfnWndProc   = STB_WndProc;
  wcx.cbClsExtra    = 0;
  wcx.cbWndExtra    = 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 = "BOLSTB";
  wcx.hIconSm       = wcx.hIcon;
  return RegisterClassEx(&wcx);
}

HWND WINAPI CreateStatBar(HWND hwnd, I4B id, rTOBS ss)
{ // 僗僥乕僞僗僶乕偺嶌惉
  return CreateWindowEx(
    0,
    "BOLSTB",
    "",
    WS_CHILD|WS_VISIBLE,
    0, 0,
    0, 0,
    hwnd,
    (HMENU)id,
    WindowInstance(hwnd),
    (pANY)ss
  );
}

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

//#define  BST_UNCHECKED       0x0000
//#define  BST_CHECKED         0x0001

void WINAPI SetBFLG(HWND hdlg, I4B id, BOOL va)
{ // 僠僃僢僋儃僢僋僗忬懺愝掕
  CheckDlgButton(hdlg, id, va? BST_CHECKED: BST_UNCHECKED);
}

BOOL WINAPI GetBFLG(HWND hdlg, I4B id)
{ // 僠僃僢僋儃僢僋僗忬懺庢摼
  return IsDlgButtonChecked(hdlg, id) == BST_CHECKED;
}

void WINAPI SetEINT(HWND hdlg, I4B id, I4B va)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞愝掕(惍悢)
  SetESTR(hdlg, id, format("%d", va));
}

I4B  WINAPI GetEINT(HWND hdlg, I4B id)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞庢摼(惍悢)
  I1B bf[256];

  GetESTR(hdlg, id, bf, sizeof(bf) - 1);
  return cztoi(bf);
}

void WINAPI SetEDBL(HWND hdlg, I4B id, F8B va)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞愝掕(幚悢)
  SetESTR(hdlg, id, format("%.15G", va));
}

F8B  WINAPI GetEDBL(HWND hdlg, I4B id)
{ // 僄僨傿僢僩僐儞僩儘乕儖僨乕僞庢摼(幚悢)
  I1B bf[256];

  GetESTR(hdlg, id, bf, sizeof(bf) - 1);
  return cztof(bf);
}

void WINAPI SetLSEL(HWND hdlg, I4B id, I4B ir, rENMS ls)
{ // 儕僗僩儃僢僋僗僨乕僞愝掕
  I4B i;

  SendDlgItemMessage(hdlg, id, WM_SETREDRAW, FALSE, 0);
  SendDlgItemMessage(hdlg, id, LB_RESETCONTENT, 0, 0);
  for (i = 0; i < ls->ni; i++) {
    SendDlgItemMessage(hdlg, id, LB_ADDSTRING, 0, (uANY)ls->ps[i]);
  }
  SendDlgItemMessage(hdlg, id, LB_SETCURSEL, ir, 0);
  SendDlgItemMessage(hdlg, id, WM_SETREDRAW, TRUE, 0);
  InvalidateRect(GetDlgItem(hdlg, id), NULL, TRUE);
}

I4B  WINAPI GetLSEL(HWND hdlg, I4B id)
{ // 儕僗僩儃僢僋僗僨乕僞庢摼
  I4B i;

  i = SendDlgItemMessage(hdlg, id, LB_GETCURSEL, 0, 0);
  if (i < 0) { i = 0;}
  return i;
}

void WINAPI SetCSEL(HWND hdlg, I4B id, I4B ir, rENMS ls)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞愝掕
  I4B i;

  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  for (i = 0; i < ls->ni; i++) {
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (uANY)ls->ps[i]);
  }
  SendDlgItemMessage(hdlg, id, CB_SETCURSEL, ir, 0);
}

I4B  WINAPI GetCSEL(HWND hdlg, I4B id)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞庢摼
  I4B i;

  i = SendDlgItemMessage(hdlg, id, CB_GETCURSEL, 0, 0);
  if (i < 0) { i = 0;}
  return i;
}

void WINAPI SetCCOD(HWND hdlg, I4B id, I4B va, rCODS ls)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞愝掕(柤慜/抣儁傾巊梡)
  I4B i, i0 = 0;

  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  for (i = 0; i < ls->ni; i++) {
    if (ls->pv[i].va == va) { i0 = i;}
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (uANY)ls->pv[i].st);
  }
  SendDlgItemMessage(hdlg, id, CB_SETCURSEL, i0, 0);
}

I4B  WINAPI GetCCOD(HWND hdlg, I4B id, rCODS ls)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞庢摼(柤慜/抣儁傾巊梡)
  I4B i;

  i = SendDlgItemMessage(hdlg, id, CB_GETCURSEL, 0, 0);
  if (i < 0) { i = 0;}
  return ls->pv[i].va;
}

void WINAPI SetCSTR(HWND hdlg, I4B id, rSTR st, rENMS ls)
{ // 僐儞儃儃僢僋僗僨乕僞愝掕
  I4B i;

  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  for (i = 0; i < ls->ni; i++) {
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (uANY)ls->ps[i]);
  }
  SetESTR(hdlg, id, st);
}

void WINAPI SetDLGI(pDLGI di, rSTR cls, I4B sty, U2B x, U2B y, U2B w, U2B h, I4B id, rSTR txt)
{ // 僟僀傾儘僌儃僢僋僗崁栚偺愝掕
  di->cls = cls; di->sty = sty; di->x = x; di->y = y; di->w = w; di->h = h; di->id = id; di->txt = txt;
}

pANY LOCALF mkdlgtmp(rDLGS ds, rSTR cls, U4B sty)
{ // 僟僀傾儘僌儃僢僋僗僥儞僾儗乕僩偺嶌惉
  I4B n, f1, f2, f3, ni = ds->ni, sz, ptsz = TMPPTSZ;
  rDLGI di, di0 = ds->di;
  pANY lp, lp0;
  rSTR tx, face = TMPFACE;

  f1 = (cls && cls[0] != '\0');
  f2 = (ds->tit && ds->tit[0] != '\0');
  f3 = (face[0] != '\0');
  sz = 20;
  if (f1) {
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, cls, -1, NULL, 0);
    sz += 2 * n;
  } else {
    sz += 2;
  }
  if (f2) {
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, ds->tit, -1, NULL, 0);
    sz += 2 * n;
  } else {
    sz += 2;
  }
  if (f3) {
    sz += 2;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, face, -1, NULL, 0);
    sz += 2 * n;
  }
  if (sz & 2) { sz += 2;}
  for (di = di0; di < di0 + ni; di++) {
    tx = di->txt; if (!tx) { tx = "";}
    sz += 18;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, di->cls, -1, NULL, 0);
    sz += 2 * n;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, tx, -1, NULL, 0);
    sz += 2 * n;
    sz += 2;
    if (sz & 2) { sz += 2;}
  }
  lp = halloc(sz, FALSE); if (!lp) { return ierr(E_MEM);}
  lp0 = lp;
  *((pU4B)lp)++= sty | (f3? DS_SETFONT: 0) | DS_3DLOOK;
  *((pU4B)lp)++= 0;
  *((pU2B)lp)++ = (U2B)ni;
  *((pU2B)lp)++ = ds->x; *((pU2B)lp)++ = ds->y;
  *((pU2B)lp)++ = ds->w; *((pU2B)lp)++ = ds->h;
  *((pU2B)lp)++ = 0;
  if (f1) {
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, cls, -1, lp, 256);
    ((pU2B)lp) += n;
  } else {
    *((pU2B)lp)++ = 0;
  }
  if (f2) {
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, ds->tit, -1, lp, 256);
    ((pU2B)lp) += n;
  } else {
    *((pU2B)lp)++ = 0;
  }
  if (f3) {
    *((pU2B)lp)++ = (U2B)ptsz;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, face, -1, lp, 256);
    ((pU2B)lp) += n;
  }
  if ((U4B)lp & 2) { *((pU2B)lp)++ = 0;}
  for (di = di0; di < di0 + ni; di++) {
    tx = di->txt; if (!tx) { tx = "";}
    *((pU4B)lp)++= di->sty;
    *((pU4B)lp)++= 0;
    *((pU2B)lp)++ = di->x; *((pU2B)lp)++ = di->y;
    *((pU2B)lp)++ = di->w; *((pU2B)lp)++ = di->h;
    *((pU2B)lp)++ = (U2B)di->id;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, di->cls, -1, lp, 256);
    ((pU2B)lp) += n;
    n = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, tx, -1, lp, 256);
    ((pU2B)lp) += n;
    *((pU2B)lp)++ = 0;
    if ((U4B)lp & 2) { *((pU2B)lp)++ = 0;}
  }
  return lp0;
}

I4B  WINAPI DlgBoxInput(HWND hwnd, rDLGS ds, DLGPROC lpfn, iANY lpa)
{ // 儌乕僟儖僟僀傾儘僌儃僢僋僗
  I4B re;
  pANY lp;

  lp = mkdlgtmp(ds, NULL, wsDlg); if (!lp) return -1;
  re = DialogBoxIndirectParam(WindowInstance(hwnd), lp, hwnd, lpfn, lpa);
  UpdateWindow(hwnd);
  hfree(lp);
  return re;
}

HWND WINAPI CreateDlgBox(HWND hwnd, rDLGS ds, DLGPROC lpfn, iANY lpa)
{ // 儌乕僪儗僗僟僀傾儘僌儃僢僋僗
  pANY lp;
  HWND hdlg;

  lp = mkdlgtmp(ds, NULL, wsMls); if (!lp) return NULL;
  hdlg = CreateDialogIndirectParam(WindowInstance(hwnd), lp, hwnd, lpfn, lpa);
  hfree(lp);
  return hdlg;
}

I4B  WINAPI PropSheetInput(HWND hwnd, rPSHS ps, I4B ip)
{ // 僾儘僷僥傿僔乕僩
  I4B i, re;
  pPSHI pp;
  pANY lp, pa[32];

  for (i = 0, pp = ps->pp; i < ps->np; i++, pp++) {
    if (pp->psz) {
      pa[i] = halloc(pp->psz, FALSE); if (!pa[i]) { ierr(E_MEM); re = -1; goto _10;}
      memcpy(pa[i], (rANY)pp->lpa, pp->psz);
    } else {
      *(uANY *)&pa[i] = pp->lpa;
    }
  }
 _00:
  pp = &ps->pp[ip];
  lp = mkdlgtmp(pp->ds, NULL, wsDlg); if (!lp) { re = -1; goto _10;}
  re = DialogBoxIndirectParam(WindowInstance(hwnd), lp, hwnd, pp->lpfn, (uANY)pa[ip]);
  hfree(lp);
  if (re >= IDPSH && re < IDPSH + ps->np) { ip = re - IDPSH; goto _00;}
 _10:
  for (i--, pp = &ps->pp[i]; i >= 0; i--, pp--) {
    if (re == IDOK) {
      if (pp->psz) {
        memcpy((pANY)pp->lpa, pa[i], pp->psz);
      } else {
        pp->lpa = *(uANY *)&pa[i];
      }
    }
    if (pp->psz) { hfree(pa[i]);}
  }
  UpdateWindow(hwnd);
  return re;
}

void LOCALF SetMBTN(pDLGI di, I4B x, I4B y, I4B id)
{ // 儊僢僙乕僕儃僢僋僗偺儃僞儞愝掕
  static DLGI btn[] = {                                    // id
    { C_BDEF|wsGT, 0, 0, 48, 14, IDOK,     "OK" },         //  1
    { C_BPSH|wsT,  0, 0, 48, 14, IDCANCEL, "僉儍儞僙儖" }, //  2
    { C_BDEF|wsGT, 0, 0, 48, 14, IDABORT,  "拞巭(&A)" },   //  3
    { C_BPSH|wsT,  0, 0, 48, 14, IDRETRY,  "嵞帋峴(&R)" }, //  4
    { C_BPSH|wsT,  0, 0, 48, 14, IDIGNORE, "柍帇(&I)" },   //  5
    { C_BDEF|wsGT, 0, 0, 48, 14, IDYES,    "偼偄(&Y)" },   //  6
    { C_BPSH|wsT,  0, 0, 48, 14, IDNO,     "偄偄偊(&N)" }, //  7
  };

  *di = btn[id - 1]; di->x = x; di->y = y;
}

BOOL LOCALF MSG_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 儊僢僙乕僕儃僢僋僗僟僀傾儘僌僾儘僔乕僕儍
  switch (umsg) {
  case WM_INITDIALOG:
    if (lpa) { SendDlgItemMessage(hdlg, 101, STM_SETIMAGE, IMAGE_ICON, lpa);}
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    switch (wpa) {
    case IDOK:
    case IDCANCEL:
    case IDABORT:
    case IDRETRY:
    case IDIGNORE:
    case IDYES:
    case IDNO:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

I4B  WINAPI MsgBox(HWND hwnd, rSTR st, rSTR ca, I4B flg)
{ // 儊僢僙乕僕儃僢僋僗
  I4B re;
  HICON hico;
  pDLGI di;
  static DLGI dit[5];
  static DLGS dlg = { dit, };

  if (!hwnd) { return MessageBox(NULL, st, ca, flg);}
  switch (flg & 0xf0) {
  default:
    hico = NULL; break;
  case MB_ICONERROR:
    hico = LoadIcon(NULL, IDI_ERROR); break;
  case MB_ICONQUESTION:
    hico = LoadIcon(NULL, IDI_QUESTION); break;
  case MB_ICONWARNING:
    hico = LoadIcon(NULL, IDI_WARNING); break;
  case MB_ICONINFORMATION:
    hico = LoadIcon(NULL, IDI_INFORMATION); break;
  }
  dlg.w = 208;
  dlg.h =  80;
  dlg.tit = ca? ca: WindowText(hwnd);
  di = dlg.di;
  if (hico) {
    SetDLGI(di++, C_SICO|wsG,  8, 10, 24, 24, 101, "");
    SetDLGI(di++, C_SMUL|wsG, 32, 14, dlg.w - 40, 40, -1, st);
  } else {
    SetDLGI(di++, C_SMUL|wsG,  8, 14, dlg.w - 16, 40, -1, st);
  }
  switch (flg & 0x0f) {
  default:
    SetMBTN(di++, dlg.w - 54, dlg.h - 20, 1);
    break;
  case MB_OKCANCEL:
    SetMBTN(di++, dlg.w -106, dlg.h - 20, 1);
    SetMBTN(di++, dlg.w - 54, dlg.h - 20, 2);
    break;
  case MB_ABORTRETRYIGNORE:
    SetMBTN(di++, dlg.w -158, dlg.h - 20, 3);
    SetMBTN(di++, dlg.w -106, dlg.h - 20, 4);
    SetMBTN(di++, dlg.w - 54, dlg.h - 20, 5);
    break;
  case MB_YESNOCANCEL:
    SetMBTN(di++, dlg.w -158, dlg.h - 20, 6);
    SetMBTN(di++, dlg.w -106, dlg.h - 20, 7);
    SetMBTN(di++, dlg.w - 54, dlg.h - 20, 2);
    break;
  case MB_YESNO:
    SetMBTN(di++, dlg.w -106, dlg.h - 20, 6);
    SetMBTN(di++, dlg.w - 54, dlg.h - 20, 7);
    break;
  }
  dlg.ni = di - dlg.di;
  re = DlgBoxInput(hwnd, &dlg, MSG_DlgProc, (uANY)hico);
  if (re == IDCANCEL) {
    switch (flg & 0x0f) {
    case MB_OK:
      re = IDOK; break;
    case MB_ABORTRETRYIGNORE:
      re = IDABORT; break;
    case MB_YESNO:
      re = IDNO; break;
    }
  }
  return re;
}

I4B  WINAPI OkBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_OK);
}

I4B  WINAPI OkCanBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_OKCANCEL);
}

I4B  WINAPI YesNoBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_YESNO);
}

I4B  WINAPI YesNoCanBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_YESNOCANCEL);
}

I4B  WINAPI ErrorBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_ICONERROR|MB_OK);
}

I4B  WINAPI WarningBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_ICONWARNING|MB_YESNO);
}

I4B  WINAPI AlertBox(HWND hwnd, rSTR st, rSTR ca)
{ // 儊僢僙乕僕儃僢僋僗
  return MsgBox(hwnd, st, ca, MB_ICONWARNING|MB_ABORTRETRYIGNORE);
}

I4B  WINAPI ResultBox(HWND hwnd, rSTR st, rSTR ca, BOOL re)
{ // 儊僢僙乕僕儃僢僋僗
  return (re? OkBox: ErrorBox)(hwnd, format(re? "%s傪姰椆偟傑偟偨丅": "%s偵幐攕偟傑偟偨丅", st), ca);
}

BOOL LOCALF AltErrorBox(rSTR em, U4B er, rSTR fn, U4B lo)
{ // 僄儔乕儊僢僙乕僕昞帵
  HWND hwnd = error_message_box_owner();
  I1B msg[LBUF];

  return MsgBox(hwnd, error_reporting_message(msg, em, er, fn, lo), NULL, MB_ICONERROR|MB_OKCANCEL) == IDOK;
}

BOOL WINAPI OpenFileDlgBox(HWND hwnd, pOFNS os)
{ // 奐偔僟僀傾儘僌儃僢僋僗
  I4B re;
  OPENFILENAME ofn;

  memset(&ofn, 0, sizeof(OPENFILENAME));
  ofn.lStructSize = sizeof(OPENFILENAME);
  ofn.hwndOwner = hwnd;
  ofn.lpstrFilter = os->fil;
  ofn.nFilterIndex = os->idx;
  ofn.lpstrFile = os->nam;
  ofn.nMaxFile = 256;
  ofn.Flags = os->flg;
  re = GetOpenFileName(&ofn);
  os->idx = ofn.nFilterIndex;
  os->flg = ofn.Flags;
  UpdateWindow(hwnd);
  return re;
}

BOOL WINAPI SaveFileDlgBox(HWND hwnd, pOFNS os)
{ // 曐懚僟僀傾儘僌儃僢僋僗
  I4B re;
  OPENFILENAME ofn;

  memset(&ofn, 0, sizeof(OPENFILENAME));
  ofn.lStructSize = sizeof(OPENFILENAME);
  ofn.hwndOwner = hwnd;
  ofn.lpstrFilter = os->fil;
  ofn.nFilterIndex = os->idx;
  ofn.lpstrFile = os->nam;
  ofn.nMaxFile = 256;
  ofn.Flags = os->flg;
  re = GetSaveFileName(&ofn);
  os->idx = ofn.nFilterIndex;
  os->flg = ofn.Flags;
  UpdateWindow(hwnd);
  return re;
}

BOOL WINAPI PrintDlgBox(HWND hwnd, pPRDS ps)
{ // 報嶞僟僀傾儘僌儃僢僋僗
  I4B re, fi;
  LPDEVMODE dm;
  PRINTDLG prd;

  memset(&prd, 0, sizeof(PRINTDLG));
  prd.lStructSize = sizeof(PRINTDLG);
  prd.hwndOwner = hwnd;
  prd.Flags = PD_RETURNDEFAULT;
  prd.nFromPage = ps->nf;
  prd.nToPage = ps->nt;
  prd.nMinPage = 1;
  prd.nMaxPage = ps->np;
  prd.nCopies = ps->nc;
  re = PrintDlg(&prd); if (!re) goto _10;
  if (prd.hDevMode && !!(dm = GlobalLock(prd.hDevMode))) {
    fi = dm->dmFields;
    if (fi & DM_PAPERSIZE)   { dm->dmPaperSize   = ps->psz;}
    if (fi & DM_ORIENTATION) { dm->dmOrientation = ps->ori;}
    if (fi & DM_PAPERWIDTH)  { dm->dmPaperWidth  = ps->wid;}
    if (fi & DM_PAPERLENGTH) { dm->dmPaperLength = ps->len;}
    GlobalUnlock(prd.hDevMode);
  }
  prd.Flags = ps->flg;
  re = PrintDlg(&prd); if (!re) goto _10;
  ps->hdc = prd.hDC;
  ps->flg = prd.Flags;
  ps->nf = prd.nFromPage;
  ps->nt = prd.nToPage;
  ps->nc = prd.nCopies;
  if (prd.hDevMode && !!(dm = GlobalLock(prd.hDevMode))) {
    fi = dm->dmFields;
    if (fi & DM_PAPERSIZE)   { ps->psz = dm->dmPaperSize;}
    if (fi & DM_ORIENTATION) { ps->ori = dm->dmOrientation;}
    if (fi & DM_PAPERWIDTH)  { ps->wid = dm->dmPaperWidth;}
    if (fi & DM_PAPERLENGTH) { ps->len = dm->dmPaperLength;}
    GlobalUnlock(prd.hDevMode);
  }
 _10:
  UpdateWindow(hwnd);
  return re;
}

typedef struct {
  rSTR  st;
  I4B   wid;
  I4B   hei;
  I4B   hmg;
  I4B   vmg;
} PAPI;
  // 梡巻僒僀僘
static PAPI PAP[] = {
  { "俙俁 (297 x 420 mm)", 297, 420, 20, 25 },
  { "俛係 (257 x 364 mm)", 257, 364, 20, 25 },
  { "俙係 (210 x 297 mm)", 210, 297, 20, 25 },
  { "俛俆 (182 x 257 mm)", 182, 257, 20, 25 },
  { "俙俆 (148 x 210 mm)", 148, 210, 20, 25 },
  { "俛俇 (128 x 182 mm)", 128, 182, 20, 25 },
  { "俙俇 (105 x 148 mm)", 105, 148, 20, 25 },
};

  // 報嶞梡巻愝掕忣曬
typedef struct {
  I4B   SZ, PO, EA, AJ;
  F8B   SC;
  F8B   OW, AW;
  F8B   LM, TM, RM, BM;
} PSDP;

void LOCALF getPSD(PSDP *pa, rPSDS ps)
{ // 報嶞梡巻愝掕忣曬偺庢摼
  I4B i, w;

  pa->SZ = 2;
  pa->PO = (ps->oph >= ps->opw);
  w = (pa->PO)? ps->opw / 1000: ps->oph / 1000;
  for (i = 0; i < _countof(PAP); i++) {
    if (PAP[i].wid == w) { pa->SZ = i; break;}
  }
  pa->EA = (ps->apw > 0);
  pa->AJ = ps->adj;
  if (pa->EA && (pa->AJ & RSW_AUT)) {
    pa->SC = (F8B)ps->opw / (F8B)(ps->lpm + ps->apw + ps->rpm);
  } else {
    pa->SC = (F8B)ps->opw / (F8B)ps->ppw;
  }
  pa->SC = iround(pa->SC * 1000.0) * 0.001;
  if (pa->SC <= 0.01 || pa->SC >= 100.0) { pa->SC = 1.0;}
  pa->OW = ps->opw * 0.001;
  pa->AW = ps->apw * 0.001;
  pa->LM = ps->lpm * 0.001;
  pa->TM = ps->tpm * 0.001;
  pa->RM = ps->rpm * 0.001;
  pa->BM = ps->bpm * 0.001;
}

void LOCALF setPSD(pPSDS ps, const PSDP *pa)
{ // 報嶞梡巻愝掕忣曬偺奿擺
  if (pa->PO) {
    ps->opw = PAP[pa->SZ].wid * 1000;
    ps->oph = PAP[pa->SZ].hei * 1000;
  } else {
    ps->opw = PAP[pa->SZ].hei * 1000;
    ps->oph = PAP[pa->SZ].wid * 1000;
  }
  ps->adj = pa->AJ;
  ps->ppw = iround(ps->opw / pa->SC);
  ps->pph = iround(ps->oph / pa->SC);
  ps->lpm = iround(pa->LM * 1000.0);
  ps->tpm = iround(pa->TM * 1000.0);
  ps->rpm = iround(pa->RM * 1000.0);
  ps->bpm = iround(pa->BM * 1000.0);
}

void LOCALF SetCPAP(HWND hdlg, I4B id, I4B sz)
{ // 僪儘僢僾僟僂儞儕僗僩僨乕僞愝掕(梡巻僒僀僘)
  I4B i;

  SendDlgItemMessage(hdlg, id, CB_RESETCONTENT, 0, 0);
  for (i = 0; i < _countof(PAP); i++) {
    SendDlgItemMessage(hdlg, id, CB_ADDSTRING, 0, (uANY)PAP[i].st);
  }
  SendDlgItemMessage(hdlg, id, CB_SETCURSEL, sz, 0);
}

BOOL LOCALF PSD_DlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 報嶞梡巻愝掕僟僀傾儘僌僾儘僔乕僕儍
  PSDP *pa;
  F8B sc, lm, rm;

  switch (umsg) {
  case WM_INITDIALOG:
    SetWindowLong(hdlg, DWL_USER, (iANY)(pa = (PSDP *)lpa));
    SetCPAP(hdlg, 101, pa->SZ);
    SetBSEL(hdlg, 102, pa->PO);
    SetBSEL(hdlg, 103, !GetBSEL(hdlg, 102));
    SetEDBL(hdlg, 104, pa->TM);
    SetEDBL(hdlg, 105, pa->LM);
    SetEDBL(hdlg, 106, pa->RM);
    SetEDBL(hdlg, 107, pa->BM);
    SetBSEL(hdlg, 108, pa->AJ & RSW_AUT);
    SetBSEL(hdlg, 109, !GetBSEL(hdlg, 108));
    SetEDBL(hdlg, 110, (F8B)iround(pa->SC * 100.0));
    EnableDlgItem(hdlg, 108, pa->EA);
    EnableDlgItem(hdlg, 110, GetBSEL(hdlg, 109));
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    pa = (PSDP *)GetWindowLong(hdlg, DWL_USER);
    switch (wpa) {
    case 108:
    case 109:
      if (GetBSEL(hdlg, 108)) {
        lm = GetEDBL(hdlg, 105); rm = GetEDBL(hdlg, 106);
        sc = pa->OW / (lm + pa->AW + rm);
        SetEDBL(hdlg, 110, (F8B)iround(sc * 100.0));
      }
      EnableDlgItem(hdlg, 110, GetBSEL(hdlg, 109));
      break;
    case MKU4B(110, EN_KILLFOCUS):
      sc = GetEDBL(hdlg, 110) * 0.01; if (sc <= 0.01 || sc >= 100.0) { sc = 1.0;}
      SetEDBL(hdlg, 110, (F8B)iround(sc * 100.0));
      break;
    case IDOK:
      pa->SZ = GetCSEL(hdlg, 101);
      pa->PO = GetBSEL(hdlg, 102);
      pa->TM = GetEDBL(hdlg, 104);
      pa->LM = GetEDBL(hdlg, 105);
      pa->RM = GetEDBL(hdlg, 106);
      pa->BM = GetEDBL(hdlg, 107);
      if (GetBSEL(hdlg, 108)) { pa->AJ |= RSW_AUT;} else { pa->AJ &=~RSW_AUT;}
      pa->SC = GetEDBL(hdlg, 110) * 0.01; if (pa->SC <= 0.01 || pa->SC >= 100.0) { pa->SC = 1.0;}
      // fall through
    case IDCANCEL:
      EndDialog(hdlg, wpa);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL WINAPI PageSetupDlgBox(HWND hwnd, pPSDS ps)
{ // 報嶞梡巻愝掕僟僀傾儘僌儃僢僋僗
  I4B re = TRUE;
  PSDP par;
  static DLGI dit[] = {
    { C_BGRP|wsG,   6,  6,212, 44,  -1, "梡巻" },
    { C_SLFT|wsG,  14, 18, 40,  8,  -1, "僒僀僘(&Z):" },
    { C_CSEL|wsT,  54, 16,112,128, 101, "" },
    { C_SLFT|wsG,  14, 34, 40,  8,  -1, "曽丂岦:" },
    { C_BSEL|wsGT, 54, 33, 48, 10, 102, "廲(&P)" },
    { C_BSEL|ws_, 102, 33, 48, 10, 103, "墶(&A)" },
    { C_BGRP|wsG,   6, 54,212, 44,  -1, "梋敀(mm)" },
    { C_SLFT|wsG,  82, 66, 28,  8,  -1, "忋(&T):" },
    { C_ENUM|wsT, 110, 64, 28, 12, 104, "" },
    { C_SLFT|wsG,  14, 74, 28,  8,  -1, "嵍(&L):" },
    { C_ENUM|wsT,  42, 72, 28, 12, 105, "" },
    { C_SLFT|wsG, 150, 74, 28,  8,  -1, "塃(&R):" },
    { C_ENUM|wsT, 178, 72, 28, 12, 106, "" },
    { C_SLFT|wsG,  82, 82, 28,  8,  -1, "壓(&B):" },
    { C_ENUM|wsT, 110, 80, 28, 12, 107, "" },
    { C_BGRP|wsG,   6,102,212, 44,  -1, "奼戝弅彫" },
    { C_BSEL|wsGT, 14,113, 80, 10, 108, "墶暆偵崌傢偣傞(&J)" },
    { C_BSEL|ws_,  14,129, 50, 10, 109, "攞丂棪(&S):" },
    { C_ENUM|wsT,  64,128, 32, 12, 110, "" },
    { C_SLFT|wsG,  97,130, 16,  8,  -1, "亾" },
    { C_BDEF|wsGT,118,172, 48, 14, IDOK, "OK" },
    { C_BPSH|wsT, 170,172, 48, 14, IDCANCEL, "僉儍儞僙儖" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 224, 192, "報嶞梡巻愝掕" };

  getPSD(&par, ps);
  if (!(ps->adj & RSW_SKP)) { re = (DlgBoxInput(hwnd, &dlg, PSD_DlgProc, (uANY)&par) == IDOK);}
  if (re) { setPSD(ps, &par);}
  return re;
}

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

  // 儗億乕僩忣曬
typedef struct {
  CVSE  cvse;
  HWND  hown;
  I4B   npg;
  FREP  frep;
  uANY  par;
  uANY  ext;
  U4B   rsv;
  I4B   adj;  // -+
  I4B   apw;  //  |
  I4B   opw;  //  |
  I4B   oph;  //  |
  I4B   ppw;  //  |
  I4B   pph;  //  |
  I4B   lpm;  //  |
  I4B   tpm;  //  |
  I4B   rpm;  //  |= PSDS
  I4B   bpm;  // -+
  I4B   phh;
  I4B   pfh;
  I4B   csf, lsf;
  I4B   pid, cid;
  I4B   bph, aph;
  I4B   tal, fiw;
  I4B   liw, riw;
  I4B   sta;
  I4B   rsr;
  I4B   rtm;
  I1B   tit[32];
  I1B   usr[32];
} REPE;
typedef REPE *pREPE;

HREP WINAPI CreateReport(rREPI ri)
{ // 儗億乕僩忣曬嶌惉
  I4B flg;
  pREPE rp;

  if (!ri->frep) return NULL;
  rp = (pREPE)CreateCanvas(NULL, sizeof(REPE) - sizeof(CVSE)); if (!rp) return NULL;
  rp->npg = 1;
  rp->frep = ri->frep;
  rp->par = ri->pa;
  flg = ri->flg;
  if (!(flg & 0x08)) {
    rp->opw = PAP[flg & 0x07].wid * 1000;
    rp->oph = PAP[flg & 0x07].hei * 1000;
  } else {
    rp->opw = PAP[flg & 0x07].hei * 1000;
    rp->oph = PAP[flg & 0x07].wid * 1000;
  }
  rp->ppw = rp->opw;
  rp->pph = rp->oph;
  rp->lpm = rp->rpm = (PAP[flg & 0x07].hmg + (1 - ((flg & 0x80)>>6))*((flg & 0x70)>>3)) * 1000;
  rp->tpm = rp->bpm = (PAP[flg & 0x07].vmg + (1 - ((flg & 0x80)>>6))*((flg & 0x70)>>3)) * 1000;
  rp->phh = (rp->tpm > 5000)? rp->tpm - 5000: 0;
  rp->pfh = (rp->bpm > 5000)? rp->bpm - 5000: 0;
  rp->csf = 250;
  rp->lsf = 1300;
  if (ri->tit) { strcpyn(rp->tit, ri->tit, sizeof(rp->tit) - 1);}
  if (!rp->frep((HREP)rp, REPM_CREATE, 0, rp->par)) { DeleteCanvas((HREP)rp); return NULL;}
  return (HREP)rp;
}

void WINAPI DeleteReport(HREP rp)
{ // 儗億乕僩忣曬嶍彍
  if (!rp) return;
  ((pREPE)rp)->frep(rp, REPM_DESTROY, 0, ((pREPE)rp)->par);
  DeleteCanvas(rp);
}

HWND WINAPI hWND(HREP rp)
{ // 恊僂傿儞僪僂偺僴儞僪儖
  return ((pREPE)rp)->hown;
}

void WINAPI SetReportInfo(HREP rp, rSTR tit, rSTR usr, I4B sr, I4B tm)
{ // 僞僀僩儖丄嶌惉幰丄嶌惉擔丄嶌惉帪崗偺愝掕
  if (tit) { strcpyx(((pREPE)rp)->tit, tit, sizeof(((pREPE)rp)->tit) - 1);}
  if (usr) { strcpyx(((pREPE)rp)->usr, usr, sizeof(((pREPE)rp)->usr) - 1);}
  if (sr) { ((pREPE)rp)->rsr = sr;}
  if (tm) { ((pREPE)rp)->rtm = tm;}
}

rSTR WINAPI ReportTitle(HREP rp)
{ // 僞僀僩儖
  return ((pREPE)rp)->tit;
}

rSTR WINAPI ReportAuthor(HREP rp)
{ // 嶌惉幰
  return ((pREPE)rp)->usr;
}

I4B  WINAPI ReportDate(HREP rp)
{ // 嶌惉擔
  return ((pREPE)rp)->rsr;
}

I4B  WINAPI ReportTime(HREP rp)
{ // 嶌惉帪崗
  return ((pREPE)rp)->rtm;
}

void WINAPI SetReportExtra(HREP rp, uANY pa)
{ // 儗億乕僩偺晅壛忣曬愝掕
  ((pREPE)rp)->ext = pa;
}

uANY WINAPI ReportExtra(HREP rp)
{ // 儗億乕僩偺晅壛忣曬
  return ((pREPE)rp)->ext;
}

void WINAPI SetNPages(HREP rp, I4B npg)
{ // 儁乕僕悢愝掕
  if (npg > 0) { ((pREPE)rp)->npg = npg;}
}

I4B  WINAPI NPages(HREP rp)
{ // 儁乕僕悢
  return ((pREPE)rp)->npg;
}

void WINAPI SetPaperSize(HREP rp, F8B w, F8B h, F8B scl)
{ // 弌椡梡巻僒僀僘偲攞棪偺愝掕
  if (scl <= 0.01 || scl >= 100.0) { scl = 1.0;}
  ((pREPE)rp)->opw = iround(w * 1000.0);
  ((pREPE)rp)->oph = iround(h * 1000.0);
  ((pREPE)rp)->ppw = iround((w / scl) * 1000.0);
  ((pREPE)rp)->pph = iround((h / scl) * 1000.0);
}

F8B  WINAPI PaperWidth(HREP rp)
{ // 弌椡梡巻墶僒僀僘
  return ((pREPE)rp)->opw * 0.001;
}

F8B  WINAPI PaperHeight(HREP rp)
{ // 弌椡梡巻廲僒僀僘
  return ((pREPE)rp)->oph * 0.001;
}

void WINAPI SetPageSize(HREP rp, F8B w, F8B h)
{ // 尨峞梡巻僒僀僘愝掕
  SetPaperSize(rp, w, h, 1.0);
}

F8B  WINAPI PageWidth(HREP rp)
{ // 尨峞梡巻墶僒僀僘
  return ((pREPE)rp)->ppw * 0.001;
}

F8B  WINAPI PageHeight(HREP rp)
{ // 尨峞梡巻廲僒僀僘
  return ((pREPE)rp)->pph * 0.001;
}

F8B  WINAPI PageLeft(HREP rp)
{ // 尨峞梡巻嵍抂
  return -OriginX(rp);
}

F8B  WINAPI PageTop(HREP rp)
{ // 尨峞梡巻忋抂
  return -OriginY(rp);
}

F8B  WINAPI PageRight(HREP rp)
{ // 尨峞梡巻塃抂
  return (((pREPE)rp)->ppw * 0.001) - OriginX(rp);
}

F8B  WINAPI PageBottom(HREP rp)
{ // 尨峞梡巻壓抂
  return (((pREPE)rp)->pph * 0.001) - OriginY(rp);
}

void WINAPI SetPageMargin(HREP rp, F8B lm, F8B tm, F8B rm, F8B bm)
{ // 梡巻偺梋敀僒僀僘愝掕
  ((pREPE)rp)->lpm = iround(lm * 1000.0); ((pREPE)rp)->tpm = iround(tm * 1000.0);
  ((pREPE)rp)->rpm = iround(rm * 1000.0); ((pREPE)rp)->bpm = iround(bm * 1000.0);
  ((pREPE)rp)->phh = (((pREPE)rp)->tpm > 500)? ((pREPE)rp)->tpm - 500: 0;
  ((pREPE)rp)->pfh = (((pREPE)rp)->bpm > 500)? ((pREPE)rp)->bpm - 500: 0;
}

F8B  WINAPI BodyWidth(HREP rp)
{ // 杮暥椞堟墶僒僀僘
  return (((pREPE)rp)->ppw - ((pREPE)rp)->lpm - ((pREPE)rp)->rpm) * 0.001;
}

F8B  WINAPI BodyHeight(HREP rp)
{ // 杮暥椞堟廲僒僀僘
  return (((pREPE)rp)->pph - ((pREPE)rp)->tpm - ((pREPE)rp)->bpm) * 0.001;
}

F8B  WINAPI BodyLeft(HREP rp)
{ // 杮暥椞堟嵍抂
  return ((pREPE)rp)->lpm * 0.001 - OriginX(rp);
}

F8B  WINAPI BodyTop(HREP rp)
{ // 杮暥椞堟忋抂
  return ((pREPE)rp)->tpm * 0.001 - OriginY(rp);
}

F8B  WINAPI BodyRight(HREP rp)
{ // 杮暥椞堟塃抂
  return (((pREPE)rp)->ppw - ((pREPE)rp)->rpm) * 0.001 - OriginX(rp);
}

F8B  WINAPI BodyBottom(HREP rp)
{ // 杮暥椞堟壓抂
  return (((pREPE)rp)->pph - ((pREPE)rp)->bpm) * 0.001 - OriginY(rp);
}

void WINAPI SetHeaderHeight(HREP rp, F8B hh)
{ // 僿僢僟椞堟崅偝愝掕
  ((pREPE)rp)->phh = iround(hh * 1000.0);
}

void WINAPI SetFooterHeight(HREP rp, F8B fh)
{ // 僼僢僞椞堟崅偝愝掕
  ((pREPE)rp)->pfh = iround(fh * 1000.0);
}

F8B  WINAPI HeaderHeight(HREP rp)
{ // 僿僢僟椞堟崅偝
  return ((pREPE)rp)->phh * 0.001;
}

F8B  WINAPI HeaderTop(HREP rp)
{ // 僿僢僟椞堟忋抂
  return BodyTop(rp) - ((pREPE)rp)->phh * 0.001;
}

F8B  WINAPI FooterHeight(HREP rp)
{ // 僼僢僞椞堟崅偝
  return ((pREPE)rp)->pfh * 0.001;
}

F8B  WINAPI FooterBottom(HREP rp)
{ // 僼僢僞椞堟壓抂
  return BodyBottom(rp) + ((pREPE)rp)->phh * 0.001;
}

void WINAPI SetReqBodyWidth(HREP rp, F8B w, I4B sw)
{ // 墶暆崌傢偣婎弨抣愝掕
  ((pREPE)rp)->adj = sw;
  ((pREPE)rp)->apw = iround(w * 1000.0);
}

F8B  WINAPI ReqBodyWidth(HREP rp)
{ // 墶暆崌傢偣婎弨抣
  return ((pREPE)rp)->apw * 0.001;
}

pCELL WINAPI PageCell(pCELL pc, HREP rp)
{ // 尨峞梡巻嬮宍
  return SetCell(pc, PageLeft(rp), PageTop(rp), PageRight(rp), PageBottom(rp));
}

pCELL WINAPI BodyCell(pCELL pc, HREP rp)
{ // 杮暥椞堟嬮宍
  return SetCell(pc, BodyLeft(rp), BodyTop(rp), BodyRight(rp), BodyBottom(rp));
}

pCELL WINAPI HeaderCell(pCELL pc, HREP rp)
{ // 僿僢僟椞堟嬮宍
  return SetCell(pc, HeaderLeft(rp), HeaderTop(rp), HeaderRight(rp), HeaderBottom(rp));
}

pCELL WINAPI FooterCell(pCELL pc, HREP rp)
{ // 僼僢僞椞堟嬮宍
  return SetCell(pc, FooterLeft(rp), FooterTop(rp), FooterRight(rp), FooterBottom(rp));
}

static U2B  CRLF = 0x0a0d;
static U2B  LTAG = 0xf781;
static U2B  PTAG = 0xa581;
static U2B  LBRA = 0xe181;
static U2B  RBRA = 0xe281;

void WINAPI SetLineBreakTag(U2B lbt)
{ // 夵峴僞僌偺愝掕
  LTAG = lbt;
}

U2B  WINAPI LineBreakTag(void)
{ // 夵峴僞僌
  return LTAG;
}

void WINAPI SetPageBreakTag(U2B pbt)
{ // 夵儁乕僕僞僌偺愝掕
  PTAG = pbt;
}

U2B  WINAPI PageBreakTag(void)
{ // 夵儁乕僕僞僌
  return PTAG;
}

void WINAPI SetBrackets(U2B lbr, U2B rbr)
{ // 僞僌妵屖偺愝掕
  LBRA = lbr;
  RBRA = rbr;
}

U2B  WINAPI BracketL(void)
{ // 僞僌嵍妵屖
  return LBRA;
}

U2B  WINAPI BracketR(void)
{ // 僞僌塃妵屖
  return RBRA;
}

#define  KINSTR  "丅丄丆丏乯乴乶乸乺乼乿亁亃"

BOOL LOCALF IsKinsoku(rSTR pt)
{ // 峴摢嬛懃暥帤
  rSTR st = KINSTR;

  while (*st != '\0') {
    if (iszen(st)) {
      if (*(rU2B)pt == *((rU2B)st)++) return TRUE;
    } else {
      if ((U1B)*pt == (U1B)*st++) return TRUE;
    }
  }
  return *(rU2B)pt == CRLF || *(rU2B)pt == LTAG || *(rU2B)pt == PTAG;
}

void WINAPI CloseBrackets(rSTR *pp, BOOL sw)
{ // 僞僌偺廔傢傝傑偱僗僉僢僾
  rSTR st = *pp;

  while (*st != '\0') {
    if (*(rU2B)st == RBRA) { st += 2; goto _10;}
    else if (iszen(st)) { st += 2;}
    else { st++;}
  }
  ierr(E_DAT); goto _20;
 _10: if (sw && *(rU2B)st == CRLF) { st += 2;}
 _20: *pp = st;
}

void WINAPI SetSpacingFactor(HREP rp, F8B csf, F8B lsf)
{ // 暥帤娫挷惍攞棪丄峴僺僢僠攞棪偺愝掕
  if (csf < 0.0 || csf > 2.0) { csf = 0.0;} else if (csf > 1.0) { csf -= 1.0;}
  if (lsf < 0.0 || lsf > 2.0) { lsf = 1.0;} else if (lsf < 1.0) { lsf += 1.0;}
  ((pREPE)rp)->csf = iround(csf * 1000.0);
  ((pREPE)rp)->lsf = iround(lsf * 1000.0);
}

F8B  WINAPI SpacingFactorC(HREP rp)
{ // 暥帤娫挷惍攞棪
  return ((pREPE)rp)->csf * 0.001;
}

F8B  WINAPI SpacingFactorL(HREP rp)
{ // 峴僺僢僠攞棪
  return ((pREPE)rp)->lsf * 0.001;
}

pWHSZ WINAPI SpaceSize(pWHSZ sz, HREP rp)
{ // 暥帤娫挷惍丄峴僺僢僠
  sz->w = (((pCVSE)rp)->tch * ((pREPE)rp)->csf * 0.001) * 0.001;
  sz->h = (((pCVSE)rp)->tch * ((pREPE)rp)->lsf * 0.001) * 0.001;
  return sz;
}

typedef struct {
  I1B   tag[4];
  I1B   tfa[32];
  I4B   tch, tst;
  BGRC  tco;
  I4B   bph, aph;
  I4B   tal, fiw;
  I4B   liw, riw;
} PFME;
typedef PFME *pPFME;
  // 抜棊彂幃丄僼僅儞僩
typedef struct {
  pPFME pf;
  I4B   ni;
} PFMM;
typedef PFMM *pPFMM;

static PFME FMTI[32];
static PFMM FMTS = { FMTI, _countof(FMTI) };

I4B  LOCALF PFmtID(rSTR tag)
{ // 抜棊彂幃僒乕僠
  I4B i;

  for (i = 0; i < FMTS.ni; i++) {
    if (*(rU2B)tag == *(rU2B)FMTS.pf[i].tag) { return i;}
  }
  return -1;
}

BOOL WINAPI RegisterParagraphFormat(I4B id, rSTR tag, rPFMI fi)
{ // 抜棊彂幃偺搊榐
  pPFME pf;

  if ((U4B)id >= (U4B)FMTS.ni) {
    if (tag) { id = PFmtID(tag);}
    if (id < 0) return FALSE;
  }
  pf = &FMTS.pf[id];
  if (tag) { *(pU2B)&pf->tag = *(rU2B)tag;}
  if (fi) {
    if (fi->face) { strcpyx(pf->tfa, fi->face, sizeof(pf->tfa) - 1);}
    if (fi->ch > 0.0) { pf->tch = iround(fi->ch * 1000.0);}
    pf->tst = fi->flg &~0x0f;
    pf->tco = fi->col;
    pf->bph = iround(fi->bph * 1000.0);
    pf->aph = iround(fi->aph * 1000.0);
    pf->tal = fi->flg & 0x0f;
    pf->fiw = iround(fi->fiw * 1000.0);
    pf->liw = iround(fi->liw * 1000.0);
    pf->riw = iround(fi->riw * 1000.0);
  }
  return TRUE;
}

F8B  WINAPI ParagraphSpacingB(HREP rp)
{ // 抜棊慜僗儁乕僗
  return ((pREPE)rp)->bph * 0.001;
}

F8B  WINAPI ParagraphSpacingA(HREP rp)
{ // 抜棊屻僗儁乕僗
  return ((pREPE)rp)->aph * 0.001;
}

I4B  WINAPI ParagraphAlignment(HREP rp)
{ // 暥帤懙偊
  return ((pREPE)rp)->tal;
}

F8B  WINAPI ParagraphIndentationF(HREP rp)
{ // 嵟弶偺峴偺僀儞僨儞僩
  return ((pREPE)rp)->fiw * 0.001;
}

F8B  WINAPI ParagraphIndentationL(HREP rp)
{ // 嵍僀儞僨儞僩
  return ((pREPE)rp)->liw * 0.001;
}

F8B  WINAPI ParagraphIndentationR(HREP rp)
{ // 塃僀儞僨儞僩
  return ((pREPE)rp)->riw * 0.001;
}

void WINAPI SetFlowTextStatus(HREP rp, I4B sta)
{ // 忬懺僼儔僌愝掕
  ((pREPE)rp)->sta = sta;
}

I4B  WINAPI FlowTextStatus(HREP rp)
{ // 忬懺僼儔僌
  return ((pREPE)rp)->sta;
}

void WINAPI StartFlowText(HREP rp)
{ // 奐巒張棟
  memset(FMTS.pf, 0, FMTS.ni * sizeof(PFME));
  strcpyx(FMTS.pf[0].tfa, MONFACE, sizeof(FMTS.pf[0].tfa) - 1);
  FMTS.pf[0].tch = iround(PT2MM(DLGPTSZ) * 1000.0);
  ((pREPE)rp)->pid = ((pREPE)rp)->cid = 0;
  ((pREPE)rp)->sta = STA_PAR|STA_LIN;
}

  // 僞僌梫慺
static FTEI TAGI[32];
static FTES TAGS = { TAGI, _countof(TAGI) };

BOOL WINAPI RegisterFlowTextTags(rFTES ps)
{ // 棳偟崬傒僥僉僗僩偺僞僌梫慺偺搊榐
  I4B i;

  for (i = 0; i < TAGS.ni; i++) {
    if (!TAGS.pi[i].nam) break;
  }
  if (ps->ni >= TAGS.ni - i) { return (BOOL)ierr(E_CAP);}
  memcpy(&TAGS.pi[i], ps->pi, ps->ni * sizeof(FTEI));
  return TRUE;
}

BOOL LOCALF ReadPTag(HREP rp, rSTR *pp)
{ // 抜棊僞僌撉崬
  I4B i;

  if (*(rU2B)*pp != LBRA) return FALSE;
  start(*pp + 2);
  if (token_is(TKN_IDN)) {
    for (i = 0; i < TAGS.ni; i++) {
      if (!strcmp(TAGS.pi[i].nam, buf()) && TAGS.pi[i].fpar) {
        *pp = cpos(); TAGS.pi[i].fpar(rp, pp); return TRUE;
      }
    }
  }
  CloseBrackets(pp, TRUE);
  return TRUE;
}

void LOCALF SetPFmt(HREP rp, I4B id)
{ // 抜棊彂幃愝掕
  pPFME pf = &FMTS.pf[id];

  ((pREPE)rp)->pid = ((pREPE)rp)->cid = id;
  SetTextFont(rp, pf->tfa, pf->tch * 0.001, pf->tst, pf->tco);
  ((pREPE)rp)->bph = pf->bph; ((pREPE)rp)->aph = pf->aph;
  ((pREPE)rp)->tal = pf->tal; ((pREPE)rp)->fiw = pf->fiw;
  ((pREPE)rp)->liw = pf->liw; ((pREPE)rp)->riw = pf->riw;
}

void LOCALF ReadPFmt(HREP rp, rSTR *pp)
{ // 抜棊彂幃巜掕撉崬
  I4B id;
  rSTR pt = *pp;

  if (*pt == '\0' || *(rU2B)pt == CRLF || *(rU2B)pt == LTAG || *(rU2B)pt == PTAG) return;
  while (ReadPTag(rp, &pt)) {}
  if ((id = PFmtID(pt)) >= 0) {
    pt += 2;
  } else {
    id = 0;
  }
  SetPFmt(rp, id);
  *pp = pt;
}

BOOL LOCALF ReadCTag(HREP rp, rSTR *pp, rCELL pc, pWHSZ sz)
{ // 僞僌撉崬
  I4B i;
  RECT rct;

  if (*(rU2B)*pp != LBRA) return FALSE;
  sz->w = sz->h = 0.0;
  start(*pp + 2);
  if (token_is(TKN_IDN)) {
    for (i = 0; i < TAGS.ni; i++) {
      if (!strcmp(TAGS.pi[i].nam, buf()) && TAGS.pi[i].fchr) {
        *pp = cpos(); TAGS.pi[i].fchr(rp, pp, pc, sz); return TRUE;
      }
    }
  } else if (token_is(TKN_STR)) {
    if (pc && hDC(rp)) { DrawText(hDC(rp), buf(), -1, c2dRect(&rct, rp, pc), DT2DT(((pREPE)rp)->tal &~0x03));}
    TextSize(sz, rp, buf(), -1);
    *pp = cpos();
  }
  CloseBrackets(pp, FALSE);
  return TRUE;
}

void LOCALF SetCFmt(HREP rp, I4B id)
{ // 暥帤僼僅儞僩愝掕
  pPFME pf = &FMTS.pf[id];

  ((pREPE)rp)->cid = id;
  SetTextFont(rp, pf->tfa, pf->tch * 0.001, pf->tst, pf->tco);
}

void LOCALF ReadCFmt(HREP rp, rSTR *pp, rCELL pc, pWHSZ sz)
{ // 彂幃晅偒僥僉僗僩撉崬乛弌椡
  I4B id;
  rSTR st, pt = *pp;
  RECT rct;

  sz->w = sz->h = 0.0;
  if (*pt == '\0') {
    ((pREPE)rp)->sta = STA_END|STA_PAR|STA_LIN;
  } else if (*(rU2B)pt == CRLF || *(rU2B)pt == LTAG) {
    pt += 2;
    ((pREPE)rp)->sta = STA_PAR|STA_LIN;
  } else if (*(rU2B)pt == PTAG) {
    pt += 2;
    if (*(rU2B)pt == CRLF) { pt += 2;}
    ((pREPE)rp)->sta = STA_END|STA_PAR|STA_LIN;
  } else if (ReadCTag(rp, &pt, pc, sz)) {
    ;
  } else if ((id = PFmtID(pt)) >= 0) {
    pt += 2;
    SetCFmt(rp, id);
    SpaceSize(sz, rp);
  } else if (iszen(pt)) {
    st = pt;
    pt += 2;
    if (pc && hDC(rp)) { DrawText(hDC(rp), st, 2, c2dRect(&rct, rp, pc), DT2DT(((pREPE)rp)->tal &~0x03));}
    TextSize(sz, rp, st, 2);
  } else {
    st = isprn(pt)? pt: "?";
    pt++;
    if (pc && hDC(rp)) { DrawText(hDC(rp), st, 1, c2dRect(&rct, rp, pc), DT2DT(((pREPE)rp)->tal &~0x03));}
    TextSize(sz, rp, st, 1);
  }
  *pp = pt;
}

void WINAPI FlowText(HREP rp, rSTR *pp, rCELL pc)
{ // 嬮宍椞堟傊偺彂幃晅偒僥僉僗僩棳偟崬傒
  I4B sw;
  rSTR pr, pt = *pp;
  F8B xl, xr, yt, yb, wl, wr, rh;
  CELL cel;
  WHSZ c, r;

  xl = pc->x1 + CellMarginH(rp);
  xr = pc->x2 - CellMarginH(rp);
  yt = pc->y1 + CellMarginV(rp);
  yb = pc->y2 - CellMarginV(rp);
  for (((pREPE)rp)->sta &=~STA_END, cel.y1 = yt; !(((pREPE)rp)->sta & STA_END); cel.y1 = cel.y2) {
    pr = pt;
    sw = ((((pREPE)rp)->sta & STA_PAR) != 0);
    if (sw) { ReadPFmt(rp, &pr);} else { ((pREPE)rp)->pid = ((pREPE)rp)->cid;}
    wl = xl + (sw? ((pREPE)rp)->fiw: ((pREPE)rp)->liw) * 0.001;
    wr = xr - ((pREPE)rp)->riw * 0.001;
    SpaceSize(&r, rp); rh = r.h;
    r.w = 0.0;
    ((pREPE)rp)->sta = 0;
    while (!(((pREPE)rp)->sta & STA_LIN)) {
      ReadCFmt(rp, &pr, NULL, &c);
      r.w += c.w; if (c.h > r.h) { r.h = c.h;}
      if (wl + r.w > wr - c.w && !IsKinsoku(pr)) { ((pREPE)rp)->sta |= STA_LIN;}
    }
    if (sw) { ReadPFmt(rp, &pt);} else { SetCFmt(rp, ((pREPE)rp)->pid);}
    cel.x1 = wl;
    if (((pREPE)rp)->tal & DT_RGT) { cel.x1 += (wr - wl - r.w);}
    else if (((pREPE)rp)->tal & DT_CEN) { cel.x1 += (wr - wl - r.w) / 2;}
    if (sw) { cel.y1 += ((pREPE)rp)->bph * 0.001;}
    cel.x2 = cel.x1 + r.h;
    cel.y2 = cel.y1 + r.h;
    ((pREPE)rp)->sta = 0;
    while (!(((pREPE)rp)->sta & STA_LIN)) {
      ReadCFmt(rp, &pt, &cel, &c);
      if (cel.x1 + c.w > wr - c.w && !IsKinsoku(pt)) { ((pREPE)rp)->sta |= STA_LIN;}
      else { MoveCell(&cel, c.w, 0.0);}
    }
    if (cel.y2 > yb - rh * 0.8) { ((pREPE)rp)->sta |= STA_END;}
    else if (((pREPE)rp)->sta & STA_PAR) { cel.y2 += ((pREPE)rp)->aph * 0.001;}
  }
  *pp = pt;
}

pPSDS WINAPI PageSetupInfo(HREP rp)
{ // 報嶞梡巻愝掕忣曬
  return (pPSDS)&((pREPE)rp)->adj;
}

void WINAPI StartPrint(HREP rp, HDC hdc, I4B dpi)
{ // 昤夋奐巒張棟
  F8B sc, tm;

  SetCanvasHDC(rp, hdc, dpi);
  if (((pREPE)rp)->rsr == 0) {
    tm = now();
    ((pREPE)rp)->rsr = (I4B)tm;
    ((pREPE)rp)->rtm = (I4B)((tm - (I4B)tm) * 86400);
  }
  sc = (F8B)((pREPE)rp)->opw / (F8B)((pREPE)rp)->ppw;
  SetScale(rp, sc, sc);
  DisableCanvas(rp);
  ((pREPE)rp)->frep(rp, REPM_STARTPRINT, 0, ((pREPE)rp)->par);
  EnableCanvas(rp);
}

void WINAPI EndPrint(HREP rp)
{ // 昤夋廔椆張棟
  SetCanvasHDC(rp, NULL, 0);
  ((pREPE)rp)->frep(rp, REPM_ENDPRINT, 0, ((pREPE)rp)->par);
}

void WINAPI DrawPage(HREP rp, I4B pg)
{ // 儁乕僕昤夋
  ((pREPE)rp)->frep(rp, REPM_DRAWPAGE, pg, ((pREPE)rp)->par);
}

void WINAPI SkipPage(HREP rp, I4B pg)
{ // 儁乕僕僗僉僢僾
  DisableCanvas(rp);
  ((pREPE)rp)->frep(rp, REPM_SKIPPAGE, pg, ((pREPE)rp)->par);
  EnableCanvas(rp);
}

BOOL WINAPI ReportSetup(HWND hwnd, HREP rp)
{ // 報嶞僨乕僞愝掕
  ((pREPE)rp)->hown = hwnd;
  return ((pREPE)rp)->frep(rp, REPM_SETUP, 0, ((pREPE)rp)->par);
}

BOOL WINAPI PageSetup(HWND hwnd, HREP rp)
{ // 報嶞梡巻愝掕
  I4B re;

  re = PageSetupDlgBox(hwnd, (pPSDS)&((pREPE)rp)->adj);
  if (re) ((pREPE)rp)->frep(rp, REPM_PAGESETUP, 0, ((pREPE)rp)->par);
  return re;
}

static BOOL UBrk;
static HWND hAbortDlg;

BOOL LOCALF AbortDlgProc(HWND hdlg, U4B umsg, uANY wpa, iANY lpa)
{ // 拞巭僟僀傾儘僌僾儘僔乕僕儍
  switch (umsg) {
  case WM_INITDIALOG:
    CenterWindow(hdlg, GetWindow(hdlg, GW_OWNER));
    return TRUE;
  case WM_COMMAND:
    switch (wpa) {
    case IDCANCEL:
      UBrk = TRUE;
      hAbortDlg = NULL;
      DestroyWindow(hdlg);
      return TRUE;
    }
    break;
  }
  return FALSE;
}

BOOL LOCALF AbortProc(HDC hdc, I4B er)
{ // 拞巭娭悢
  MSG msg;

  while (!UBrk && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    if (!hAbortDlg || !IsDialogMessage(hAbortDlg, &msg)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  return !UBrk;
}

void LOCALF dmpaper(pPRDS ps, HREP rp)
{ // 梡巻偺僒僀僘偲岦偒
  I4B i, w, sz = 2;

  ps->ori = (((pREPE)rp)->oph >= ((pREPE)rp)->opw)? DMORIENT_PORTRAIT: DMORIENT_LANDSCAPE;
  w = (ps->ori == DMORIENT_PORTRAIT)? ((pREPE)rp)->opw / 1000: ((pREPE)rp)->oph / 1000;
  for (i = 0; i < _countof(PAP); i++) {
    if (PAP[i].wid == w) { sz = i; break;}
  }
  switch (sz) {
  case 0: ps->psz = DMPAPER_A3; break;
  case 1: ps->psz = DMPAPER_B4; break;
  case 2: ps->psz = DMPAPER_A4; break;
  case 3: ps->psz = DMPAPER_B5; break;
  case 4: ps->psz = DMPAPER_A5; break;
  case 5: ps->psz = DMPAPER_B6_JIS; break;
  case 6: ps->psz = DMPAPER_A6; break;
  }
  ps->wid = (ps->ori == DMORIENT_PORTRAIT)? ((pREPE)rp)->opw / 100: ((pREPE)rp)->oph / 100;
  ps->len = (ps->ori == DMORIENT_PORTRAIT)? ((pREPE)rp)->oph / 100: ((pREPE)rp)->opw / 100;
}

BOOL WINAPI PrintReport(HWND hwnd, HREP rp)
{ // 報嶞
  I4B pg, i1, i2, ox, oy;
  PRDS prd;
  I1B bf[256];
  static DOCINFO dci = { sizeof(DOCINFO), };
  static DLGI dit[] = {
    { C_SCEN|wsG,   6, 20,148,  8, 101, "報嶞拞..." },
    { C_BDEF|wsGT,106, 44, 48, 14, IDCANCEL, "僉儍儞僙儖" },
  };
  static DLGS dlg = { dit, _countof(dit), 0, 0, 160, 64, "報嶞拞" };

  prd.flg = PD_NOSELECTION|PD_RETURNDC;
  prd.nf = prd.nc = 1;
  prd.np = prd.nt = (U2B)((pREPE)rp)->npg;
  dmpaper(&prd, rp);
  if (!PrintDlgBox(hwnd, &prd)) return FALSE;
  if (prd.flg & PD_PAGENUMS) {
    i1 = prd.nf; i2 = prd.nt;
  } else {
    i1 = 1; i2 = ((pREPE)rp)->npg;
  }
  dci.lpszDocName = ((pREPE)rp)->tit;
  UBrk = FALSE;
  hAbortDlg = CreateDlgBox(hwnd, &dlg, AbortDlgProc, 0);
  EnableWindow(hwnd, FALSE);
  SetAbortProc(prd.hdc, AbortProc);
  StartPrint(rp, prd.hdc, 0);
  if (StartDoc(prd.hdc, &dci) <= 0) goto _10;
  ox = GetDeviceCaps(prd.hdc, PHYSICALOFFSETX);
  oy = GetDeviceCaps(prd.hdc, PHYSICALOFFSETY);
  for (pg = 1; pg <= i2; pg++) {
    if (pg >= i1) {
      if (StartPage(prd.hdc) <= 0) { AbortDoc(prd.hdc); goto _10;}
      sprintfs(bf, "%s   %d / %d 儁乕僕", ((pREPE)rp)->tit, pg, ((pREPE)rp)->npg);
      SetSSTR(hAbortDlg, 101, bf);
      SetWindowOrgEx(prd.hdc, 0, 0, NULL);
      SetViewportOrgEx(prd.hdc, -ox, -oy, NULL);
      DrawPage(rp, pg);
      if (EndPage(prd.hdc) <= 0 || !!UBrk) { AbortDoc(prd.hdc); goto _10;}
    } else {
      SkipPage(rp, pg);
    }
  }
  EndDoc(prd.hdc); _10:
  EndPrint(rp);
  DeleteDC(prd.hdc);
  EnableWindow(hwnd, TRUE);
  if (hAbortDlg) { DestroyWindow(hAbortDlg); hAbortDlg = NULL;}
  return TRUE;
}

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

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

BOOL WINAPI InitBOLFRO(uANY pa)
{ // 奐巒張棟
  override_errmsg(AltErrorBox);
  InitGraphicObjects();
  RegisterBOLTIPClass(NULL);
  RegisterBOLTOBClass(NULL);
  RegisterBOLSTBClass(NULL);
  return TRUE;
}

void WINAPI TermBOLFRO(void)
{ // 廔椆張棟
  TermGraphicObjects();
}

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