/*===========================================
          DolphMorph（ドルフモーフ）

      モーフィング＆変形アニメ作成ソフト

  モーフィングアルゴリズム: EAST 1994
  インターフェース作成:     松内 良介 1994
===========================================*/
#define	MODULE_POINTS
/*
	モジュール points.c

	操作点ウィンドウに関する実現部

			int		init_points(void)
			void	end_points(void)

		●操作点構造体の生成／消滅
	static	CPOINT	*cpoint_new(int type, int x, int y)
	static	void	cpoint_delete(CPOINT *pcp)

		●表示画像、操作点に関する座標取得／チェック
			void	points_whereis(int scrx, int scry, int *side, int *n)
	static	void	getImageFrame(int side, FRAME *fr)
	static	int		checkOnImage(int scrx, int scry, int *imgx, int *imgy)
	static	void	getPointXY(int side, int num, int *scrx, int *scry)
	static	int		checkOnPoint(int side, int imagex, int imagey,
								 int *pDx, int *pDy)

		●操作点、Ａ／Ｂ画像の表示
	static	void	setClipImage(int side)
	static	void	_drawPoint(int side, int n, int mode)
	static	void	_drawRubber(int side,int n, int flag, int mode)
	static	void	dispPoints(void)
	static	void	dispImages(void)

		●指定した操作点の作成／移動／消去
	static	void	makeControlPoint(int type, int imgx, int imgy)
	static	void	moveControlPoint(int side,int num,int dx,int dy)
	static	void	deleteControlPoint(int side,int num)

		●操作点の作成のイベントループ
	static	void	points_makeNewPoints(EVENT *pev)

		●操作点ウィンドウへの画像の登録
			void	points_storeImage(int side, IMAGE *im)

		●モーフィング処理用の通信関数
	static	void	dispXY2imageXY(int dispx,int dispy,int dispwid,int dispht,
							   int imagewid, int imageht, int *ix,int *iy)
			int		points_makeMorphPoints(LIST *plPOINT, LIST *plLINE)
			int		points_checkMorphImages(void)
			void	points_getImageSize(int *pwid,int *pht)
			int		morphGetFromPixel(fxp x, fxp y, int *r,int *g,int *b)
			int		morphGetToPixel(fxp x, fxp y, int *r,int *g,int *b)

		●デスクトップメニューから呼び出される関数
			int		points_checkLoadPoints(void)
			void	points_loadPoints(void)
			int		points_checkSavePoints(void)
			void	points_savePoints(void)
			int		points_checkClearPoints(void)
			void	points_clearPoints(void)
			void	points_loadImage(int side)

		●操作点設定ウィンドウ上の部品から呼び出される関数
			int		PointsWinFunc(kobj, messId, argc, pev, trigger)
			int		PointsTypeTIconFunc(kobj, messId, argc, pev, trigger)
			int		PointsCommandTIconFunc(kobj, messId, argc, pev, trigger)
			int		PointsEditDBtnFunc(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 <msdos.cf>
#include <file_dlg.h>

#include <ryosuke.h>
#include <usrlib.h>

#include "morph.h"
#include "desktop.h"
#include "points.h"
#include "wgbmac.h"
#include "guisub.h"
#include "image.h"
#include "fifo.h"
#include "domorph.h"
#include "imstore.h"
#include "morphgo.h"
#include "alert.h"
#include "sub.h"

/*--------------------------------------------------------*/
/*                        部品ＩＤ                        */
/*--------------------------------------------------------*/

	int	idPointsWin = -1 ;
	int	idPointsTitleDBtn = -1 ;
	int	idPointsTitleMsg = -1 ;
	int	idPointsTypeTIcon[2] = -1 ;
	int	idPointsCommandTIcon[3] = -1 ;
	int	idPointsEditDBtn[6] = -1 ;
	int	idPointsEditMsg[6] = -1 ;
	int	idPointsDarkTIcon[2] = -1 ;
	int	idPointsDarkMsg[2] = -1 ;

/*--------------------------------------------------------*/
/*                 モジュール内定数・変数                 */
/*--------------------------------------------------------*/

  /* 操作点ウィンドウ内での画像の位置 */
	static int IMAGEX[2] = {48,48};
	static int IMAGEY[2] = {68,274};

  /* 操作点の種別 */
	#define	CPOINT_POINT	0
	#define	CPOINT_LINE		1
	#define	CPOINT_QUAD		2

  /* 操作点をあらわす構造体 */
	typedef struct {
		int		x[2],y[2];	/* Ａ側、Ｂ側それぞれの座標 */
		int		type;		/* CPOINT_POINT, ..LINE,..QUAD */
		int		c1,c2;
				/* ↑接続している操作点の番号:
						CPOINT_POINT の場合 c1, c2 は無意味、
						CPOINT_LINE の場合、始点で c1=-1, 終点で c2=-1
						CPOINT_QUAD の場合、点１で c1=-1, 点４で c2=-1 */
	} CPOINT;	/* 操作点（control point） */

  /* 操作点リスト */
	LIST *plPoints = NULL;
		#define	CP_NUM			list_getDataNum(plPoints)
		#define	CP_GETDATA(n,p) \
			{ list_moveTo(plPoints,(n)); list_getData(plPoints,(p)); }
		static int CP_INSERT(int n, CPOINT **p)
		 { list_moveTo(plPoints,n);  return list_insertData(plPoints,p); }
	int curPoint = 0;	/* 現在選択中の操作点の番号 */

  /* 操作点設定ウィンドウ内の画像の大きさ */
	#define	IMAGEWIDTH	240
	#define	IMAGEHEIGHT	180
  /* 操作点設定ウィンドウ内の画像を表す構造体 */
  /* [0]:Ａ側  [1]:Ｂ側 */
	static IMAGE *piOriginal[2] = {NULL,NULL};	// オリジナル画像
	static IMAGE *piDisplay[2] = {NULL,NULL};	// 表示用画像
  /* 操作点ウィンドウ上で選んでいる「操作点タイプ」 */
	static int pointType;
  /* 操作点ウィンドウ上で選んでいる「操作点コマンド」 */
	static int pointCommand;
  /* CPOINT_LINE の場合、現在どの操作点を始点としているか */
	static int nFromPoint = -1;

	static void points_checkActivity(int bRedraw);

