#define MODULE_PENSELS
/*
	pensels.c
	
	int	pensel_init(void)
	void pensel_end(void)

	Pen pensel_curpen(void)

	static void DrawPenSample(int idObj, int ofsx, int ofsy, Pen pen)

	int _do_loadPenData(char* fname)
	int _do_savePenData(char* fname)

int	BrushPenDispWinProc(int kobj,int messId,int argc,EVENT* pev,int trig)
int	BrushPenBtnProc(int kobj,int messId,int argc,EVENT* pev,int trig)
int	brushTICONpensampleFunc(kobj, messId, argc, pev, trigger)
int pensel_getmix(void);

static void pened_drawSample(void)
int	PenEdEditWinProc(int kobj,int messId,int argc,EVENT* pev,int trigger)
int	PenEdSampleWinProc(int kobj,int messId,int argc,EVENT* pev,int trigger)
int	penedTICONtoolFunc(int kobj,int messId,int argc,EVENT*pev,int trigger)
int EditPen(int penidx)

static int save_penlist(void)
static int load_penlist(void)
int	PenSelSampleListWinProc(kobj, messId, argc, pev, trigger)
int	PenSelSelectWinProc(int kobj,int messId,int argc,EVENT* pev,int trig)
int	penselDBTNeditFunc(kobj, messId, argc, pev, trigger)
int	penselSBARFunc(kobj, messId, argc, pev, trigger)

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <egb.h>
#include <wgb.h>
#include <file_dlg.h>
#include "art.h"
#include "guisub.h"
#include "wgbmac.h"
#include "pensel.h"
#include "desktop.h"
#include "pen.h"
#include "fifo.h"
#include "subgrp.h"
#include "screen.h"

/*--------------------------------------------------------*/
/*                       各部品ＩＤ                       */
/*--------------------------------------------------------*/


int	idPenEdDlg = -1 ;
int	idPenEdTitleMsg = -1 ;
int	idPenEdToolTIcon[7] = -1 ;
int	idPenEdOkDBtn = -1 ;
int	idPenEdOkMsg = -1 ;
int	idPenEdCancelDBtn = -1 ;
int	idPenEdCancelMsg = -1 ;
int	idPenEdGrayMsg = -1 ;
int	idPenEdGrayNumMsg = -1 ;
int	idPenEdGraySBar = -1 ;
int	idPenEdEditHSBar = -1 ;
int	idPenEdEditVSBar = -1 ;
int	idPenEdSizeDBtn = -1 ;
int	idPenEdSizeMsg = -1 ;
int	idPenEdEditWin = -1 ;
int	idPenEdSampleWin = -1 ;
int	idPenSelDlg = -1 ;
int	idPenSelTitleMsg = -1 ;
int	idPenSelSBar = -1 ;
int	idPenSelConcMsg = -1 ;
int	idPenSelConcTIcon = -1 ;
int	idPenSelEraseIcon = -1 ;
int	idPenSelEndDBtn = -1 ;
int	idPenSelEndMsg = -1 ;
int	idPenSelEditDBtn = -1 ;
int	idPenSelEditMsg = -1 ;
int	idPenSelSaveDBtn = -1 ;
int	idPenSelSaveMsg = -1 ;
int	idPenSelLoadDBtn = -1 ;
int	idPenSelLoadMsg = -1 ;
int	idPenSelSampleListWin = -1 ;
int	idPenSelSelectWin[4] = -1 ;
int	idBrushSmallDlg = -1 ;
int	idBrushT1Hyper = -1 ;
int	idBrushTitleMsg[2] = -1 ;
int	idBrushWinSizeIcon[2] = -1 ;
int	idBrushT3Hyper = -1 ;
int	idBrushPenSampleTIcon[4] = -1 ;
int	idBrushEraseIcon[2] = -1 ;
int	idBrushTinyDlg = -1 ;
int	idBrushT5Hyper = -1 ;
int	idBrushT4Hyper = -1 ;
int	idBrushPenDispWin = -1 ;
int	idBrushPenBtn = -1 ;
int	idBrushT2Hyper = -1 ;
int	idBrushMsg[2] = -1 ;
int	idBrushModeMenu = -1 ;
int	idBrushModeMItem = -1 ;
int	idBrushModeSelMenu = -1 ;
int	idBrushModeSelMItem[7] = -1 ;
int	idBrushGrayNumMsg = -1 ;
int	idBrushGraySBar = -1 ;

// int	brushIMGBOXpendisp_tiny = -1;
// int	brushIMGBOXpendisp_tinyFunc();
// int	penselIMGBOXpenlist = -1;
// int	penselIMGBOXpenlistFunc();
// int	penedIMGBTN = -1;
// int	penedIMGBTNFunc();

/*--------------------------------------------------------*/
/*                    モジュール内変数                    */
/*--------------------------------------------------------*/

#define	PENDATAFILE	"artemis2.pen"
static char pendata_fname[_MAX_PATH];

#define	PENSEL_XNUM		5	/* 選択リスト表示の個数 */
#define	PENSEL_YNUM		3	/* 同上 */

