home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / art2 / src.lzh / IMGWIN.C < prev    next >
C/C++ Source or Header  |  1995-06-19  |  13KB  |  491 lines

  1. /*====================================================
  2.                       ARTemis
  3.                    (version 1.3)
  4.              FM-TOWNS 用ペイントツール
  5.  
  6.                  by 松内 良介 1994
  7. ====================================================*/
  8. #define MODULE_IMGWIN
  9. /*
  10.     imgwins.c
  11.  
  12.     int    imageWINfunc(kobj, messId, argc, pev, trigger)
  13.     int    imageSBARfunc(kobj, messId, argc, pev, trigger)
  14.     int    ImageEraseDBtnProc(int kobj)
  15.  
  16. static int draw_line(IMWIN *win, POINT *first, int type)
  17. static int draw_freeline(IMWIN *win, POINT *first, int type)
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <winb.h>
  24. #include <te.h>
  25. #include <fntb.h>
  26. #include <gui.h>
  27. #include <egb.h>
  28. #include <wgb.h>
  29. #include <msdos.cf>
  30. #include "art.h"
  31. #include "guisub.h"
  32. #include "wgbmac.H"
  33. #include "alert.h"
  34.  
  35. #include "imagewin.h"
  36. #include "imgwin.h"
  37. #include "pensel.h"
  38. #include "colsel.h"
  39. #include "fifo.h"
  40. #include "subgrp.h"
  41. #include "desktop.h"
  42. #include "copy.h"
  43.  
  44. int    idImageWin = -1 ;
  45. int    idImageHSBar = -1 ;
  46. int    idImageVSBar = -1 ;
  47. int    idImageTitleDBtn = -1 ;
  48. int    idImageTitleMsg = -1 ;
  49. int    idImageEraseDBtn = -1 ;
  50. int    idImageBtn = -1 ;
  51.  
  52. /*--------------------------------------------------------*/
  53. /*                   部品の呼び出し関数                   */
  54. /*--------------------------------------------------------*/
  55.  
  56. static    int        draw_freeline(IMWIN *win, EVENT* first_ev, int type);
  57. static    int        draw_line(IMWIN *win, POINT *first, int type);
  58.  
  59.   /* ■画像ウィンドウの呼び出し関数■ */
  60.  
  61.         /*    initDataIMGWIN:imageWIN:MJ_WINDOWL40の呼び出し関数    */
  62.     int    imageWINfunc(kobj, messId, argc, pev, trigger)
  63.     int        kobj ;
  64.     int        messId ;
  65.     int        argc ;
  66.     EVENT    *pev ;
  67.     int        trigger ;
  68.     {
  69.         IMWIN *win;
  70.         WINCLIP *clipStack;
  71.         win = imagewin_getWinFromPart(kobj);
  72.         if (win == NULL)
  73.             return -1;
  74.  
  75.       /* MM_SHOW メッセージへの応答 */
  76.         if (messId == MM_SHOW)
  77.             imagewin_updateScr(win);
  78.  
  79.       /* MM_UPDATE(リサイズ)への応答 */
  80.         else if (messId == MM_UPDATE)
  81.             imagewin_resize(win, TRUE);
  82.  
  83.       /* アクティブになった時 */
  84.         else if (messId == MM_WAKE)
  85.         {
  86.             HYPER Ht;
  87.             WINCLIP *clipStack;
  88.             OBJHYP(win->titlebar).clr.back = DARKGRAY;
  89.             OBJHYP(win->titlemsg).clr.ch   = WHITE;
  90.             OBJHYP(win->erasebtn).clr.back = DARKGRAY;
  91.             WIN_beginUpDateObj(win->titlebar, &clipStack);
  92.             MMI_SendMessage(win->titlebar, MM_SHOW, 0);
  93.             MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
  94.             MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
  95.             WIN_endUpDateObj(clipStack);
  96.             imagewin_setCurrentWin(win);
  97.         }
  98.  
  99.       /* ノンアクティブになった時 */
  100.         else if (messId == MM_SLEEP)
  101.         {
  102.             HYPER Ht;
  103.             WINCLIP *clipStack;
  104.             OBJHYP(win->titlebar).clr.back = GRAY;
  105.             OBJHYP(win->titlemsg).clr.ch   = BLACK;
  106.             OBJHYP(win->erasebtn).clr.back = GRAY;
  107.             WIN_beginUpDateObj(win->titlebar, &clipStack);
  108.             MMI_SendMessage(win->titlebar, MM_SHOW, 0);
  109.             MMI_SendMessage(win->titlemsg, MM_SHOW, 0);
  110.             MMI_SendMessage(win->erasebtn, MM_SHOW, 0);
  111.             WIN_endUpDateObj(clipStack);
  112.             if (imagewin_getCurrentWin() == win)
  113.                 imagewin_setCurrentWin(NULL);
  114.         }
  115.  
  116.       // マウスボタンに対する応答
  117.         else if (messId == MM_MOUSEON && (pev->shift&SLEFTBTN) != 0)
  118.         {
  119.             int ret;
  120.             int tool = toolbox_getCurrentTool();
  121.             switch (tool)
  122.             {
  123.                 case TOOL_FPSET:
  124.                 case TOOL_FLINE:
  125.                 case TOOL_KOSURI:
  126.                 case TOOL_PAINT:
  127.                 case TOOL_NIZIMI:
  128.                 case TOOL_BOKASI:
  129.                 case TOOL_SAND:
  130.                     ret = draw_freeline(win, pev, tool);
  131.                     break;
  132.                 case TOOL_LINE:
  133.                     ret = draw_line(win, (POINT*)&pev->info, 0);
  134.                     break;
  135.                 case TOOL_BOXFILL:
  136.                     ret = draw_line(win, (POINT*)&pev->info, 2);
  137.                     break;
  138.                 case TOOL_COPY:
  139.                     ret = input_rectarea(win, pev);
  140.                     break;
  141.                 case TOOL_POLYGONCOPY:
  142.                     ret = input_polygonarea(win,pev);
  143.                     break;
  144.                 case TOOL_POLYGONFILL:
  145.                     ret = cmd_polygonfill(win,pev);
  146.                     break;
  147.             }
  148.             return ret;
  149.         }
  150.         
  151.         else if (messId == MM_MOUSEON && (pev->shift&SRIGHTBTN) != 0)
  152.         {
  153.             // スポイト操作
  154.             POINT mospt = *(POINT*)&pev->info;
  155.             if (imagewin_PtInPic(win,&mospt))
  156.             {
  157.                 POINT ptPic;
  158.                 imagewin_getPosFromMos(win,&mospt,&ptPic);
  159.                 PIXEL pix;
  160.                 pic_getPixelXy(win->pic, ptPic.x,ptPic.y, &pix);
  161.                 colsel_setCurPixel(&pix);
  162.             }
  163.         }
  164.         return NOERR ;
  165.     }
  166.  
  167.   /* ■画像ウィンドウのスクロールバー■ */
  168.  
  169.         /*    initDataIMGWIN:imageSBARhori:MJ_SCRLL40の呼び出し関数    */
  170.         /*    initDataIMGWIN:imageSBARvert:MJ_SCRLL40の呼び出し関数    */
  171.     int    imageSBARfunc(kobj, messId, argc, pev, trigger)
  172.     int        kobj ;
  173.     int        messId ;
  174.     int        argc ;
  175.     EVENT    *pev ;
  176.     int        trigger ;
  177.     {
  178.         IMWIN *win;
  179.         if ((win = imagewin_getWinFromPart(kobj)) == NULL)
  180.             return -1;
  181.         imagewin_updateBuf(win);
  182.         imagewin_updateScr(win);
  183.         return NOERR ;
  184.     }
  185.  
  186. int    ImageEraseDBtnProc(int kobj)
  187. // initDataZIMGWIN:idImageEraseDBtn:MJ_DBUTTONL40の呼び出し関数
  188. {
  189.     IMWIN *win;
  190.     if ((win = imagewin_getWinFromPart(kobj)) == NULL)
  191.         return -1;
  192.     char buf[250];
  193.     sprintf(buf, "画像 %s のウィンドウをクローズします。"
  194.             "画像データは破棄されますが、よろしいですか?",
  195.             (win->fname[0]==0 ? "<名称未定>" : win->fname));
  196.     if (dispCheckMessage("画像ウィンドウを閉じる", buf, "続行") == 0)
  197.     {
  198.         imagewin_unlink(win);
  199.         imagewin_destroy(win);
  200.         if (imagewin_getCurrentWin() == win)
  201.             imagewin_setCurrentWin(NULL);
  202.     }
  203.     return NOERR ;
  204. }
  205.  
  206.  
  207. /*--------------------------------------------------------*/
  208. /*                   自由曲線による描画                   */
  209. /*--------------------------------------------------------*/
  210.  
  211. static int pen_ofsx, pen_ofsy;
  212.  
  213. static void _putPixel(IMWIN *win, POINT *pt)
  214. /* 画像内の位置 pt に点を置く */
  215. {
  216.     PIXEL pixel;
  217.     colsel_getPixel(&pixel);
  218.     pic_psetpen(win->pic,pt->x,pt->y,pensel_curpen(),&pixel);
  219. }
  220.  
  221. static void _flushPointBuf(IMWIN *win, FIFO *points, int tooltype)
  222. {
  223.     if (fifo_isEmpty(points))
  224.         return;
  225.     pic_beginUpDate(win->pic);
  226.   /* 4座標ずつまとめて処理 */
  227.     int i;
  228.     for (i=0; i<4; i++)
  229.     {
  230.         if (fifo_isEmpty(points))
  231.             break;
  232.         POINT mosp, imgp;
  233.       /* マウスカーソル位置が画像内のどこであるかを得る */
  234.         fifo_get(points, &mosp);
  235.         imagewin_getPosFromMos(win, &mosp, &imgp);
  236.         PIXEL pixel;  colsel_getPixel(&pixel);
  237.         Pen pen = pensel_curpen();
  238.         switch(tooltype)
  239.         {
  240.         case TOOL_NIZIMI:
  241.             pic_blot(win->pic, imgp.x,imgp.y,2,paramNizimi, &pixel);
  242.             break;
  243.         case TOOL_KOSURI:
  244.             pic_kosuriDrag(win->pic,imgp.x-pen_ofsx,imgp.y-pen_ofsy,
  245.                             paramKosuri);
  246.             break;
  247.         case TOOL_BOKASI:
  248.             pic_diffusePen(win->pic,imgp.x,imgp.y,pen);
  249.             break;
  250.         case TOOL_SAND:
  251.             pic_sandPen(win->pic,imgp.x,imgp.y,pen);
  252.             break;
  253.         default:
  254.             _putPixel(win, &imgp);
  255.             break;
  256.         }
  257.     }
  258.   /* 画面(とユーザー領域バッファ)に画像の更新部分を転送 */
  259.     FRAME updatefr;
  260.     pic_endUpDate(win->pic, &updatefr);
  261.     imagewin_updateScrPart(win, &updatefr);
  262. }
  263.  
  264. static    int draw_freeline(IMWIN *win, EVENT* first_ev, int type)
  265. /* first:最初のマウス座標 */
  266. {
  267.     imagewin_storeUndo(win);
  268.     EVENT *ev = first_ev;
  269.     POINT cp = *(POINT*)&first_ev->info;
  270.     POINT lastp = cp;
  271.   // FIFOバッファの作成
  272.     FIFO *points = fifo_new(sizeof(POINT));
  273.     if (points == NULL)
  274.     {
  275.         dispAlertMessage("メモリ不足です",
  276.             "描画処理を行うためのメモリ領域が不足しています。"
  277.             "不要な画像ウィンドウをクローズしてみてください");
  278.         return NOERR;
  279.     }
  280.   // 最初の点に関する処理
  281.     switch(type)
  282.     {
  283.     case TOOL_KOSURI: {
  284.         char *graypat;  int wid,ht;
  285.         pensel_getPattern(&graypat, &wid,&ht,&pen_ofsx,&pen_ofsy);
  286.         POINT pt;  imagewin_getPosFromMos(win, &cp, &pt);
  287.         pic_kosuriStart(win->pic,pt.x-pen_ofsx,pt.y-pen_ofsy,
  288.             graypat,wid,ht);
  289.         } break;
  290.     case TOOL_PAINT: {
  291.         POINT pt;  imagewin_getPosFromMos(win, &cp, &pt);
  292.         PIXEL pix; colsel_getPixel(&pix);
  293.         int csr;
  294.         MG_PushPtr(MOSICON_WAIT, &csr);
  295.         pic_beginUpDate(win->pic);
  296.         pic_paint(win->pic,pt.x,pt.y, &pix);
  297.         FRAME frUpdate;
  298.         pic_endUpDate(win->pic, &frUpdate);
  299.         MG_PopPtr(csr);
  300.         imagewin_updateScrPart(win, &frUpdate);
  301.         } break;
  302.     }
  303.   /* イベントループ */
  304.     BOOL fFirst = TRUE;
  305.     int ev_ret = NOERR;
  306.     for (;;)
  307.     {
  308.       // マウスボタンが放されたら終了
  309.         if (!fFirst && ev->what!=EVMOSDRAG && (ev->shift&SLEFTBTN)!=0)
  310.             break;
  311.       // PIC領域にカーソルがあれば、座標登録
  312.         else if (imagewin_PtInPic(win, &cp))
  313.         {
  314.           /* FIFOバッファへ座標を登録する関数 */
  315.             void push_p(int x,int y)
  316.             {
  317.                 POINT p;  p.x = x;  p.y = y;
  318.                 fifo_set(points,&p);
  319.             }
  320.           /* 処理種別ごとに分岐 */
  321.             switch (type)
  322.             {
  323.             case TOOL_KOSURI:
  324.             case TOOL_NIZIMI:
  325.                 push_p(cp.x, cp.y);
  326.                 break;
  327.             case TOOL_FPSET:
  328.             case TOOL_BOKASI:
  329.             case TOOL_SAND:
  330.                 if (ev_ret == NOERR)
  331.                     push_p(cp.x, cp.y);
  332.                 break;
  333.             case TOOL_FLINE:
  334.                 if (ev_ret == NOERR)
  335.                     do_line_cont(lastp.x,lastp.y,cp.x,cp.y, push_p);
  336.                 break;
  337.             }
  338.             lastp = cp;
  339.         }
  340.         if (!fifo_isEmpty(points))
  341.             _flushPointBuf(win,points,type);
  342.       // イベントセンス
  343.         MMI_iosense();
  344.         EVENT *pre_ev = ev;
  345.         if ((ev_ret = MMI_GetEvnt(EVMOSDRAG|EVMOSUP,&ev)) != NOERR)
  346.             ev = pre_ev;
  347.         else
  348.             fFirst = FALSE;
  349.         cp = *(POINT*)&ev->info;
  350.     }
  351.   /* 座標バッファのフラッシュ */
  352.     while (!fifo_isEmpty(points))
  353.         _flushPointBuf(win,points,type);
  354.     fifo_destroy(points);
  355.   /* 次に続くイベントループ処理のために、最後のイベントをキューに戻す */
  356.     EVENT evbuf;
  357.     evbuf = *ev;
  358.     MMI_SetEvnt(&evbuf);
  359.     return NOERR ;
  360. }
  361.  
  362. /*--------------------------------------------------------*/
  363. /*                 直線、矩形、矩形フィル                 */
  364. /*--------------------------------------------------------*/
  365.  
  366. static    int        draw_line(IMWIN *win, POINT *first, int type)
  367. /* first:最初のマウス座標 */
  368. /* type:0=直線  1=矩形  2=矩形フィル */
  369. {
  370.     imagewin_storeUndo(win);
  371.     int ret;
  372.     EVENT *ev, evbuf;
  373.     WINCLIP *pstackClip ;
  374.     FIFO *points;
  375.     POINT lastp;
  376.     int rub_x, rub_y;
  377.   /* FIFOバッファの作成 */
  378.     points = fifo_new(sizeof(POINT));
  379.     lastp = *first;
  380.     rub_x = lastp.x, rub_y = lastp.y;
  381.   /* クリップ枠の設定 */
  382.     RM_setOriginZero();
  383.     RM_setClipWinUser(win->win, &pstackClip) ; 
  384.   /* イベントループ */
  385.     for (;;)
  386.     {
  387.         int what,shift;
  388.         POINT *pt;
  389.       /* ラバー描画 */
  390.         MG_mosDisp(2);
  391.         if (type == 0)
  392.             { WGB_LINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
  393.                        MG_colorChange(WHITE), 4); }
  394.         else
  395.             { WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y,rub_x,rub_y,
  396.                           MG_colorChange(WHITE), 4); }
  397.         MG_mosDisp(3);
  398.       /* イベントセンス */
  399.         do {
  400.             MMI_iosense();
  401.         } while (MMI_GetEvnt(EVALL, &ev) != NOERR);
  402.       /* ラバー消去 */
  403.         MG_mosDisp(2);
  404.         if (type == 0)
  405.             { WGB_LINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
  406.                        MG_colorChange(WHITE), 4); }
  407.         else
  408.             { WGB_BOXLINE(guiEgbPtr,lastp.x,lastp.y, rub_x, rub_y,
  409.                           MG_colorChange(WHITE), 4); }
  410.         MG_mosDisp(3);
  411.       /* イベント種別、シフト状態、マウス座標を得る */
  412.         what  = ev->what;
  413.         shift = ev->shift;
  414.         pt    = (POINT *) &ev->info;
  415.       /* 次のラバー座標を得る */
  416.         rub_x = pt->x;
  417.         rub_y = pt->y;
  418.       /* 左ボタンがクリックされたら */
  419.         if (what == EVMOSDN && (shift & SLEFTBTN) != 0)
  420.         {
  421.             FRAME fr; RM_getWinUserFrame(win->win, &fr);
  422.             if (fr.X <= pt->x && pt->x <= fr.X2 &&
  423.                 fr.Y <= pt->y && pt->y <= fr.Y2)
  424.             {
  425.                 void pset(int x,int y)
  426.                 {
  427.                     POINT p;  p.x = x;  p.y = y;
  428.                     fifo_set(points,&p);
  429.                 }
  430.                 switch (type)
  431.                 {
  432.                 case 0:
  433.                     do_line(lastp.x,lastp.y,pt->x,pt->y, pset);
  434.                     while (!fifo_isEmpty(points))
  435.                         _flushPointBuf(win, points, TOOL_FPSET);
  436.                     break;
  437.                 case 1:
  438.                     do_boxline(lastp.x,lastp.y,pt->x,pt->y, pset);
  439.                     while (!fifo_isEmpty(points))
  440.                         _flushPointBuf(win, points, TOOL_FPSET);
  441.                     break;
  442.                 case 2:
  443.                     POINT mosp,imgp1,imgp2;
  444.                     FRAME updatefr,scrfr;
  445.                     PIXEL pixel;
  446.                     int min_y,max_y,i;
  447.                     colsel_getPixel(&pixel);
  448.                     mosp.x = lastp.x, mosp.y = lastp.y;
  449.                     imagewin_getPosFromMos(win, &mosp, &imgp1);
  450.                     mosp.x = pt->x,   mosp.y = pt->y;
  451.                     imagewin_getPosFromMos(win, &mosp, &imgp2);
  452.                     min_y = _min(imgp1.y, imgp2.y);
  453.                     max_y = _max(imgp1.y, imgp2.y);
  454.                   /* 画面更新の開始 */
  455.                     MG_mosDisp(2);
  456.                     pic_beginUpDate(win->pic);
  457.                   /* 矩形の描画 */
  458.                     for (i=min_y; i<=max_y; i++)
  459.                         pic_grayhline(win->pic,imgp1.x,imgp2.x,i,
  460.                                       pensel_getmix(),&pixel);
  461.                   /* 画面に画像の更新部分を転送 */
  462.                     pic_endUpDate(win->pic, &updatefr);
  463.                     imagewin_updateScrPart(win, &updatefr);
  464.                   /* 画面更新の終了 */
  465.                     MG_mosDisp(3);
  466.                 }
  467.                 lastp = *pt;
  468.                 if (type != 0)
  469.                     break;
  470.             }
  471.         }
  472.       /* 右ボタンがクリックされたら */
  473.         else if (what == EVMOSDN && (shift & SRIGHTBTN) != 0)
  474.         {
  475.             break;
  476.         }
  477.     }
  478.   /* クリップ枠の復帰 */
  479.     RM_resetClipWinUser(pstackClip) ;
  480.     RM_recoverOrigin();
  481.   /* FIFOバッファの消滅 */
  482.     fifo_destroy(points);
  483.   /* 次に続くイベントループ処理のために、マウス左ボタンの EVMOSUP イベントを
  484.      キューに積む */
  485.     evbuf = *ev;
  486.     evbuf.what = EVMOSUP;
  487.     evbuf.shift = (evbuf.shift & (~SRIGHTBTN)) | SLEFTBTN;
  488.     MMI_SetEvnt(&evbuf);
  489.     return NOERR ;
  490. }
  491.