/*--------------------------------------------------------*/
/*                モジュールの初期化・終了                */
/*--------------------------------------------------------*/

	int	init_points(void)
	{
		int i;
		for (i=0; i<2; i++)
		{
			if ((piDisplay[i] = image_new(IMAGEWIDTH/2,IMAGEHEIGHT/2)) == NULL)
				return -1;
		}
		points_checkActivity(FALSE);
		pointType = 1;
		RM_initRadioButton(idPointsTypeTIcon,
						   INTNUM(idPointsTypeTIcon), &pointType);
		pointCommand = 0;
		RM_initRadioButton(idPointsCommandTIcon,
						   INTNUM(idPointsCommandTIcon), &pointCommand);
		plPoints = list_new(sizeof(CPOINT*));
		return 0;
	}

	void end_points(void)
	{
		list_destroy(plPoints);
	}

/*--------------------------------------------------------*/
/*        ウィンドウ上のボタンの有効／無効チェック        */
/*--------------------------------------------------------*/

	static void points_checkActivity(int bRedraw)
	{
		int i;
		for (i=0; i<2; i++)
		{
			WINCLIP *pwclip;
			if (piOriginal[i] == NULL)
			{
				MMI_SendMessage(idPointsDarkTIcon[i], MM_ENABLE, 1, FALSE);
				RM_setChColor(idPointsDarkMsg[i], GRAY);
			}
			else
			{
				MMI_SendMessage(idPointsDarkTIcon[i], MM_ENABLE, 1, TRUE);
				RM_setChColor(idPointsDarkMsg[i], BLACK);
			}
			if (bRedraw)
			{
				WIN_beginUpDateObj(idPointsDarkTIcon[i], &pwclip);
				MMI_SendMessage(idPointsDarkTIcon[i], MM_SHOW, 0);
				MMI_SendMessage(idPointsDarkMsg[i], MM_SHOW, 0);
				WIN_endUpDateObj(pwclip);
			}
		}
	}

/*--------------------------------------------------------*/
/*                      操作点構造体                      */
/*--------------------------------------------------------*/

	static CPOINT *cpoint_new(int type, int x, int y)
	{
		CPOINT *pcp;
		if ((pcp = TL_calloc(1,sizeof(CPOINT))) == NULL)
			return NULL;
		pcp->type = type;
		pcp->x[0] = pcp->x[1] = x;
		pcp->y[0] = pcp->y[1] = y;
		pcp->c1 = pcp->c2 = -1;
		return pcp;
	}

	static void cpoint_delete(CPOINT *pcp)
	{
		TL_free(pcp);
	}