static int nSelectPen=0;	// 0〜3:ペン候補のうちどれを選んでいるか
static int nSamplePen[10];	// 各ペン先候補(0〜3)が、何番のペンを選択しているか
// static LIST *penSampleList;	// 各ペン先候補(0〜3)の補正後のペン先
static LIST *penList;		// ペンリスト
static Pen penEdit;			// 編集中のペン(１時オブジェクト)
static int nPenEditTool=0;	// ペン編集ウィンドウで選んでいるツ−ル

int list_x=0;	/* ペンリスト上のカーソルの位置 */
int list_y=0;


/*--------------------------------------------------------*/
/*                        補助関数                        */
/*--------------------------------------------------------*/

int	grayToColor(int gray)
{
	if (scrPixelSize == 16)
	{
		int g;
		g = (255 - _min(255,_max(0,gray))) >> 3;
		return g*(1024+32+1);
	}
	else
	{
		uint g;
		g = (255 - _min(255,_max(0,gray)));
		return (g<<16)|(g<<8)|g;
	}
}

static int getPenListPosition(int n, FRAME *fr_)
/* 引数  n = リスト内番号 */
/* 返値  0=成功  -1=画面外 */
/*       fr←(x,y,wid,ht) */
{
	int ofsy = RM_getScrollPos(idPenSelSBar);
	FRAME frUser;
	RM_getWinUserFrame(idPenSelSampleListWin, &frUser);
	int x,y;
	x = n % PENSEL_XNUM;
	y = n / PENSEL_XNUM - ofsy;
	if (y < 0 || PENSEL_YNUM <= y)
		return -1;
	FRAME fr;
	fr.X = frUser.X + 36 * x;
	fr.Y = frUser.Y + 36 * y;
	fr.WID = 36;
	fr.HT = 36;
	if (fr_ != NULL)
		*fr_ = fr;
	return 0;
}

/*--------------------------------------------------------*/
/*    ペン選択ダイアログのリスト縦スクロールバーの更新    */
/*--------------------------------------------------------*/

static void pensel_updateSBar(BOOL fRedraw)
{
	int all = (list_getDataNum(penList) + PENSEL_XNUM) / PENSEL_XNUM;
	all = _max(PENSEL_YNUM, all);
	RM_setScrollRange(idPenSelSBar, PENSEL_YNUM, all, fRedraw);
}

/*--------------------------------------------------------*/
/*                   モジュールの初期化                   */
/*--------------------------------------------------------*/

int	pensel_init(void)
{
	int i;
	HYPER hyp;
  // ラジオボタン初期化
	RM_initRadioButton(idBrushPenSampleTIcon,
		               INTNUM(idBrushPenSampleTIcon), &nSelectPen);
	RM_initRadioButton(idPenEdToolTIcon,
		               INTNUM(idPenEdToolTIcon), &nPenEditTool);
  // 選択候補ペンのリストの作成
	#if 0
		if ((penSampleList = list_new(sizeof(Pen))) == NULL)
			return -1;
		for (i = 0; i < INTNUM(idPenSelSelectWin); i++)
		{
			Pen pen;
			if ((pen = pen_new(32,32)) == NULL)
				return -1;
			list_insertData(penSampleList, &pen);
		}
	#endif
  // 各候補がどのペン先を選択しているかの設定
	for (i = 0; i < INTNUM(idPenSelSelectWin); i++)
		nSamplePen[i] = i;
  // ペンのリストの作成(最初は空)
	if ((penList = list_new(sizeof(Pen))) == NULL)
		return -1;
  // 起動時のペンデータ読み込み
	sprintf(pendata_fname, "%s%s", dirExec, PENDATAFILE);
	FILE *fp = fopen(pendata_fname,"rb");
	if (fp != NULL)
		fclose(fp);
	else
	{
		_searchenv(PENDATAFILE,"PATH",pendata_fname);
		if (pendata_fname[0] == 0)
			_searchenv(PENDATAFILE,"PATH386",pendata_fname);
	}
	if (pendata_fname[0] != 0)
		_do_loadPenData(pendata_fname);
	pensel_updateSBar(FALSE);
	return 0;
}

void pensel_end(void)
{
  // 終了時のペンデータ保存
	if (pendata_fname[0] == 0)
		strcpy(pendata_fname, PENDATAFILE);
	_do_savePenData(pendata_fname);
}

/*--------------------------------------------------------*/
/*              ペンリストのダミー要素の作成              */
/*--------------------------------------------------------*/

static int penlist_makeDummy(int n)
// ペンリストの要素数が[n+1]になるまで追加する
// 成功=NOERR 失敗=-1
{
	while (list_getDataNum(penList) <= n)
	{
		Pen pen;
		if ((pen = pen_new(32,32)) == NULL)
			return -1;
		list_moveTo(penList, list_getDataNum(penList));
		if (list_insertData(penList, &pen) != 0)
			return -1;
	}
	return NOERR;
}

/*--------------------------------------------------------*/
/*              ペン先データの読み込み・保存              */
/*--------------------------------------------------------*/

#define	HEADER	15
static char pendata_header[] = "ARTemisPEN00000";

