home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix Heaven Sunny 2
/
APPARE2.BIN
/
oh_towns
/
art2
/
src.lzh
/
IMGWIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-19
|
13KB
|
491 lines
/*====================================================
ARTemis
(version 1.3)
FM-TOWNS 用ペイントツール
by 松内 良介 1994
====================================================*/
#define MODULE_IMGWIN
/*
imgwins.c
int imageWINfunc(kobj, messId, argc, pev, trigger)
int imageSBARfunc(kobj, messId, argc, pev, trigger)
int ImageEraseDBtnProc(int kobj)
static int draw_line(IMWIN *win, POINT *first, int type)
static int draw_freeline(IMWIN *win, POINT *first, int type)
*/
#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 "art.h"
#include "guisub.h"
#include "wgbmac.H"
#include "alert.h"
#include "imagewin.h"
#include "imgwin.h"
#include "pensel.h"
#include "colsel.h"
#include "fifo.h"
#include "subgrp.h"
#include "desktop.h"
#include "copy.h"
int idImageWin = -1 ;
int idImageHSBar = -1 ;
int idImageVSBar = -1 ;
int idImageTitleDBtn = -1 ;
int idImageTitleMsg = -1 ;
int idImageEraseDBtn = -1 ;
int idImageBtn = -1 ;
/*--------------------------------------------------------*/
/* 部品の呼び出し関数 */
/*--------------------------------------------------------*/
static int draw_freeline(IMWIN *win, EVENT* first_ev, int type);
static int draw_line(IMWIN *win, POINT *first, int type);
/* ■画像ウィンドウの呼び出し関数■ */
/* initDataIMGWIN:imageWIN:MJ_WINDOWL40の呼び出し関数 */
int imageWINfunc(kobj, messId, argc, pev, trigger)
int kobj ;
int messId ;
int argc ;
EVENT *pev ;
int trigger ;
{
IMWIN *win;
WINCLIP *clipStack;
win = imagewin_getWinFromPart(kobj);
if (win == NULL)
return -1;
/* MM_SHOW メッセージへの応答 */
if (messId == MM_SHOW)
imagewin_updateScr(win);
/* MM_UPDATE(リサイズ)への応答 */
else if (messId == MM_UPDATE)
imagewin_resize(win, TRUE);
/* アクティブになった時 */
else if (messId == MM_WAKE)
{
HYPER Ht;
WINCLIP *clipStack;
OBJHYP(win->titlebar).clr.back = DARKGRAY;
OBJHYP(win->titlemsg).clr.ch = WHITE;
OBJHYP(win->erasebtn).clr.back = DARKGRAY;
WIN_beginUpDateObj(win->titlebar, &clipStack);
MMI_SendMessage(win->titlebar, MM_SHOW, 0);
MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
WIN_endUpDateObj(clipStack);
imagewin_setCurrentWin(win);
}
/* ノンアクティブになった時 */
else if (messId == MM_SLEEP)
{
HYPER Ht;
WINCLIP *clipStack;
OBJHYP(win->titlebar).clr.back = GRAY;
OBJHYP(win->titlemsg).clr.ch = BLACK;
OBJHYP(win->erasebtn).clr.back = GRAY;
WIN_beginUpDateObj(win->titlebar, &clipStack);
MMI_SendMessage(win->titlebar, MM_SHOW, 0);
MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
WIN_endUpDateObj(clipStack);
if (imagewin_getCurrentWin() == win)
imagewin_setCurrentWin(NULL);
}
// マウスボタンに対する応答
else if (messId == MM_MOUSEON && (pev->shift&SLEFTBTN) != 0)
{
int ret;
int tool = toolbox_getCurrentTool();
switch (tool)
{
case TOOL_FPSET:
case TOOL_FLINE:
case TOOL_KOSURI:
case TOOL_PAINT:
case TOOL_NIZIMI:
case TOOL_BOKASI:
case TOOL_SAND:
ret = draw_freeline(win, pev, tool);
break;
case TOOL_LINE:
ret = draw_line(win, (POINT*)&pev->info, 0);
break;
case TOOL_BOXFILL:
ret = draw_line(win, (POINT*)&pev->info, 2);
break;
case TOOL_COPY:
ret = input_rectarea(win, pev);
break;
case TOOL_POLYGONCOPY:
ret = input_polygonarea(win,pev);
break;
case TOOL_POLYGONFILL:
ret = cmd_polygonfill(win,pev);
break;
}
return ret;
}
else if (messId == MM_MOUSEON && (pev->shift&SRIGHTBTN) != 0)
{
// スポイト操作
POINT mospt = *(POINT*)&pev->info;
if (imagewin_PtInPic(win,&mospt))
{
POINT ptPic;
imagewin_getPosFromMos(win,&mospt,&ptPic);
PIXEL pix;
pic_getPixelXy(win->pic, ptPic.x,ptPic.y, &pix);
colsel_setCurPixel(&pix);
}
}
return NOERR ;
}
/* ■画像ウィンドウのスクロールバー■ */
/* initDataIMGWIN:imageSBARhori:MJ_SCRLL40の呼び出し関数 */
/* initDataIMGWIN:imageSBARvert:MJ_SCRLL40の呼び出し関数 */
int imageSBARfunc(kobj, messId, argc, pev, trigger)
int kobj ;
int messId ;
int argc ;
EVENT *pev ;
int trigger ;
{
IMWIN *win;
if ((win = imagewin_getWinFromPart(kobj)) == NULL)
return -1;
imagewin_updateBuf(win);
imagewin_updateScr(win);
return NOERR ;
}
int ImageEraseDBtnProc(int kobj)
// initDataZIMGWIN:idImageEraseDBtn:MJ_DBUTTONL40の呼び出し関数
{
IMWIN *win;
if ((win = imagewin_getWinFromPart(kobj)) == NULL)
return -1;
char buf[250];
sprintf(buf, "画像 %s のウィンドウをクローズします。"
"画像データは破棄されますが、よろしいですか?",
(win->fname[0]==0 ? "<名称未定>" : win->fname));
if (dispCheckMessage("画像ウィンドウを閉じる", buf, "続行") == 0)
{
imagewin_unlink(win);
imagewin_destroy(win);
if (imagewin_getCurrentWin() == win)
imagewin_setCurrentWin(NULL);
}
return NOERR ;
}
/*--------------------------------------------------------*/
/* 自由曲線による描画 */
/*--------------------------------------------------------*/
static int pen_ofsx, pen_ofsy;
static void _putPixel(IMWIN *win, POINT *pt)
/* 画像内の位置 pt に点を置く */
{
PIXEL pixel;
colsel_getPixel(&pixel);
pic_psetpen(win->pic,pt->x,pt->y,pensel_curpen(),&pixel);
}
static void _flushPointBuf(IMWIN *win, FIFO *points, int tooltype)
{
if (fifo_isEmpty(points))
return;
pic_beginUpDate(win->pic);
/* 4座標ずつまとめて処理 */
int i;
for (i=0; i<4; i++)
{
if (fifo_isEmpty(points))
break;
POINT mosp, imgp;
/* マウスカーソル位置が画像内のどこであるかを得る */
fifo_get(points, &mosp);
imagewin_getPosFromMos(win, &mosp, &imgp);
PIXEL pixel; colsel_getPixel(&pixel);
Pen pen = pensel_curpen();
switch(tooltype)
{
case TOOL_NIZIMI:
pic_blot(win->pic, imgp.x,imgp.y,2,paramNizimi, &pixel);
break;
case TOOL_KOSURI:
pic_kosuriDrag(win->pic,imgp.x-pen_ofsx,imgp.y-pen_ofsy,
paramKosuri);
break;
case TOOL_BOKASI:
pic_diffusePen(win->pic,imgp.x,imgp.y,pen);
break;
case TOOL_SAND:
pic_sandPen(win->pic,imgp.x,imgp.y,pen);
break;
default:
_putPixel(win, &imgp);
break;
}
}
/* 画面(とユーザー領域バッファ)に画像の更新部分を転送 */
FRAME updatefr;
pic_endUpDate(win->pic, &updatefr);
imagewin_updateScrPart(win, &updatefr);
}
static int draw_freeline(IMWIN *win, EVENT* first_ev, int type)
/* first:最初のマウス座標 */
{
imagewin_storeUndo(win);
EVENT *ev = first_ev;
POINT cp = *(POINT*)&first_ev->info;
POINT lastp = cp;
// FIFOバッファの作成
FIFO *points = fifo_new(sizeof(POINT));
if (points == NULL)
{
dispAlertMessage("メモリ不足です",
"描画処理を行うためのメモリ領域が不足しています。"
"不要な画像ウィンドウをクローズしてみてください");
return NOERR;
}
// 最初の点に関する処理
switch(type)
{
case TOOL_KOSURI: {
char *graypat; int wid,ht;
pensel_getPattern(&graypat, &wid,&ht,&pen_ofsx,&pen_ofsy);
POINT pt; imagewin_getPosFromMos(win, &cp, &pt);
pic_kosuriStart(win->pic,pt.x-pen_ofsx,pt.y-pen_ofsy,
graypat,wid,ht);
} break;
case TOOL_PAINT: {
POINT pt; imagewin_getPosFromMos(win, &cp, &pt);
PIXEL pix; colsel_getPixel(&pix);
int csr;
MG_PushPtr(MOSICON_WAIT, &csr);
pic_beginUpDate(win->pic);
pic_paint(win->pic,pt.x,pt.y, &pix);
FRAME frUpdate;
pic_endUpDate(win->pic, &frUpdate);
MG_PopPtr(csr);
imagewin_updateScrPart(win, &frUpdate);
} break;
}
/* イベントループ */
BOOL fFirst = TRUE;
int ev_ret = NOERR;
for (;;)
{
// マウスボタンが放されたら終了
if (!fFirst && ev->what!=EVMOSDRAG && (ev->shift&SLEFTBTN)!=0)
break;
// PIC領域にカーソルがあれば、座標登録
else if (imagewin_PtInPic(win, &cp))
{
/* FIFOバッファへ座標を登録する関数 */
void push_p(int x,int y)
{
POINT p; p.x = x; p.y = y;
fifo_set(points,&p);
}
/* 処理種別ごとに分岐 */
switch (type)
{
case TOOL_KOSURI:
case TOOL_NIZIMI:
push_p(cp.x, cp.y);
break;
case TOOL_FPSET:
case TOOL_BOKASI:
case TOOL_SAND:
if (ev_ret == NOERR)
push_p(cp.x, cp.y);
break;
case TOOL_FLINE:
if (ev_ret == NOERR)
do_line_cont(lastp.x,lastp.y,cp.x,cp.y, push_p);
break;
}
lastp = cp;
}
if (!fifo_isEmpty(points))
_flushPointBuf(win,points,type);
// イベントセンス
MMI_iosense();
EVENT *pre_ev = ev;
if ((ev_ret = MMI_GetEvnt(EVMOSDRAG|EVMOSUP,&ev)) != NOERR)
ev = pre_ev;
else
fFirst = FALSE;
cp = *(POINT*)&ev->info;
}
/* 座標バッファのフラッシュ */
while (!fifo_isEmpty(points))
_flushPointBuf(win,points,type);
fifo_destroy(points);
/* 次に続くイベントループ処理のために、最後のイベントをキューに戻す */
EVENT evbuf;
evbuf = *ev;
MMI_SetEvnt(&evbuf);
return NOERR ;
}
/*--------------------------------------------------------*/
/* 直線、矩形、矩形フィル */
/*--------------------------------------------------------*/
static int draw_line(IMWIN *win, POINT *first, int type)
/* first:最初のマウス座標 */
/* type:0=直線 1=矩形 2=矩形フィル */
{
imagewin_storeUndo(win);
int ret;
EVENT *ev, evbuf;
WINCLIP *pstackClip ;
FIFO *points;
POINT lastp;
int rub_x, rub_y;
/* FIFOバッファの作成 */
points = fifo_new(sizeof(POINT));
lastp = *first;
rub_x = lastp.x, rub_y = lastp.y;
/* クリップ枠の設定 */
RM_setOriginZero();
RM_setClipWinUser(win->win, &pstackClip) ;
/* イベントループ */
for (;;)
{
int what,shift;
POINT *pt;
/* ラバー描画 */
MG_mosDisp(2);
if (type == 0)
{ WGB_LINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
MG_colorChange(WHITE), 4); }
else
{ WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
MG_colorChange(WHITE), 4); }
MG_mosDisp(3);
/* イベントセンス */
do {
MMI_iosense();
} while (MMI_GetEvnt(EVALL, &ev) != NOERR);
/* ラバー消去 */
MG_mosDisp(2);
if (type == 0)
{ WGB_LINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
MG_colorChange(WHITE), 4); }
else
{ WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
MG_colorChange(WHITE), 4); }
MG_mosDisp(3);
/* イベント種別、シフト状態、マウス座標を得る */
what = ev->what;
shift = ev->shift;
pt = (POINT *) &ev->info;
/* 次のラバー座標を得る */
rub_x = pt->x;
rub_y = pt->y;
/* 左ボタンがクリックされたら */
if (what == EVMOSDN && (shift & SLEFTBTN) != 0)
{
FRAME fr; RM_getWinUserFrame(win->win, &fr);
if (fr.X <= pt->x && pt->x <= fr.X2 &&
fr.Y <= pt->y && pt->y <= fr.Y2)
{
void pset(int x,int y)
{
POINT p; p.x = x; p.y = y;
fifo_set(points,&p);
}
switch (type)
{
case 0:
do_line(lastp.x,lastp.y,pt->x,pt->y, pset);
while (!fifo_isEmpty(points))
_flushPointBuf(win, points, TOOL_FPSET);
break;
case 1:
do_boxline(lastp.x,lastp.y,pt->x,pt->y, pset);
while (!fifo_isEmpty(points))
_flushPointBuf(win, points, TOOL_FPSET);
break;
case 2:
POINT mosp,imgp1,imgp2;
FRAME updatefr,scrfr;
PIXEL pixel;
int min_y,max_y,i;
colsel_getPixel(&pixel);
mosp.x = lastp.x, mosp.y = lastp.y;
imagewin_getPosFromMos(win, &mosp, &imgp1);
mosp.x = pt->x, mosp.y = pt->y;
imagewin_getPosFromMos(win, &mosp, &imgp2);
min_y = _min(imgp1.y, imgp2.y);
max_y = _max(imgp1.y, imgp2.y);
/* 画面更新の開始 */
MG_mosDisp(2);
pic_beginUpDate(win->pic);
/* 矩形の描画 */
for (i=min_y; i<=max_y; i++)
pic_grayhline(win->pic,imgp1.x,imgp2.x,i,
pensel_getmix(),&pixel);
/* 画面に画像の更新部分を転送 */
pic_endUpDate(win->pic, &updatefr);
imagewin_updateScrPart(win, &updatefr);
/* 画面更新の終了 */
MG_mosDisp(3);
}
lastp = *pt;
if (type != 0)
break;
}
}
/* 右ボタンがクリックされたら */
else if (what == EVMOSDN && (shift & SRIGHTBTN) != 0)
{
break;
}
}
/* クリップ枠の復帰 */
RM_resetClipWinUser(pstackClip) ;
RM_recoverOrigin();
/* FIFOバッファの消滅 */
fifo_destroy(points);
/* 次に続くイベントループ処理のために、マウス左ボタンの EVMOSUP イベントを
キューに積む */
evbuf = *ev;
evbuf.what = EVMOSUP;
evbuf.shift = (evbuf.shift & (~SRIGHTBTN)) | SLEFTBTN;
MMI_SetEvnt(&evbuf);
return NOERR ;
}