/*--------------------------------------------------------*/
/*           画像上であるかどうかの座標チェック           */
/*--------------------------------------------------------*/

	void points_whereis(int scrx, int scry, int *side, int *n)
	// 返値 side: 0=Ａ側  1=Ｂ側  -1=どちらでもない
	//      n:    0=画像内  -1=画像外
	{
		EVENT ev;
		ev.what = EVMOSDN;
		ev.shift = SLEFTBTN;
		((POINT*)&ev.info)->x = scrx;
		((POINT*)&ev.info)->y = scry;
		int id;
		id = MMI_SendMessage(idDesktopSelectiveHyper, MM_ONPARTS, 1, &ev);
		if (id != idPointsWin)
			goto NOWHERE;
		FRAME fr;
		RM_getFrame(idPointsWin, &fr);
		int i;
		for (i=0; i<2; i++)
		{
			int ix,iy;
			ix = fr.lupx + IMAGEX[i];
			iy = fr.lupy + IMAGEY[i];
			if (ix <= scrx && scrx < ix + IMAGEWIDTH &&
				iy <= scry && scry < iy + IMAGEHEIGHT)
			{
				int wid,ht;
				if (piOriginal[i] == NULL)
					wid = 0, ht = 0;
				else
					image_getDispSize(piOriginal[i], IMAGEWIDTH, IMAGEHEIGHT,
									  &wid, &ht);
				if (ix <= scrx && scrx < ix+wid && iy <= scry && scry < iy+ht)
					{ *side = i;  *n = 0;  return; }
				else
					{ *side = i;  *n = -1;  return; }
			}
		}
	   NOWHERE:;
		*side = -1;
		*n = -1;
	}

	static void getImageFrame(int side, FRAME *fr)
	{
		if (fr == NULL)
			return;
		RM_getFrame(idPointsWin, fr);
		fr->lupx += IMAGEX[side];
		fr->lupy += IMAGEY[side];
		fr->rdwx = fr->lupx + IMAGEWIDTH - 1;
		fr->rdwy = fr->lupy + IMAGEHEIGHT - 1;
	}

	static int checkOnImage(int scrx,int scry,int *pimgx,int *pimgy)
	/* -1:画像外  0:画像Ａ　１：画像Ｂ */
	/* 返値: *pimgx,*pimgy : 画像内での画面座標 */
	{
		FRAME fr;
		RM_getFrame(idPointsWin, &fr);
		int i;
		for (i=0; i<2; i++)
		{
			int wid,ht;
			if (piOriginal[i] == NULL)
			  wid = 0, ht = 0;
			else
			  image_getDispSize(piOriginal[i],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
			if (fr.lupx+IMAGEX[i] <= scrx && scrx < fr.lupx+IMAGEX[i]+wid &&
				fr.lupy+IMAGEY[i] <= scry && scry < fr.lupy+IMAGEY[i]+ht)
			{
				*pimgx = scrx - (fr.lupx+IMAGEX[i]);
				*pimgy = scry - (fr.lupy+IMAGEY[i]);
				return i;
			}
		}
		return -1;
	}

	#define	MAXDIF	4		/* ±MAXDIF 以内の座標なら「操作点の上」とみなす */

	static void getPointXY(int side, int num, int *scrx, int *scry)
	// ある操作点の、画面上での座標を求める。
	{
		FRAME fr;
		CPOINT *pcp;
		RM_getFrame(idPointsWin, &fr);
		list_moveTo(plPoints, num);
		list_getData(plPoints, &pcp);
		*scrx = fr.lupx + IMAGEX[side] + pcp->x[side];
		*scry = fr.lupy + IMAGEY[side] + pcp->y[side];
	}

	static int checkOnPoint(int side, int imagex, int imagey, int *pDx, int *pDy)
	{
		int n;
		for (list_top(plPoints),n=0; !list_isOut(plPoints);
			 list_next(plPoints),n++)
		{
			CPOINT *pcp;
			list_getData(plPoints, &pcp);
			if (pcp->x[side]-4 <= imagex && imagex <= pcp->x[side]+4 &&
			    pcp->y[side]-4 <= imagey && imagey <= pcp->y[side]+4)
			{
				*pDx = pcp->x[side] - imagex;
				*pDy = pcp->y[side] - imagey;
				return n;
			}
		}
		return -1;
	}

/*--------------------------------------------------------*/
/*                      操作点の表示                      */
/*--------------------------------------------------------*/

	static void setClipImage(int side)
	{
		int wid,ht;
		if (piOriginal[side] != NULL)
		  image_getDispSize(piOriginal[side],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
		else
		  wid = IMAGEWIDTH, ht = IMAGEHEIGHT;
		FRAME fr;
		RM_getFrame(idPointsWin, &fr);
		fr.lupx = fr.lupx + IMAGEX[side];
		fr.lupy = fr.lupy + IMAGEY[side];
		fr.rdwx = fr.lupx + wid - 1;
		fr.rdwy = fr.lupy + ht - 1;
		RM_setClipAnyFrame(idPointsWin, &fr);
	}

	static char grpPoint[] =
	// 9×9ドット、透過色０
	{
		0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00,
		0x00,0xf8,0xff,0x08,0x00,0x00,0x00,0x00,
		0x80,0xff,0xff,0x8f,0x00,0x00,0x00,0x00,
		0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
		0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
		0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
		0x80,0xff,0xff,0x8f,0x00,0x00,0x00,0x00,
		0x00,0xf8,0xff,0x08,0x00,0x00,0x00,0x00,
		0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00
	};

	static char grpPoint2[] =
	// 選択中の操作点。9×9ドット、透過色０
	{
		0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00,
		0x00,0xa8,0xaa,0x08,0x00,0x00,0x00,0x00,
		0x80,0xaa,0xaa,0x8a,0x00,0x00,0x00,0x00,
		0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
		0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
		0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
		0x80,0xaa,0xaa,0x8a,0x00,0x00,0x00,0x00,
		0x00,0xa8,0xaa,0x08,0x00,0x00,0x00,0x00,
		0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00
	};

	static FRAME _frWin;

	#define	SX(side,x)		(_frWin.lupx + IMAGEX[side] + (x))
	#define	SY(side,y)		(_frWin.lupy + IMAGEY[side] + (y))

	static void _dispPoints_init(void)
	{
		RM_getFrame(idPointsWin, &_frWin);
	}

	#define	DRAW_NORMAL		0
	#define	DRAW_XOR		1
	#define	DRAW_ERASE		2

	static void _drawPoint(int side, int n, int mode)
	{
		if (n < 0 || CP_NUM <= n)
			return;
		CPOINT *cp;
		CP_GETDATA(n, &cp);
		int x,y;
		char *grp;
		x = SX(side, cp->x[side]);
		y = SY(side, cp->y[side]);
		grp = (n == curPoint ? grpPoint2 : grpPoint);
		if (mode == DRAW_NORMAL)
		{
			WGB_PUTBLOCK_MATTE(guiEgbPtr, grp, x-4,y-4, 9,9);
		}
		else if (mode == DRAW_XOR)
		{
			WGB_PUTBLOCK(guiEgbPtr, grp, x-4,y-4, 9,9, XOR);
		}
		else if (mode == DRAW_ERASE)
		{
			WGB_RBOXFILL(guiEgbPtr, x-4,y-4, 9,9, 0,0);
		}
	}

	#define	RUB_PREV	1
	#define	RUB_NEXT	2

	static void _drawRubber(int side,int n,int flag,int mode)
	// flag:RUB_PREV, RUB_NEXT
	// mode:0=消去  1=描画
	{
		if (n < 0 || CP_NUM <= n)
			return;
		CPOINT *cp,*cp2;
		CP_GETDATA(n, &cp);
		if (cp->type != CPOINT_LINE)
			return;
		int i;
		for (i=0; i<2; i++)
		{
			if ((i == 0 ? ((flag&RUB_PREV)!=0 && cp->c1 >= 0) :
						  ((flag&RUB_NEXT)!=0 && cp->c2 >= 0)))
			{
				CP_GETDATA((i == 0 ? cp->c1 : cp->c2), &cp2);
				if (cp2 != NULL)
				{
					#define	X(pCp)		SX(side, (pCp)->x[side])
					#define	Y(pCp)		SY(side, (pCp)->y[side])
					if (mode == DRAW_NORMAL)
					 { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),RED,0); }
					else if (mode == DRAW_XOR)
					 { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),RED,XOR); }
					else if (mode == DRAW_ERASE) /* ?? */
					 { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),0,0); }
					#undef Y
					#undef X
				}
			}
		}
	}

	static void dispPoints(void)
	{
		int i;
		MG_mosDisp(2);
		RM_setOriginZero();
		_dispPoints_init();
		for (i=0; i<2; i++)
		{
		  /* いったんすべての操作点を消す */
			int wid,ht;
			image_getDispSize(piOriginal[i],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
			if (wid == 0 || ht == 0)
				continue;
			setClipImage(i);
			WGB_RBOXFILL(guiEgbPtr, SX(i,0), SY(i,0), wid, ht, 0, 0);
		  /* 線分操作点の連結線を描画 */
			int n;
			for (n=0; n<CP_NUM; n++)
				_drawRubber(i, n, RUB_NEXT, DRAW_NORMAL);
		  /* 操作点を描画 */
			for (n=0; n<CP_NUM; n++)
				_drawPoint(i, n, DRAW_NORMAL);
			RM_recoverClipVisible();
		}
		RM_recoverOrigin();
		MG_mosDisp(3);
	}

	#undef SX
	#undef SY

/*--------------------------------------------------------*/
/*              操作点ウィンドウ内の画像表示              */
/*--------------------------------------------------------*/

	static void dispImages(void)
	{
		static char *msg = "画像が読み込まれていません";
		#define	SX	((IMAGEWIDTH-12*13)/2)
		#define	SY	((IMAGEHEIGHT-12)/2)
		FRAME fr;
		MG_mosDisp(2);
		RM_getFrame(idPointsWin, &fr);
		RM_setOriginZero();
		WINCLIP *pwc;
		RM_setClipWinUser(idPointsWin, &pwc);
		int i;
		for (i=0; i<2; i++)
		{
			int x,y;
			x = fr.lupx + IMAGEX[i];
			y = fr.lupy + IMAGEY[i];
			WGB_RBOXFILL(guiEgbPtr,x+IMAGEWIDTH-6*12,y+IMAGEHEIGHT+2,
						 6*12,12,WINBACK,0);
			WGB_RBOXFILL(guiEgbPtr,x,y-2-12,6*12,12,WINBACK,0);
			if (piOriginal[i] != NULL)
			{
				image_disp(piDisplay[i],x,y,IMAGEWIDTH, IMAGEHEIGHT);
				if (i==0)
				{
					char msg[40];
					sprintf(msg,"↑(%d×%d)",
							piOriginal[i]->virwid,piOriginal[i]->virht);
					RM_putstring12(guiEgbPtr,x+IMAGEWIDTH-6*strlen(msg),
								   y+IMAGEHEIGHT+2, msg, BLACK, 0);
				}
				else
				{
					char msg[40];
					sprintf(msg,"(%d×%d)↓",
							piOriginal[i]->virwid,piOriginal[i]->virht);
					RM_putstring12(guiEgbPtr,x,y-2-12,msg, BLACK, 0);
				}
			}
			else
			{
				WGB_RBOXFILL(guiEgbPtr,x,y,IMAGEWIDTH,IMAGEHEIGHT,WINBACK, 0);
				WGB_RBOXLINE(guiEgbPtr,x,y,IMAGEWIDTH,IMAGEHEIGHT,BLACK, 0);
				RM_putstring12(guiEgbPtr,x+SX,y+SY,msg, BLACK,0);
			}
		}
		RM_resetClipWinUser(pwc);
		RM_recoverOrigin();
		dispPoints();
		MG_mosDisp(3);
		#undef SX
		#undef SY
	}

/*--------------------------------------------------------*/
/*           操作点の作成／移動／削除のサブ処理           */
/*--------------------------------------------------------*/

  /* 操作点の作成 */

	static int makeControlPoint(int type, int imgx, int imgy)
	/*
		タイプ type (CPOINT_POINT / CPOINT_LINE) の操作点を
		画像上の表示座標(imgx,imgy) の位置に作成し、
		画面表示をそれにあわせて更新する。
		返値: 作成した操作点の番号 (失敗時 -1)
	*/
	{
		CPOINT *pcp;
		if ((pcp = cpoint_new(type,imgx,imgy)) == NULL)
		{
			alert_noMemory("操作点の作成");
			return -1;
		}
		int n = CP_NUM;
		CP_INSERT(n, &pcp);
		curPoint = n;
		if (type == CPOINT_LINE)
		{
			if (nFromPoint >= 0)
			{
				CPOINT *pcp2;
				CP_GETDATA(nFromPoint, &pcp2);
				pcp2->c2 = n, pcp->c1 = nFromPoint;	// 線分操作点のリンク
			}
			nFromPoint = n;
		}
		dispPoints();
		return n;
	}

  /* 操作点の移動 */

	static void moveControlPoint(int side,int num,int dx,int dy)
	/* side,num: Ａ／Ｂ選択と、操作点番号 */
	/* (dx,dy)＝マウス座標から見た操作点の固定変位 */
	/* 呼ばれるときにはマウスカーソルは表示されていること */
	{
		int moscsr;
		EVENT *pev;
		RM_setOriginZero();
		setClipImage(side);
	  /* カレント操作点を、クリックした操作点に設定、画面更新 */
		curPoint = num;
		dispPoints(); /* もっと効率よい画面更新はないか？ */
		MG_mosDisp(2);
		_dispPoints_init();
		_drawPoint(side, num, DRAW_ERASE);
		_drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_ERASE);
		MG_PushPtr(MOSICON_PICK, &moscsr);
		MG_mosDisp(3);
	  /* ドラッグしている間のループ */
		do {
			int msx,msy;
			MG_mosDisp(2);
			_drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_XOR);
			_drawPoint(side, num, DRAW_XOR);
			MG_mosDisp(3);
			do {
				MMI_iosense() ;
			} while ((MMI_GetEvnt(EVMOSDRAG|EVMOSUP, &pev)) < NOERR);
			MG_mosDisp(2);
			_drawPoint(side,num,DRAW_XOR);
			_drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_XOR);
			MG_mosDisp(3);
			msx = *((short *)&(pev->info)) ;
			msy = *(((short *)&(pev->info)) + 1) ;
			if (pev->what == EVMOSDRAG)
			{
				int imx,imy;
				if (checkOnImage(msx,msy,&imx,&imy) == side)
				{
				  /* 操作点をマウスにあわせ移動 */
					CPOINT *pcp;
					CP_GETDATA(num, &pcp);
					pcp->x[side] = imx + dx;
					pcp->y[side] = imy + dy;
				}
			}
		} while ((pev->what != EVMOSUP) || (pev->shift & SLEFTBTN) == 0);
		dispPoints();
		MG_PopPtr(moscsr);
		RM_recoverClipVisible();
		RM_recoverOrigin();
	}

  /* 操作点の削除 */

	static void deleteControlPoint(int side,int num)
	/* side,num: Ａ／Ｂ選択と、操作点番号 */
	/* 呼ばれるときにはマウスカーソルは表示されていること */
	{
		int moscsr;
		int msx,msy;
		EVENT *pev;
	  /* カレント操作点を、クリックされた操作点にする */
		curPoint = num;
		dispPoints();	/* もっと効率よい画面更新はないか？ */
		MG_PushPtr(MOSICON_POINT, &moscsr);
	  /* ドラッグ操作 */
		do {
			do {
				MMI_iosense() ;
			} while ((MMI_GetEvnt(EVMOSDRAG|EVMOSUP, &pev)) < NOERR);
			msx = *((short *)&(pev->info)) ;
			msy = *(((short *)&(pev->info)) + 1) ;
		} while ((pev->what != EVMOSUP) || (pev->shift & SLEFTBTN) == 0);
	  /* ドラッグ操作された後もマウスが同じ操作点を指していたら削除 */
		FRAME fr;
		RM_getFrame(idPointsWin, &fr);
		int cx,cy;
		getPointXY(side,num,&cx,&cy);
		if (abs(msx-cx) <= MAXDIF && abs(msy-cy) <= MAXDIF)
		{
			CPOINT *pcp;
			CP_GETDATA(num, &pcp);
		  /* 線分操作点だったときのリンクの修正 */
			if (pcp->type == CPOINT_LINE)
			{
				CPOINT *pcp2;
				if (pcp->c1 >= 0)
					{ CP_GETDATA(pcp->c1, &pcp2);  pcp2->c2 = pcp->c2; }
				if (pcp->c2 >= 0)
					{ CP_GETDATA(pcp->c2, &pcp2);  pcp2->c1 = pcp->c1; }
			}
		  /* 操作点の削除 */
			list_moveTo(plPoints, num);
			list_deleteData(plPoints);
			cpoint_delete(pcp);
		  /* 他の線分操作点のリンクの修正 */
			int n;
			for (n=0; n<CP_NUM; n++)
			{
				CPOINT *pcp2;
				CP_GETDATA(n,&pcp2);
				if (pcp2->type == CPOINT_LINE)
				{
					if (pcp2->c1 >= num)  pcp2->c1--;
					if (pcp2->c2 >= num)  pcp2->c2--;
				}
			}
		  /* 選択中の操作点番号の更新 */
			if (curPoint > num)
				curPoint--;
		}
	  /* 画面表示更新 */
		dispPoints();	/* もっと効率よい画面更新はないか？ */
		MG_PopPtr(moscsr);
	}