int _do_loadPenData(char* fname)
{
	FILE *fp;
	if ((fp = fopen(fname, "rb")) == NULL)
		return 0;
	char headbuf[HEADER];
	fread(headbuf,1,HEADER,fp);
	if (memcmp(headbuf, pendata_header, HEADER) == 0)
	{
		list_moveTo(penList, list_getDataNum(penList));
		while (!feof(fp))
		{
			int wh[2];
			char *buf;  int wid,ht;
			Pen pen;
			fread(wh, sizeof(wh), 1, fp);
			wid = wh[0];  ht = wh[1];
			if ((pen = pen_new(wid,ht)) == NULL)
				break;
			pen_getPattern(pen, &buf,&wid,&ht);
			fread(buf, wid*ht,1, fp);
			pen_setPattern(pen, buf,wid,ht);	/* あんましキレイじゃない */
			if (pen_IsNull(pen))
				pen_destroy(pen);
			else
				list_insertData(penList, &pen);
		}
	}
	fclose(fp);
	return 1;
}

int _do_savePenData(char* fname)
{
	FILE *fp;
	if ((fp = fopen(fname, "wb")) == NULL)
		return 0;
	fwrite(pendata_header,1,HEADER,fp);
	for (list_top(penList); !list_isOut(penList); list_next(penList))
	{
		Pen pen;
		char *buf;  int wid,ht;
		int wh[2];
		list_getData(penList, &pen);
		if (!pen_IsNull(pen))
		{
			pen_getPattern(pen, &buf,&wid,&ht);
			if (buf!=NULL)
			{
				wh[0] = wid;
				wh[1] = ht;
				fwrite(wh, sizeof(wh),1, fp);
				fwrite(buf, wid*ht, 1, fp);
			}
		}
	}
	fclose(fp);
	return 1;
}

/*--------------------------------------------------------*/
/*                     ペン先パレット                     */
/*--------------------------------------------------------*/

static void DrawPenSample(int idObj, int ofsx, int ofsy, Pen pen)
// idObj のユーザー領域内で、
// 34×34 領域内でのサンプル表示を行う
{
	#define SIZE 34
	WINCLIP *clip;
  // 描画の準備
	MG_mosDisp(2);
	RM_setOriginZero();
	RM_setClipWinUser(idObj, &clip);
  // ペンの描画
	FRAME fr;
	RM_getWinUserFrame(idObj, &fr);
	WGB_RBOXFILL(guiEgbPtr, fr.X+ofsx,fr.Y+ofsy,SIZE,SIZE,RMcol(WHITE),0);
	if (pen != NULL)
	{
		int x0,y0;
		x0 = fr.X + ofsx + (SIZE-pen->wid)/2;
		y0 = fr.Y + ofsy + (SIZE-pen->ht)/2;
		int i,j;
		for (i=0; i<pen->ht; i++)
		{
			for (j=0; j<pen->wid; j++)
			{
				int g = pen_getPixel(pen,j,i);
				if (g > 0)
					WGB_PSET(guiEgbPtr,x0+j,y0+i,grayToColor(g),0);
			}
		}
	}
  // 描画終了
	RM_resetClipWinUser(clip);
	RM_recoverOrigin();
	MG_mosDisp(3);
	#undef SIZE
}

int pensel_getmix(void)
{
	uint m = RM_getScrollPos(idBrushGraySBar);
	return (m * 255 + 50) / 100;
}

/*--------------------------------------------------------*/
/*              ペン先パレット・部品実行関数              */
/*--------------------------------------------------------*/

	int	BrushPenDispWinProc(int kobj,int messId,int argc,EVENT* pev,int trig)
	// initDataZPENSEL:idBrushPenDispWin:MJ_WINDOWL40の呼び出し関数
	{
		if (messId == MM_SHOW)
		{
			DrawPenSample(kobj, 0,0, pensel_curpen());
		}
		return NOERR ;
	}

	// initDataZPENSEL:idBrushPenBtn:MJ_BUTTONL40の呼び出し関数
	int	BrushPenBtnProc(int kobj,int messId,int argc,EVENT* pev,int trig)
	{
		EXECDIALOG(idPenSelDlg);
	  // ペン先標本の再表示
		MMI_SendMessage(idBrushPenDispWin, MM_SHOW, 0);
		return NOERR ;
	}

  /* サイズボタン */
		/*	initDataPENSEL:brushICONwinsize[0]:MJ_ICONL40の呼び出し関数	*/
		/*	initDataPENSEL:brushICONwinsize[1]:MJ_ICONL40の呼び出し関数	*/
	int	brushICONwinsizeFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		return NOERR ;
	}

  /* イレーズボタン */
		/*	initDataPENSEL:brushICONerase[0]:MJ_ICONL40の呼び出し関数	*/
		/*	initDataPENSEL:brushICONerase[1]:MJ_ICONL40の呼び出し関数	*/
	int	brushICONeraseFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		return NOERR ;
	}

  /* 描画モード選択 */
	// initDataPENSEL:brushMITEMmodesel[0..6]:MJ_MITEML40の呼び出し関数
	int	brushMITEMmodeselFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		static char msgbuf[20];
		WINCLIP *clip;
		sprintf(msgbuf,"%-9s",OBJDATA(MITEML40,kobj).string);
		MMI_SendMessage(idBrushModeMItem, MM_SETMSG, 1, msgbuf);
		WIN_beginUpDateObj(idBrushModeMItem, &clip);
		MMI_SendMessage(idBrushModeMItem, MM_SHOW, 1, msgbuf);
		WIN_endUpDateObj(clip);
		return NOERR ;
	}

  /* 描画濃度設定 */
		/*	initDataPENSEL:brushSBARgray:MJ_SCRLL40の呼び出し関数	*/
	int	brushSBARgrayFunc(kobj)
	int		kobj ;
	{
		int ptr,a;
		WINCLIP *clip;
		static char msgbuf[5];
	  /* idBrushGrayNumMsg の表示文字列の更新 */
		MMI_SendMessage( kobj, MM_GETSCROLL, 5,&ptr,&a,&a,&a,&a ) ;
		sprintf( msgbuf,"%3d%%", ptr );
		MMI_SendMessage( idBrushGrayNumMsg, MM_SETMSG, 1, msgbuf );
	  /* 表示の更新 */
		WIN_beginUpDateObj( idBrushGrayNumMsg, &clip );
		MMI_SendMessage( idBrushGrayNumMsg, MM_SHOW, 0 );
		WIN_endUpDateObj( clip );
		return NOERR ;
	}

  /*  */
	// initDataPENSEL:idBrushPenSampleTIcon[0..3]:MJ_TICONL40の呼び出し関数
	int	brushTICONpensampleFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		int i;
		for (i=0 ; i<sizeof(idBrushPenSampleTIcon)/sizeof(int) ; i++)
			if (idBrushPenSampleTIcon[i] == kobj)
				goto PENSEL;
		goto END;
	  PENSEL:
		if (nSelectPen != i)
		{
			WINCLIP *clip;
			WIN_beginUpDateObj(idBrushSmallDlg, &clip);
			MTL_resetFlagObj(idBrushPenSampleTIcon[nSelectPen], 
							 ~(MS_UNSELECT|MS_TOGGLE)) ;
			MMI_SendMessage(idBrushPenSampleTIcon[nSelectPen], MM_SHOW, 0) ;
			nSelectPen = i;
			MTL_setFlagObj(idBrushPenSampleTIcon[nSelectPen],
						   (MS_UNSELECT|MS_TOGGLE)) ;
			WIN_endUpDateObj(clip);
		}
	  END:
		return NOERR ;
	}