/*--------------------------------------------------------*/
/*                      操作点の作成                      */
/*--------------------------------------------------------*/

	static void points_makeNewPoints(EVENT *pev)
	{
		if (pointCommand != 0)
			return;
	  /* マウスポインタの位置のチェック */
		POINT pt;
		pt = *(POINT*)&pev->info;
		int side,rx,ry;
		if ((side = checkOnImage(pt.x, pt.y, &rx,&ry)) < 0)
			return;		/* ポインタが画像上にない */
		int dx,dy;
		if (checkOnPoint(side,rx,ry,&dx,&dy) >= 0)
			return;		/* ポインタが既存の操作点上にある */
	  /* 操作点タイプ別の処理 */
		RM_setOriginZero();
		setClipImage(side);
		if (pointType == CPOINT_POINT)
			makeControlPoint(CPOINT_POINT, rx,ry);
		else if (pointType == CPOINT_LINE)
		{
			nFromPoint = -1;
			int idPoint;
			if ((idPoint = makeControlPoint(CPOINT_LINE, rx,ry)) < 0)
				goto END_MAKELINECPOINT;
			int fromx,fromy;
			int msx,msy;
			getPointXY(side, idPoint, &fromx, &fromy);
			msx = fromx, msy = fromy;
			for (;;)
			{
				MG_mosDisp(2);
				WGB_LINE(guiEgbPtr, fromx,fromy,msx,msy,RED, XOR);
				MG_mosDisp(3);
				do {
					MMI_iosense() ;
				} while ((MMI_GetEvnt(EVMOSMOVE|EVMOSDRAG|EVMOSDN, &pev))
						 < NOERR);
				MG_mosDisp(2);
				WGB_LINE(guiEgbPtr, fromx,fromy,msx,msy,RED, XOR);
				MG_mosDisp(3);
				msx = *((short *)&(pev->info)) ;
				msy = *(((short *)&(pev->info)) + 1) ;
				if (pev->what == EVMOSDN && (pev->shift & SRIGHTBTN) != 0)
					break;	// 右クリックされたので終了
				if (pev->what == EVMOSDN && (pev->shift & SLEFTBTN) != 0)
				{
					int imx,imy;
					if (checkOnImage(msx,msy,&imx,&imy) == side)
					{
						checkOnPoint(side,imx,imy,&dx,&dy);
						makeControlPoint(CPOINT_LINE, imx,imy);
						fromx = msx, fromy = msy;
					}
				}
			}
			nFromPoint = -1;
		   END_MAKELINECPOINT:;
		}
		RM_recoverClipVisible();
		RM_recoverOrigin();
	}

/*--------------------------------------------------------*/
/*       操作点設定ウィンドウ内へ静止画像を読み込む       */
/*--------------------------------------------------------*/

	void points_storeImage(int side, IMAGE *im)
	{
		if (side < 0 || 1 < side)
			{ printf("points_storeImage: internal error!\n");
			  return; }
		if (piOriginal[side] != NULL)
			image_delete(piOriginal[side]);
		piOriginal[side] = im;
		image_zoomdown(piDisplay[side], piOriginal[side]);
		dispImages();
		points_checkActivity(TRUE);
	}

	void points_loadImage(int side)
	/* side: 0=Ａ側   1=Ｂ側 */
	{
		int ret;
		static char alertTitle[] = "静止画読込(操作点設定ウィンドウ)";
		char pathbuf[100];
		ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
							   "静止画の読込", "読込", "取消",
							   "*.TIF", FDG_FILEONLY, pathbuf);
		if (ret != 0)
			return;	// 「取消」
		TIFFinfo tiffinfo;
		if (TIFFgetinfo(pathbuf, &tiffinfo) != 0)
		{
			char strbuf[200];
			sprintf(strbuf, "ファイル %s が見つかりません", pathbuf);
			dispAlertMessage(alertTitle, strbuf);
			return;
		}
		if (tiffinfo.pixelsize != MORPH_PIXELSIZE)
		{
			char strbuf[200];
			sprintf(strbuf, "ファイル %s は３万色画像ではない"
					"ので読み込めません", pathbuf);
			dispAlertMessage(alertTitle, strbuf);
			return;
		}
		IMAGE *im;
		if ((im = image_new(tiffinfo.xlen, tiffinfo.ylen)) == NULL)
			{ alert_noMemory(alertTitle);  return; }
		int moscsr;
		MG_PushPtr(MOSICON_WAIT, &moscsr);
		ret = image_loadTIFF(im, pathbuf);
		MG_PopPtr(moscsr);
		if (ret != 0)
			{ dispAlertMessage(alertTitle, "ファイル読み込みに失敗しました");
			  return; }
		points_storeImage(side, im);
	}