/*--------------------------------------------------------*/
/*                  ペン先パターンの編集                  */
/*--------------------------------------------------------*/

static SCRBITMAP bmPenEdSample=NULL; // ペン先編集時のサンプル表示ビットマップ
static int pened_ret = NOERR;

static void pened_drawSample(void)
{
	BEGINPAINT(idPenEdSampleWin)
	FRAME fr;  RM_getWinUserFrame(idPenEdSampleWin,&fr);
	scrbitmap_draw(bmPenEdSample, fr.X,fr.Y);
	ENDPAINT
}

/*--------------------------------------------------------*/
/*           ペン先パターンの編集・部品実行関数           */
/*--------------------------------------------------------*/


	int	PenEdEditWinProc(int kobj,int messId,int argc,EVENT* pev,int trigger)
	// initDataZPENSEL:idPenEdEditWin:MJ_WINDOWL40の呼び出し関数
	{
		int gray = RM_getScrollPos(idPenEdGraySBar);
		FRAME fr;
		RM_getWinUserFrame(kobj, &fr);
		if (messId == MM_SHOW)
		{
			BEGINPAINT(kobj)
			WGB_BOXFILL(guiEgbPtr,fr.X,fr.Y,fr.X2,fr.Y2,RMcol(WHITE),0);
			int i,j;
			for (i=0; i<=penEdit->wid; i++)
				WGB_LINE(guiEgbPtr, fr.X+6*i, fr.Y, fr.X+6*i, fr.Y2,
						 RMcol(BLACK), 0);
			for (i=0; i<=penEdit->ht; i++)
				WGB_LINE(guiEgbPtr, fr.X, fr.Y+6*i, fr.X2, fr.Y+6*i,
						 RMcol(BLACK), 0);
			for (i=0; i<penEdit->ht; i++)
				for (j=0; j<penEdit->wid; j++)
				{
					int g = pen_getPixel(penEdit,j,i);
					if (g > 0)
					{
						WGB_RBOXFILL(guiEgbPtr,fr.X+6*j+1,fr.Y+6*i+1,5,5,
									 grayToColor(g),0);
					}
				}
			ENDPAINT
		}
		else if (messId == MM_MOUSEON)
		{
		  // (x,y) がペン内座標であるかどうか判別
			BOOL InPen(int x,int y)
			{
				if (0 <= x && x < penEdit->wid &&
				    0 <= y && y < penEdit->ht)
					return TRUE;
				else
					return FALSE;
			}
		  // 点をセットする関数
			void setPixel(int x,int y)
			{
				if (InPen(x,y))
				{
					pen_setPixel(penEdit,x,y,gray);
					WGB_RBOXFILL(guiEgbPtr,fr.X+6*x+1, fr.Y+6*y+1, 5,5,
								 grayToColor(gray),0);
					int igray = 255 - gray;
					scrbitmap_setpixel(bmPenEdSample,x,y,igray,igray,igray);
				}
			}
		  // ラバー描画のために点を反転する関数
			void invertPixel(int x,int y)
			{
				WGB_RBOXFILL(guiEgbPtr,fr.X+6*x+1, fr.Y+6*y+1, 5,5,
							 grayToColor(WHITE),4);
			}
		  // マウス座標からペン先パターン内座標へ変換する関数
			POINT convPt(POINT pt)
			  { POINT p = { (pt.x - fr.X) / 6, (pt.y - fr.Y) / 6 };
				return p; }
		  // 左ボタンが押されていたら、イベントループに入る
			if (!(pev->what == EVMOSDN && (pev->shift & SLEFTBTN) != 0))
				goto DONOTHING;
		  // 選択しているツールによって、ループを選択
			if (nPenEditTool == 0 || nPenEditTool == 1)
			{
				int ret;  EVENT *ev;  POINT lastp;
			  // 最初の点に描画
				lastp = convPt(*(POINT*)&pev->info);
				BEGINPAINT(kobj)
				setPixel(lastp.x, lastp.y);
				ENDPAINT
				for (;;)
				{
					int what,shift;  POINT *pt;
					MMI_iosense();
					if ((ret = MMI_GetEvnt(EVMOSDRAG|EVMOSUP,&ev)) == NOERR)
					{
					  // イベント種別、シフト状態、マウス座標を得る
						what = ev->what, shift = ev->shift;
						pt = (POINT *) &ev->info;
					  // マウスボタンが放されたら、自由曲線描画を終了
						if (what!=EVMOSDRAG && (shift&SLEFTBTN)!=0)
							break;
					  // 部品の中でマウスがドラッグされれば描画
						POINT p = convPt(*pt);
						BEGINPAINT(kobj)
						if (nPenEditTool == 0)
							setPixel(p.x,p.y);
						else if (nPenEditTool == 1)
							do_line_cont(lastp.x,lastp.y,p.x,p.y,setPixel);
						ENDPAINT
						pened_drawSample();
						lastp = p;
					}
				}
			  // 次のイベントをキューに積む
				EVENT evbuf;
				evbuf = *ev;
				evbuf.what = EVMOSUP;
				evbuf.shift = (evbuf.shift & (~SRIGHTBTN)) | SLEFTBTN;
				MMI_SetEvnt(&evbuf);
			}
			else if (nPenEditTool == 2 || nPenEditTool == 3 ||
			         nPenEditTool == 4 || nPenEditTool == 5 ||
			         nPenEditTool == 6)
			{
				void rub(int x1,int y1,int x2,int y2)
				{
					switch(nPenEditTool)
					{
					case 2: do_line(x1,y1,x2,y2,invertPixel); break;
					case 3..4: do_boxline(x1,y1,x2,y2,invertPixel); break;
					case 5: case 6:
						do_ellipse(x1,y1,abs(x1-x2),abs(y1-y2),invertPixel);
						break;
					}
				}
				void draw(int x1,int y1,int x2,int y2)
				{
					void h_do(int x1,int x2,int y)
					  { for (int x=x1; x<=x2; x++)  setPixel(x,y); }
					switch(nPenEditTool)
					{
					case 2: do_line(x1,y1,x2,y2,setPixel); break;
					case 3: do_boxline(x1,y1,x2,y2,setPixel); break;
					case 4:	do_boxfill(x1,y1,x2,y2,h_do); break;
					case 5:
						do_ellipse(x1,y1,abs(x1-x2),abs(y1-y2),setPixel);
						break;
					case 6:
						do_ellipsefill(x1,y1,abs(x1-x2),abs(y1-y2),h_do);
						break;
					}
					pened_drawSample();
				}
				EVENT *ev;
				POINT lastp = convPt(*(POINT*)&pev->info);
				POINT cp = lastp;
				for (;;)
				{
					int what,shift;  POINT *pt;
				  // ラバー描画
					BEGINPAINT(kobj)
					rub(lastp.x,lastp.y,cp.x,cp.y);
					ENDPAINT
				  // イベントセンス
					do { MMI_iosense(); }
					   while (MMI_GetEvnt(EVALL, &ev) != NOERR);
				  // ラバー消去
					BEGINPAINT(kobj)
					rub(lastp.x,lastp.y,cp.x,cp.y);
					ENDPAINT
				  // イベント種別、シフト状態、マウス座標を得る
					what=ev->what; shift=ev->shift; pt = (POINT *)&ev->info;
				  // ペン内座標を得る
					cp = convPt(*pt);
				  // 左ボタンがクリックされたら描画
					if (what==EVMOSDN&&(shift&SLEFTBTN)!=0&&InPen(cp.x,cp.y))
					{
						BEGINPAINT(kobj)
						draw(lastp.x,lastp.y,cp.x,cp.y);
						ENDPAINT
						lastp = cp;
						if (nPenEditTool != 2)
							break;
					}
				  // 右ボタンがクリックされたらイベントループ終了
					else if (what == EVMOSDN && (shift & SRIGHTBTN) != 0)
						break;
				}
			  // 次のイベントをキューに積む
				EVENT evbuf;
				evbuf = *ev;
				evbuf.what = EVMOSUP;
				evbuf.shift = (evbuf.shift & (~SRIGHTBTN)) | SLEFTBTN;
				MMI_SetEvnt(&evbuf);
			}
			DONOTHING: ;
		}
		return NOERR ;
	}

	int	PenEdSampleWinProc(int kobj,int messId,int argc,EVENT* pev,int trigger)
	// initDataZPENSEL:idPenEdSampleWin:MJ_WINDOWL40の呼び出し関数
	{
		if (messId == MM_SHOW)
			pened_drawSample();
		return NOERR ;
	}

	int	penedTICONtoolFunc(int kobj,int messId,int argc,EVENT*pev,int trigger)
		// initDataPENSEL:idPenEdToolTIcon[0..4]:MJ_TICONL40の呼び出し関数
	{
		RM_pushRadioButton(kobj, idPenEdDlg, idPenEdToolTIcon,
						   INTNUM(idPenEdToolTIcon), &nPenEditTool);
		return NOERR ;
	}

		/*	initDataPENSEL:penedDBTNok:MJ_DBUTTONL40の呼び出し関数	*/
	int	penedDBTNokFunc(int kobj)
	{
		pened_ret = NOERR;
		MMI_SetHaltFlag(TRUE);
		return NOERR ;
	}

		/*	initDataPENSEL:penedDBTNcancel:MJ_DBUTTONL40の呼び出し関数	*/
	int	penedDBTNcancelFunc(int kobj)
	{
		pened_ret = -1;
		MMI_SetHaltFlag(TRUE);
		return NOERR ;
	}

		/*	initDataPENSEL:penedSBARedit_hori:MJ_SCRLL40の呼び出し関数	*/
		/*	initDataPENSEL:penedSBARedit_vert:MJ_SCRLL40の呼び出し関数	*/
	int	penedSBAReditFunc(kobj)
	int		kobj ;
	{
		return NOERR ;
	}

	int penedSBARgrayFunc(void)
	{
		int ptr,a;
		static char numbuf[10];
		MMI_SendMessage( idPenEdGraySBar, MM_GETSCROLL, 5, &ptr,&a,&a,&a,&a);
		sprintf(numbuf, "%3d", ptr);
		MMI_SendMessage( idPenEdGrayNumMsg, MM_SETMSG, 1, numbuf );
		MMI_SendMessage( idPenEdGrayNumMsg, MM_SHOW, 0 );
		return NOERR ;
	}

		/*	initDataPENSEL:penedDBTNsize:MJ_DBUTTONL40の呼び出し関数	*/
	int	penedDBTNsizeFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		return NOERR ;
	}