/*--------------------------------------------------------*/
/*                    モーフィング処理                    */
/*--------------------------------------------------------*/

	static void dispXY2imageXY(int dispx,int dispy,int dispwid,int dispht,
							   int imagewid, int imageht, int *ix,int *iy)
	{
		int imx,imy;
		imx = ((imagewid-1)*dispx + (dispwid-1)/2) / (dispwid-1);
		imy = ((imageht -1)*dispy + (dispht -1)/2) / (dispht -1);
		*ix = imx;
		*iy = imy;
	}

	int points_makeMorphPoints(LIST *plPOINT, LIST *plLINE)
	/* モーフィング処理のための操作点(境界点)情報作成 */
	/* plPOINT,plLINE: 操作点情報を登録するための空リスト */
	/* このモジュール内の plPoints に登録されている操作点をもとに、
	   点操作点、線分操作点の情報を作成する。
	   新たに作成したリストは、plPOINT, plLINE に登録される */
	{
		static char alertTitle[] = "モーフィング／変形アニメ作成";
		int imwid,imht;
		imwid = piOriginal[0]->width;
		imht  = piOriginal[0]->height;
	  /* 画像の表示サイズを求める */
		int wid[2],ht[2];
		image_getDispSize(piOriginal[0],IMAGEWIDTH,IMAGEHEIGHT,&wid[0],&ht[0]);
		image_getDispSize(piOriginal[1],IMAGEWIDTH,IMAGEHEIGHT,&wid[1],&ht[1]);
		if (imwid < 2 || imht < 2 ||
			wid[0] < 2 || ht[0] < 2 || wid[1] < 2 || ht[1] < 2)
			return -1;	// ★「なぜか画像が小さすぎる」！内部エラーかも
	  /* 各操作点を画像内での座標に変換しながら新たにリスト作成 */
		#define	GETXY(cp,side,px,py)										\
			dispXY2imageXY((cp)->x[side],(cp)->y[side],wid[side],ht[side],	\
						   imwid,imht,px,py);
		int n;
		list_top(plPOINT);
		for (n=0; n<CP_NUM; n++)
		{
			CPOINT *pcp;
			CP_GETDATA(n, &pcp);
			if (!(pcp->type == CPOINT_POINT ||
			      (pcp->type == CPOINT_LINE && pcp->c1 < 0 && pcp->c2 < 0)))
				continue;
			MORPH_POINT mp;
			GETXY(pcp,0,&mp.from.x,&mp.from.y);
			GETXY(pcp,1,&mp.to.x,&mp.to.y);
			if (list_insertData(plPOINT, &mp) != 0)
				{ alert_noMemory(alertTitle);
				  return -1; }
			list_next(plPOINT);
		}
		list_top(plLINE);
		for (n=0; n<CP_NUM; n++)
		{
			CPOINT *pcp;
			CP_GETDATA(n,&pcp);
			if (pcp->type == CPOINT_LINE && pcp->c1 < 0 && pcp->c2 >= 0)
			{
				CPOINT *pcp2;
				for (;pcp->c2>=0;pcp=pcp2)
				{
				   CP_GETDATA(pcp->c2, &pcp2);	// 終点の操作点
				   MORPH_LINE ml;
				   GETXY(pcp, 0,&ml.from1.x,&ml.from1.y);
				   GETXY(pcp2,0,&ml.from2.x,&ml.from2.y);
				   GETXY(pcp, 1,&ml.to1.x,&ml.to1.y);
				   GETXY(pcp2,1,&ml.to2.x,&ml.to2.y);
				   if (list_insertData(plLINE, &ml) != 0)
				     { alert_noMemory(alertTitle);
				       return -1; }
				   list_next(plLINE);
				}
			}
		}
		#undef GETXY
		#if 0
			printf("morphing: Num(plPOINT)=%d\n", list_getDataNum(plPOINT));
			for (list_top(plPOINT); !list_isOut(plPOINT); list_next(plPOINT))
			{
				MORPH_POINT mp;
				list_getData(plPOINT,&mp);
				printf("  %d,%d,%d,%d\n",mp.from.x,mp.from.y,mp.to.x,mp.to.y);
			}
		#endif
		return 0;
	}

	int points_checkMorphImages(void)
	{
		if (piOriginal[0] == NULL || piOriginal[1] == NULL)
			return POINTS_IMAGE_NO_THERE;
		int imwid,imht;	// 画像のサイズ
		imwid = piOriginal[0]->width;
		imht  = piOriginal[0]->height;
		if (imwid != piOriginal[1]->width || imht != piOriginal[1]->height)
			return POINTS_IMAGE_MISMATCH_SIZE;
		return 0;
	}

	void points_getImageSize(int *pwid,int *pht)
	{
		int imwid,imht;
		if (piOriginal[0] != NULL)
			imwid = piOriginal[0]->width, imht  = piOriginal[0]->height;
		else if (piOriginal[1] != NULL)
			imwid = piOriginal[1]->width, imht  = piOriginal[1]->height;
		else
			return;
		if (pwid != NULL)
			*pwid = imwid;
		if (pht != NULL)
			*pht  = imht;
	}

	int morphGetFromPixel(fxp x, fxp y, int *r,int *g,int *b)
	{
		unsigned short c;
		int tx,ty;
		int ret;
		tx = FX2I(x);
		ty = FX2I(y);
		unsigned short *image;
		image = (unsigned short *)piOriginal[0]->image;
		c = image[piOriginal[0]->width * ty + tx];
		ret = 0;
		if (c == image[0])
			ret = -1;
		*g = (c >> 10) & 0x1f;
		*r = (c >>  5) & 0x1f;
		*b = (c      ) & 0x1f;
		return ret;
	}

	int morphGetToPixel(fxp x, fxp y, int *r,int *g,int *b)
	{
		int ret;
		unsigned short c, *image;
		int tx,ty;
		tx = FX2I(x);
		ty = FX2I(y);
		image = (unsigned short *)piOriginal[1]->image;
		c = image[piOriginal[1]->width * ty + tx];
		ret = 0;
		if (c == image[0])
			ret = -1;
		*g = (c >> 10) & 0x1f;
		*r = (c >>  5) & 0x1f;
		*b = (c      ) & 0x1f;
		return ret;
	}