int EditPen(int penidx)
// penidx 番目のペンを編集する
{
	Pen pen;
	if (penlist_makeDummy(penidx) != NOERR)
		return -1;
	list_moveTo(penList, penidx);
	list_getData(penList, &pen);
	penEdit = pen_createCopy(pen);
	if ((bmPenEdSample = scrbitmap_new(penEdit->wid,penEdit->ht)) == NULL)
		goto END;
	scrbitmap_clear(bmPenEdSample);
	int i,j;
	char *p = penEdit->buf;
	for (i=0; i<penEdit->ht; i++)
		for (j=0; j<penEdit->wid; j++,p++)
			scrbitmap_setpixel(bmPenEdSample,j,i,255-*p,255-*p,255-*p);
	RM_setScrollPos(idPenEdGraySBar, 255, FALSE);
	MMI_SendMessage(idPenEdGrayNumMsg, MM_SETMSG, 1, "255");

	RM_moveCenter(idPenEdDlg);
	MMI_SendMessage(idPenEdDlg, MM_ATTACH, 1, idDesktopAlertHyper);
	MMI_SendMessage(idPenEdDlg, MM_SHOW, 0);
	MMI_ExecSystem();
	MMI_SendMessage(idPenEdDlg, MM_ERASE, 0);
	MMI_SendMessage(idPenEdDlg, MM_DETACH, 0);
END:
	if (bmPenEdSample != NULL)
		scrbitmap_delete(bmPenEdSample);
	if (pened_ret == NOERR)
	{
		pen_destroy(pen);
		list_moveTo(penList, penidx);
		list_setData(penList, &penEdit);
	}
	else
	{
		pen_destroy(penEdit);
	}
	return NOERR;
}

/*--------------------------------------------------------*/
/*                  ペン先選択ダイアログ                  */
/*--------------------------------------------------------*/

static int save_penlist(void)
{
	static char *extstr[] = {"*.*",NULL};
	int atr,ret,i;
	unsigned int select_cnt;
	char pathname[80];
  /* ファイルダイアログのタイトル、表示位置を設定 */
	FDG_SetTitle("ペンデータ保存", "保存", "取消");
	RM_moveCenter(FDG_GetMainID());
  /* ファイルダイアログの表示 */
	ret = FDG_DspFileDlg(idDesktopFileDlgHyper,
						 FDG_TEXT,NULL,extstr,&select_cnt);
  /* 「実行」が押されたならファイル名を取得 */
	if (ret)
		FDG_GetPathName(pathname, &atr, 0);
  /* ペン先データの保存 */
	if (ret)
		_do_savePenData(pathname);
  /* 終了 */
	if (ret)
		return 0;
	else
		return -1;
}

static int load_penlist(void)
{
	static char *extstr[] = {"*.*",NULL};
	int atr,ret,i;
	unsigned int select_cnt;
	char pathname[80];
  /* ファイルダイアログのタイトル、表示位置を設定 */
	FDG_SetTitle("ペンデータ読込", "保存", "取消");
	RM_moveCenter(FDG_GetMainID());
  /* ファイルダイアログの表示 */
	ret = FDG_DspFileDlg(idDesktopFileDlgHyper,
						 FDG_TEXT,NULL,extstr,&select_cnt);
  /* 「実行」が押されたならファイル名を取得 */
	if (ret)
		FDG_GetPathName(pathname, &atr, 0);
  /* ペン先データの読み込み */
	if (ret)
		_do_loadPenData(pathname);
  /* 終了 */
	if (ret)
		return 0;
	else
		return -1;
}