/*--------------------------------------------------------*/
/*                 操作点の読み込み・保存                 */
/*--------------------------------------------------------*/

	int		points_checkLoadPoints(void)
	{
		if (piOriginal[0] == NULL && piOriginal[1] == NULL)
			return -1;
		else
			return 0;
	}

	static char pointFileHeader[32+1] = "DolphMorph PointInfo 1.0        ";

	void points_loadPoints(void)
	{
		static char ALERTTITLE[] = "操作点の読込";
		int ret;
		int i;
		char pathbuf[100];
		ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
							   "操作点読込", "読込", "取消", "*.MCP",
							   FDG_FILEONLY, pathbuf);
		if (ret != 0)
			return;	// 「取消」
		FILE *fp;
		if ((fp = fopen(pathbuf, "rb")) == NULL)
		{
			char strbuf[200];
			sprintf(strbuf, "ファイル %s が見つかりません", pathbuf);
			dispAlertMessage(ALERTTITLE, strbuf);
			return;
		}
		int moscsr;
		char readbuf[200];
		MG_PushPtr(MOSICON_WAIT, &moscsr);
		fread(readbuf, 1,32, fp);
		if (memcmp(readbuf, pointFileHeader, 32) != 0)
		{
			fclose(fp);
			char strbuf[200];
			sprintf(strbuf, "ファイル %s は操作点情報ファイルではないので"
					"読み込めません", pathbuf);
			dispAlertMessage(ALERTTITLE, strbuf);
			goto READEND;
		}
		fread(readbuf, 4,1, fp);
		int num;
		num = *(int*)readbuf;
		int idx = CP_NUM;
		for (i=0; i<num; i++)
		{
			CPOINT readcp, *pcp;
			fread(&readcp, sizeof(CPOINT), 1, fp);
			if ((pcp = cpoint_new(CPOINT_POINT,0,0)) == NULL)
			{
				alert_noMemory(ALERTTITLE);
				break;
			}
			*pcp = readcp;
			if (pcp->c1 >= 0)
				pcp->c1 += idx;
			if (pcp->c2 >= 0)
				pcp->c2 += idx;
			if (CP_INSERT(idx+i, &pcp) != 0)
			{
				alert_noMemory(ALERTTITLE);
				break;
			}
		}
		fclose(fp);
		MG_PopPtr(moscsr);
	   READEND:;
		dispImages();
		desktop_checkActivity();
	}

	int points_checkSavePoints(void)
	{
		if (CP_NUM > 0)
			return 0;
		else
			return -1;
	}
	
	void points_savePoints(void)
	{
		static char alertTitle[] = "操作点の保存";
		int ret;
		int i;
		char pathbuf[100],pathbuf2[100];
		if (CP_NUM <= 0)
		{
			dispAlertMessage("操作点の保存", "操作点が作成されていないので"
							 "保存できません");
			return;
		}
		ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
							   "操作点保存", "保存", "取消", "*.MCP",
							   FDG_FILEONLY|FDG_TEXT, pathbuf);
		if (ret != 0)
			return;	// 「取消」
		strcpy(pathbuf2,pathbuf);
		trans_fname_ext(pathbuf, pathbuf2, "MCP");
		if (fexist(pathbuf))
		{
			char strbuf[200];
			sprintf(strbuf, "ファイル %s がすでに存在しています。"
					"上書きしますか？", pathbuf);
			if (dispCheckMessage(alertTitle, strbuf, "上書き") != 0)
				return;
		}
		FILE *fp;
		if ((fp = fopen(pathbuf, "wb")) == NULL)
		{
			char strbuf[200];
			sprintf(strbuf, "ファイル %s に書き込むことができません", pathbuf);
			dispAlertMessage(alertTitle, strbuf);
			return;
		}
		int moscsr;
		MG_PushPtr(MOSICON_WAIT, &moscsr);
		fwrite(pointFileHeader, 1,32, fp);
		char writebuf[4];
		*(int*)writebuf = CP_NUM;	// int=4bytes, big endian 前提……
		fwrite(writebuf, 4,1, fp);
		for (i=0; i<CP_NUM; i++)
		{
			CPOINT *pcp;
			CP_GETDATA(i, &pcp);
			fwrite(pcp, sizeof(CPOINT), 1, fp);
		}
		fclose(fp);
		MG_PopPtr(moscsr);
		desktop_checkActivity();
	}

	int		points_checkClearPoints(void)
	{
		if (CP_NUM > 0)
			return 0;
		else
			return -1;
	}

	void points_clearPoints(void)
	{
		static char alertTitle[] = "操作点のクリア";
		if (dispCheckMessage(alertTitle, "操作点をすべて消去します。"
							 "よろしいですか？", "消去") != 0)
			return;
		int i;
		for (i=0; i<CP_NUM; i++)
		{
			CPOINT *pcp;
			CP_GETDATA(i, &pcp);
			cpoint_delete(pcp);
		}
		int cpnum;
		cpnum = CP_NUM;
		for (i=0; i<cpnum; i++)
		{
			list_top(plPoints);
			if (!list_isOut(plPoints))
				list_deleteData(plPoints);
		}
		curPoint = 0;
		dispPoints();
		desktop_checkActivity();
	}