/*--------------------------------------------------------*/
/*         ペン先選択ダイアログ・リスト表示の更新         */
/*--------------------------------------------------------*/

static void pensel_updateListDisp(void)
{
	int idWin = idPenSelSampleListWin;
	BEGINPAINT(idWin)
	FRAME fr;  RM_getWinUserFrame(idWin,&fr);
	WGB_BOXFILL(guiEgbPtr,fr.X,fr.Y,fr.X2,fr.Y2,RMcol(WHITE),0);
	int ptr = RM_getScrollPos(idPenSelSBar);
	list_moveTo(penList, PENSEL_XNUM * ptr);
	int i,j,cnt;
	cnt = 0;
	for (i=0; i<PENSEL_YNUM; i++)
	{
		for (j=0; j<PENSEL_XNUM; j++, list_next(penList),cnt++)
		{
			Pen pen;
			if (list_isOut(penList))
				goto END;
			list_getData(penList, &pen);
			DrawPenSample(idWin, 36*j+1, 36*i+1, pen);
		}
	}
  END:
  /* ペンリスト選択カーソル描画 */
	FRAME sel;
	if (getPenListPosition(PENSEL_XNUM * list_y + list_x, &sel) == 0)
	{
	 WGB_RBOXLINE(guiEgbPtr,sel.X,sel.Y,sel.WID,sel.HT,RMcol(BLACK), 0);
	 WGB_RBOXLINE(guiEgbPtr,sel.X+1,sel.Y+1,sel.WID-2,sel.HT-2,
				  RMcol(BLACK),0);
	}
  // 描画終了
	ENDPAINT
}

/*--------------------------------------------------------*/
/*           ペン先選択ダイアログ・部品実行関数           */
/*--------------------------------------------------------*/

	int	PenSelSampleListWinProc(kobj, messId, argc, pev, trigger)
	/*	initDataZPENSEL:idPenSelSampleListWin:MJ_WINDOWL40の呼び出し関数	*/
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		if (messId == MM_SHOW)
			pensel_updateListDisp();
		else if (messId == MM_MOUSEON)
		{
			POINT pt = *(POINT*)&pev->info;
			FRAME frUser;
			RM_getWinUserFrame(kobj, &frUser);
			int ix,iy;
			ix = (pt.x - frUser.X) / 36;
			iy = (pt.y - frUser.Y) / 36;
			if (ix < 0)  ix = 0;
			else if (ix >= PENSEL_XNUM)  ix = PENSEL_XNUM-1;
			if (iy < 0)  iy = 0;
			else if (iy >= PENSEL_YNUM)  iy = PENSEL_YNUM-1;
			list_x = ix;
			list_y = RM_getScrollPos(idPenSelSBar) + iy;
			nSamplePen[nSelectPen] = list_y * PENSEL_XNUM + list_x;
			RM_setClipVisibleAllScr();
			RM_setOriginZero();
			MMI_SendMessage( idPenSelSelectWin[nSelectPen], MM_SHOW, 0);
			MMI_SendMessage( idPenSelSampleListWin, MM_SHOW, 0);
			RM_recoverOrigin();
			RM_recoverClipVisible();
		}
		return NOERR ;
	}

	int	PenSelSelectWinProc(int kobj,int messId,int argc,EVENT* pev,int trig)
	// initDataZPENSEL:idPenSelSelectWin[0..3]:MJ_WINDOWL40の呼び出し関数
	{
		int i;
		for (i = 0; i < INTNUM(idPenSelSelectWin); i++)
			if (kobj == idPenSelSelectWin[i])
				goto FOUND;
		return NOERR;
	  FOUND:
		if (messId == MM_SHOW)
		{
			Pen pen;
			list_moveTo(penList, nSamplePen[i]);
			FRAME fr;
			RM_getWinUserFrame(kobj, &fr);
			WGB_BOXFILL(guiEgbPtr,fr.X,fr.Y,fr.X2,fr.Y2,RMcol(WHITE),0);
			if (list_getData(penList, &pen) == 0)
				DrawPenSample(kobj, 0,0, pen);
			if (i == nSelectPen)
			{
				BEGINPAINT(kobj)
				WGB_BOXLINE(guiEgbPtr,fr.X,fr.Y,fr.X2,fr.Y2,RMcol(BLACK),0);
				WGB_BOXLINE(guiEgbPtr,fr.X+1,fr.Y+1,fr.X2-1,fr.Y2-1,
							RMcol(BLACK),0);
				ENDPAINT
			}
		}
		else if (messId == MM_MOUSEON)
		{
			int oldx = nSelectPen;
			nSelectPen = i;
			list_x = nSamplePen[nSelectPen] % PENSEL_XNUM;
			list_y = nSamplePen[nSelectPen] / PENSEL_XNUM;
			RM_setOriginZero();
			RM_setClipVisibleAllScr();
			MMI_SendMessage( idPenSelSelectWin[oldx], MM_SHOW, 0);
			MMI_SendMessage( idPenSelSelectWin[nSelectPen], MM_SHOW, 0);
			MMI_SendMessage( idPenSelSampleListWin, MM_SHOW, 0);
			RM_recoverClipVisible();
			RM_recoverOrigin();
		}
		return NOERR ;
	}

		/*	initDataPENSEL:idPenSelSBar:MJ_SCRLL40の呼び出し関数	*/
	int	penselSBARFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		pensel_updateListDisp();
		return NOERR ;
	}

		/* initDataPENSEL:penselTICONconc:MJ_TICONL40の呼び出し関数 */
	int	penselTICONconcFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		return NOERR ;
	}

		/*	initDataPENSEL:penselICONerase:MJ_ICONL40の呼び出し関数	*/
	int	penselICONeraseFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		MMI_SetHaltFlag(TRUE);
		return NOERR ;
	}
	
		/*	initDataPENSEL:penselDBTNedit:MJ_DBUTTONL40の呼び出し関数	*/
	int	penselDBTNeditFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		int n;
		n = PENSEL_XNUM * list_y + list_x;
		MMI_SendMessage(idPenSelDlg, MM_ERASE, 0);
		MMI_SendMessage(idPenSelDlg, MM_DETACH, 0);
		EditPen(n);
		pensel_updateSBar(FALSE);
		MMI_SendMessage(idPenSelDlg, MM_ATTACH, 1, idDesktopAlertHyper);
		WINCLIP *clip;
		WIN_beginUpDateObj(idPenSelDlg, &clip);
		MMI_SendMessage(idPenSelDlg, MM_SHOW, 0);
		WIN_endUpDateObj(clip);
		return NOERR ;
	}

		/*	initDataPENSEL:penselDBTNend:MJ_DBUTTONL40の呼び出し関数	*/
	int	penselDBTNendFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		MMI_SetHaltFlag(TRUE);
		return NOERR ;
	}

		/*	initDataPENSEL:penselDBTNsave:MJ_DBUTTONL40の呼び出し関数	*/
	int	penselDBTNsaveFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
	  /* ペン選択ダイアログの消去 */
		MMI_SendMessage(idPenSelDlg, MM_ERASE, 0);
		MMI_SendMessage(idPenSelDlg, MM_DETACH, 0);
	  /* ペンデータファイルの保存 */
		save_penlist();
	  /* ペン選択ダイアログの表示 */
		MMI_SendMessage(idPenSelDlg, MM_ATTACH, 1, idDesktopAlertHyper);
		MMI_SendMessage(idPenSelDlg, MM_SHOW, 0);
		return NOERR ;
	}

		/*	initDataPENSEL:penselDBTNload:MJ_DBUTTONL40の呼び出し関数	*/
	int	penselDBTNloadFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
	  /* ペン選択ダイアログの消去 */
		MMI_SendMessage(idPenSelDlg, MM_ERASE, 0);
		MMI_SendMessage(idPenSelDlg, MM_DETACH, 0);
	  /* ペンデータファイルの読み込み */
		load_penlist();
	  /* ペン選択ダイアログの表示 */
		MMI_SendMessage(idPenSelDlg, MM_ATTACH, 1, idDesktopAlertHyper);
		MMI_SendMessage(idPenSelDlg, MM_SHOW, 0);
		return NOERR ;
	}

/*--------------------------------------------------------*/
/*         現在選択しているペン先のパターンを返す         */
/*--------------------------------------------------------*/

static char _pat[] =
{
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0, 40, 40, 40, 40, 40,  0,  0,  0,  0,  0,
	  0,  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,  0,
	  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,
	  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,
	  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,
	  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,
	  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,
	  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,
	  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,
	  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,
	  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,
	  0,  0,  0, 40, 40, 40, 40, 40, 40, 40, 40, 40,  0,  0,  0,
	  0,  0,  0,  0,  0, 40, 40, 40, 40, 40,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

Pen pensel_curpen(void)
{
	Pen pen;
	if (penlist_makeDummy(nSamplePen[nSelectPen]) != NOERR)
		return pen_new(32,32);
	list_moveTo(penList, nSamplePen[nSelectPen]);
	list_getData(penList, &pen);
	return pen;
}

void	pensel_getPattern(char **buf,int *wid,int *ht,int *ofsx,int *ofsy)
/* 濃度分布領域の先頭ポインタを返す(濃度は一要素１バイト、0〜255) */
/* 同時に、ペン先の大きさと、基準点へのオフセットを返す */
/* 濃度分布や大きさやオフセットは、呼ばれるたびに変わるかもしれない */
{
	Pen pen;
	list_moveTo(penList, nSamplePen[nSelectPen]);
	if (list_getData(penList, &pen) == 0)
	{
		pen_getPattern(pen, buf, wid, ht);
		if (wid!=NULL) *ofsx = *wid / 2;
		if (ht!=NULL)  *ofsy = *ht / 2;
	}
	else
	{
		if (buf!=NULL)
			*buf = _pat;
		if (wid!=NULL)
			*wid = 15;
		if (ht!=NULL)
			*ht = 15;
		if (ofsx!=NULL)
			*ofsx = 7;
		if (ofsy!=NULL)
			*ofsy = 7;
	}
}

void	pen_getImage(char *buf,int wid,int ht, int pennum, int atr)
/*
	ペン先

*/
{
}