/*--------------------------------------------------------*/
/*                   部品の呼び出し関数                   */
/*--------------------------------------------------------*/

	/*	initDataZPOINTS:idPointsWin:MJ_WINDOWL40の呼び出し関数	*/
	int	PointsWinFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		if (messId == MM_SHOW)
		{
			dispImages();
		}
		else if (messId == MM_MOVE)
		{
			RM_roundFramePosition(kobj,2,2);
			dispImages();
		}
		else if (messId == MM_MOUSEON && (pev->shift & SLEFTBTN)!=0)
		{
			POINT pt;
			pt = *(POINT*)&pev->info;
			int ret,rx,ry;
			if ((ret = checkOnImage(pt.x, pt.y, &rx,&ry)) >= 0)
			{
				int pn;
				int dx,dy;
				if ((pn = checkOnPoint(ret,rx,ry,&dx,&dy)) >= 0)
				{
					if (pointCommand == 0 || pointCommand == 1)
						moveControlPoint(ret,pn,dx,dy);
					else if (pointCommand == 2)
						deleteControlPoint(ret,pn);
				}
				else
				{
					if (pointCommand == 0)
						points_makeNewPoints(pev);
				}
			}
		#if 0
			else
			{
			  /* 一時的にユーザー領域をなくす */
				FRAME frUser, frResize;
				MMI_SendMessage(kobj, MM_GETUSER, 2, &frUser, &frResize);
				static FRAME frUserTemp = {0,0,0,0};
				MMI_SendMessage(kobj, MM_SETUSER, 2, &frUserTemp, &frResize);
			  /* 一時的にクリップ／ビシブル領域、原点をリセットする */
				RM_setClipVisibleAllScr();
				RM_setOriginZero();
			  /* ユーザー領域がないものとして MM_MOUSEON (つまり移動) */
				MMI_SendMessage(kobj, MM_MOUSEON, argc,pev,trigger);
			  /* 原点、クリップ／ビジブル領域、ユーザー領域を復帰する */
				RM_recoverOrigin();
				RM_recoverClipVisible();
				MMI_SendMessage(kobj, MM_SETUSER, 2, &frUser, &frResize);
			}
		#endif
		}
		else if (messId == MM_MOUSEON && (pev->shift & SRIGHTBTN)!=0)
		{
			if (pointType == CPOINT_LINE && nFromPoint >= 0)
				nFromPoint = -1;
		}
		desktop_checkActivity();
		return NOERR ;
	}

	/*	initDataZPOINTS:idPointsTypeTIcon[0]:MJ_TICONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsTypeTIcon[1]:MJ_TICONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsTypeTIcon[2]:MJ_TICONL40の呼び出し関数	*/
	int	PointsTypeTIconFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		RM_pushRadioButton(kobj, idPointsWin, idPointsTypeTIcon,
						   INTNUM(idPointsTypeTIcon), &pointType);
		desktop_checkActivity();
		return NOERR ;
	}

	/*	initDataZPOINTS:idPointsCommandTIcon[0]:MJ_TICONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsCommandTIcon[1]:MJ_TICONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsCommandTIcon[2]:MJ_TICONL40の呼び出し関数	*/
	int	PointsCommandTIconFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		RM_pushRadioButton(kobj, idPointsWin, idPointsCommandTIcon,
						   INTNUM(idPointsCommandTIcon), &pointCommand);
		desktop_checkActivity();
		return NOERR ;
	}

	/*	initDataZPOINTS:idPointsEditDBtn[0]:MJ_DBUTTONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsEditDBtn[1]:MJ_DBUTTONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsEditDBtn[2]:MJ_DBUTTONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsEditDBtn[3]:MJ_DBUTTONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsEditDBtn[4]:MJ_DBUTTONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsEditDBtn[5]:MJ_DBUTTONL40の呼び出し関数	*/
	int	PointsEditDBtnFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		int i;
		for (i=0; i<6; i++)
			if (kobj == idPointsEditDBtn[i])
				break;
		int side;
		side = (i < 3 ? 0 : 1);
		if (kobj == idPointsEditDBtn[3*side+0] ||
			kobj == idPointsEditDBtn[3*side+1])
		{
			if (piOriginal[side] != NULL)
			{
				IMAGE *pi;
				if ((pi = image_copy(piOriginal[side])) != NULL)
				{
					if (kobj == idPointsEditDBtn[3*side+0])
					{
						image_delete(piOriginal[side]);
						piOriginal[side] = NULL;
						dispImages();
					}
					if (piPaste != NULL)
						image_delete(piPaste);
					piPaste = pi;
				}
				else
					alert_noMemory("倉庫内の画像をカット／コピー");
			}
		}
		else if (kobj == idPointsEditDBtn[3*side+2])
		{
			if (piPaste != NULL)
			{
				IMAGE *pi;
				if ((pi = image_copy(piPaste)) != NULL)
					points_storeImage(side,pi);
				else
					alert_noMemory("画像を倉庫へペースト");
			}
		}
		desktop_checkActivity();
		return NOERR ;
	}

	/*	initDataZPOINTS:idPointsDarkTIcon[0]:MJ_TICONL40の呼び出し関数	*/
	/*	initDataZPOINTS:idPointsDarkTIcon[1]:MJ_TICONL40の呼び出し関数	*/
	int	PointsDarkTIconFunc(kobj, messId, argc, pev, trigger)
	int		kobj ;
	int		messId ;
	int		argc ;
	EVENT	*pev ;
	int		trigger ;
	{
		
	
		desktop_checkActivity();
		return NOERR ;
	}
