home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / gemlib27 / doodle_c < prev    next >
Text File  |  1993-07-30  |  46KB  |  1,947 lines

  1. /************************************************************************/
  2. /*    File:    doodle.c                        */
  3. /************************************************************************/
  4. /*                                    */
  5. /*             GGGGG        EEEEEEEE     MM      MM        */
  6. /*           GG             EE           MMMM  MMMM        */
  7. /*           GG   GGG       EEEEE        MM  MM  MM        */
  8. /*           GG   GG        EE           MM      MM        */
  9. /*             GGGGG        EEEEEEEE     MM      MM        */
  10. /*                                    */
  11. /************************************************************************/
  12. /*                                    */
  13. /*                                    */
  14. /*   The  source code  contained in  this listing is a non-copyrighted    */
  15. /*   work which  can be  freely used.  In applications of  this source    */
  16. /*   code you  are requested to  acknowledge Digital Research, Inc. as    */
  17. /*   the originator of portions of this code.    The code was        */
  18. /*   originally developed by them for the IBM PC.            */
  19. /*                                    */
  20. /*    ATARI ADAPTATION IN COLOR BY HARRY KOONS            */
  21. /*        VERSION 1.1B    7/11/85                    */
  22. /*                                    */
  23. /*    If you find this program of value, I would appreciate a        */
  24. /*    contribution of $20 for the time and effort I have spent in    */
  25. /*    making it work on the Atari 520 ST.                */
  26. /*                                    */
  27. /*    Harry Koons                            */
  28. /*    1123 Oakfair Lane                        */
  29. /*    Harbor City, CA 90710                        */
  30. /*                                    */
  31. /************************************************************************/
  32.  
  33.  
  34. /*
  35.  
  36. Page*/
  37. /*------------------------------*/
  38. /*    includes        */
  39. /*------------------------------*/
  40. #ifndef __GNUC__
  41. #include "define.h"                /* misc. definitions    */
  42. #include "osbind.h"                /* gemdos bindings    */
  43. #include "portab.h"                 /* portable coding conv    */
  44. /* #include "machine.h"  */              /* machine dependent    */
  45. #include "obdefs.h"                /* object definitions    */
  46. #include "gemdefs.h"                /* misc gem definitions */
  47. #include "taddr.h"                /* tree address macros    */
  48. #include "vdibind.h"                /* vdi binding structs    */
  49. #include "b:doodle.h"                /* doodle apl resource  */
  50. #else
  51. #define __OLD_WAY__
  52. #include <osbind.h>                /* gemdos bindings    */
  53. #include <gemfast.h>                /* misc gem definitions */
  54. #include <aesbind.h>                /* aes binding structs    */
  55. #include <vdibind.h>                /* vdi binding structs    */
  56. #include <string.h>                /* string library       */
  57. #include "portab.h"                 /* portable coding conv    */
  58. #include "taddr.h"                /* tree address macros    */
  59. #include "doodle.h"                /* doodle apl resource  */
  60.  
  61. #define WF_HSLSIZ    WF_HSLSIZE
  62. #define WF_VSLSIZ    WF_VSLSIZE
  63. #endif
  64.  
  65. /*------------------------------*/
  66. /*    defines            */
  67. /*------------------------------*/
  68.  
  69.  
  70. #define    DESK        0
  71.  
  72. #define END_UPDATE    0
  73. #define    BEG_UPDATE    1
  74.  
  75. #define SHADE0        0
  76. #define SHADE1        1
  77. #define SHADE2        2
  78. #define SHADE3        3
  79. #define SHADE4        4
  80. #define SHADE5        5
  81. #define SHADE6        6
  82. #define SHADE7        7
  83. #define SHADE8        8
  84. #define SHADE9        9
  85. #define SHADE10        10
  86. #define SHADE11        11
  87. #define SHADE12        12
  88. #define SHADE13        13
  89. #define SHADE14        14
  90. #define SHADE15        15
  91.  
  92.  
  93.  
  94. #define    PEN_FINE    1
  95. #define    PEN_MEDIUM    5
  96. #define    PEN_BROAD    9
  97.  
  98.  
  99.  
  100. /*------------------------------*/
  101. /*    Macros            */
  102. /*------------------------------*/
  103.  
  104. #define LLGET(x) (*((LONG*)(x)))
  105. #define LLSET(x,y) (*((LONG*)(x))=y)
  106. #define LWGET(x) ((WORD)*((WORD*)(x)))
  107. #define LWSET(x,y) (*((WORD*)(x))=y)
  108. #define YSCALE(x) umul_div(x, scrn_xsize, scrn_ysize)
  109. #define TE_TXTLEN(x) (x + 24)
  110. #define ADDR /**/
  111. /* #define GLOBAL */
  112. /*
  113.  
  114. Page*/
  115. /************************************************************************/
  116. /************************************************************************/
  117. /****                                     ****/
  118. /****                Data Structures                 ****/
  119. /****                                     ****/
  120. /************************************************************************/
  121. /************************************************************************/
  122.  
  123.  
  124. /*------------------------------*/
  125. /*    Extrnl Data Structures    */
  126. /*------------------------------*/
  127.  
  128. UWORD    dos_err;    /* no longer external  */
  129.  
  130.  
  131. /*------------------------------*/
  132. /*    Global Data Structures    */
  133. /*------------------------------*/
  134. #ifndef __GNUC__
  135. GLOBAL WORD    contrl[11];        /* control inputs        */
  136. GLOBAL WORD    intin[80];        /* max string length        */
  137. GLOBAL WORD    ptsin[256];        /* polygon fill points        */
  138. GLOBAL WORD    intout[45];        /* open workstation output    */
  139. GLOBAL WORD    ptsout[12];
  140. #endif
  141.  
  142. /*------------------------------*/
  143. /*    Local Data Structures    */
  144. /*------------------------------*/
  145.  
  146. WORD    gl_wchar;            /* character width        */
  147. WORD    gl_hchar;            /* character height        */
  148. WORD    gl_wbox;            /* box (cell) width        */
  149. WORD    gl_hbox;            /* box (cell) height        */
  150. WORD    gl_hspace;            /* height of space between lines*/
  151. WORD    gem_handle;            /* GEM vdi handle        */
  152. WORD    vdi_handle;            /* doodle vdi handle        */
  153. WORD    work_out[57];            /* open virt workstation values    */
  154. GRECT    scrn_area;            /* whole scrn area        */
  155. GRECT    work_area;            /* drawing area of main window  */
  156. GRECT    undo_area;            /* area equal to work_area    */
  157. GRECT    save_area;            /* save area for full/unfulling */
  158. WORD    gl_rmsg[8];            /* message buffer        */
  159. LONG    ad_rmsg;            /* LONG pointer to message bfr    */
  160. LONG    gl_menu;            /* menu tree address        */
  161. WORD    gl_apid;            /* application ID        */
  162. WORD    gl_xfull;            /* full window 'x'        */
  163. WORD    gl_yfull;            /* full window 'y'        */
  164. WORD    gl_wfull;            /* full window 'w'        */
  165. WORD    gl_hfull;            /* full window 'h'        */
  166. WORD    scrn_width;            /* scrn width in pixels    */
  167. WORD    scrn_height;            /* scrn height in pixels    */
  168. WORD    scrn_planes;            /* number of color planes    */
  169. WORD    scrn_xsize;            /* width of one pixel        */
  170. WORD    scrn_ysize;            /* height of one pixel        */
  171. UWORD    m_out = FALSE;            /* mouse in/out of window flag    */
  172. WORD    ev_which;            /* event multi return state(s)    */
  173. UWORD    mousex, mousey;            /* mouse x,y position        */
  174. UWORD    bstate, bclicks;        /* button state, & # of clicks    */
  175. UWORD    kstate, kreturn;        /* key state and keyboard char    */
  176. MFDB    undo_mfdb;            /* undo buffer mmry frm def blk */
  177. MFDB    scrn_mfdb;            /* scrn memory form defn blk    */
  178. LONG    buff_size;            /* buffer size req'd for scrn    */
  179. LONG    buff_location;            /* scrn buffer pointer        */
  180. WORD    dodle_whndl;            /* doodle window handle        */
  181. BOOLEAN    dood_fill = FALSE;        /* fill or draw flag        */
  182. BOOLEAN first_fill = FALSE;        /* to set background color    */
  183. WORD    dodle_shade = SHADE1;        /* doodle current pen shade    */
  184. WORD    pen_ink = SHADE1;        /* current ink shade        */
  185. WORD    bkgr_color = SHADE0;        /* current background shade    */
  186. WORD    bkgr_next = SHADE0;        /* next background shade    */
  187. WORD    dodle_pen = 1;            /* doodle current pen width    */
  188. WORD    dodle_height = 4;        /* doodle current char height    */
  189. WORD    char_fine;            /* character height for fine    */
  190. WORD    char_medium;            /* character height for medium    */
  191. WORD    char_broad;            /* character height for broad    */
  192. WORD    monumber = 5;            /* mouse form number        */
  193. LONG    mofaddr = 0x0L;            /* mouse form address        */
  194. WORD    file_handle;            /* file handle -> pict ld/sv    */
  195. BYTE    file_name[64] = "";        /* current pict file name    */
  196. BOOLEAN    key_input;            /* key inputting state        */
  197. WORD    key_xbeg;            /* x position for line beginning*/
  198. WORD    key_ybeg;            /* y position for line beginning*/
  199. WORD    key_xcurr;            /* current x position        */
  200. WORD    key_ycurr;            /* current y position        */
  201.                     /* doodle window title        */
  202. BYTE    *wdw_title = " Dr Doodle Window ";
  203.  
  204. /*
  205.  
  206. Page*/
  207. /*------------------------------*/
  208. /*    Mouse Data Structures    */
  209. /*------------------------------*/
  210.  
  211. WORD    erase_broad[37] =        /* mouse form for broad eraser    */
  212. {
  213.     7, 7, 1, 0, 1,
  214.     0x0000, 0x0000, 0x0000, 0x0000,    /* mask */
  215.     0x0000, 0x1ff0, 0x1ff0, 0x1ff0,
  216.     0x1ff0, 0x1ff0, 0x0000, 0x0000,
  217.     0x0000, 0x0000, 0x0000, 0x0000,
  218.     0x0000, 0x0000, 0x0000, 0x0000,    /* data */
  219.     0x7ffc, 0x600c, 0x600c, 0x600c,
  220.     0x600c, 0x600c, 0x7ffc, 0x0000,
  221.     0x0000, 0x0000, 0x0000, 0x0000
  222. };
  223. WORD    erase_medium[37] =        /* mouse form for medium eraser    */
  224. {
  225.     7, 7, 1, 0, 1,
  226.     0x0000, 0x0000, 0x0000, 0x0000,    /* mask */
  227.     0x0000, 0x0000, 0x07c0, 0x07c0,
  228.     0x07c0, 0x0000, 0x0000, 0x0000,
  229.     0x0000, 0x0000, 0x0000, 0x0000,
  230.     0x0000, 0x0000, 0x0000, 0x0000,    /* data */
  231.     0x0000, 0x1ff0, 0x1830, 0x1830,
  232.     0x1830, 0x1ff0, 0x0000, 0x0000,
  233.     0x0000, 0x0000, 0x0000, 0x0000
  234. };
  235. WORD    erase_fine[37] =        /* mouse form for fine eraser    */
  236. {
  237.     7, 7, 1, 0, 1,
  238.     0x0000, 0x0000, 0x0000, 0x0000,    /* mask */
  239.     0x0000, 0x0000, 0x0000, 0x0100,
  240.     0x0000, 0x0000, 0x0000, 0x0000,
  241.     0x0000, 0x0000, 0x0000, 0x0000,
  242.     0x0000, 0x0000, 0x0000, 0x0000,    /* data */
  243.     0x0000, 0x0000, 0x07c0, 0x06c0,
  244.     0x07c0, 0x0000, 0x0000, 0x0000,
  245.     0x0000, 0x0000, 0x0000, 0x0000
  246. };
  247.  
  248.  
  249.  
  250. /*
  251.  
  252. Page*/
  253. /************************************************************************/
  254. /************************************************************************/
  255. /****                                     ****/
  256. /****                Local Procedures                 ****/
  257. /****                                     ****/
  258. /************************************************************************/
  259. /************************************************************************/
  260.  
  261.  
  262. /*------------------------------*/
  263. /*    min            */
  264. /*------------------------------*/
  265. WORD
  266. min(a, b)            /* return min of two values */
  267. WORD        a, b;
  268. {
  269.     return( (a < b) ? a : b );
  270. }
  271.  
  272.  
  273. /*------------------------------*/
  274. /*    max            */
  275. /*------------------------------*/
  276. WORD
  277. max(a, b)            /* return max of two values */
  278. WORD        a, b;
  279. {
  280.     return( (a > b) ? a : b );
  281. }
  282.  
  283.  
  284. /*------------------------------*/
  285. /*    string_addr        */
  286. /*------------------------------*/
  287. LONG
  288. string_addr(which)        /* returns a tedinfo LONG string addr    */
  289. WORD    which;
  290. {
  291.     LONG    where;
  292.  
  293.     rsrc_gaddr(R_STRING, which, &where);
  294.     return (where);
  295.  
  296.  
  297. /*------------------------------*/
  298. /*    rc_equal        */
  299. /*------------------------------*/
  300. WORD
  301. rc_equal(p1, p2)        /* tests for two rectangles equal    */
  302. GRECT        *p1, *p2;
  303. {
  304.     if ((p1->g_x != p2->g_x) ||
  305.         (p1->g_y != p2->g_y) ||
  306.         (p1->g_w != p2->g_w) ||
  307.         (p1->g_h != p2->g_h))
  308.         return(FALSE);
  309.     return(TRUE);
  310. }
  311.  
  312.  
  313.  
  314. /*------------------------------*/
  315. /*    rc_copy            */
  316. /*------------------------------*/
  317. WORD
  318. rc_copy(psbox, pdbox)        /* copy source to destination rectangle    */
  319. GRECT    *psbox;
  320. GRECT    *pdbox;
  321. {
  322.     pdbox->g_x = psbox->g_x;
  323.     pdbox->g_y = psbox->g_y;
  324.     pdbox->g_w = psbox->g_w;
  325.     pdbox->g_h = psbox->g_h;
  326. }
  327.  
  328.  
  329. /*------------------------------*/
  330. /*    rc_intersect        */
  331. /*------------------------------*/
  332. WORD
  333. rc_intersect(p1, p2)        /* compute intersect of two rectangles    */
  334. GRECT        *p1, *p2;
  335. {
  336.     WORD        tx, ty, tw, th;
  337.  
  338.     tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
  339.     th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
  340.     tx = max(p2->g_x, p1->g_x);
  341.     ty = max(p2->g_y, p1->g_y);
  342.     p2->g_x = tx;
  343.     p2->g_y = ty;
  344.     p2->g_w = tw - tx;
  345.     p2->g_h = th - ty;
  346.     return( (tw > tx) && (th > ty) );
  347. }
  348.  
  349.  
  350. /*------------------------------*/
  351. /*    inside            */
  352. /*------------------------------*/
  353. UWORD
  354. inside(x, y, pt)        /* determine if x,y is in rectangle    */
  355. UWORD        x, y;
  356. GRECT        *pt;
  357. {
  358.     if ( (x >= pt->g_x) && (y >= pt->g_y) &&
  359.         (x < pt->g_x + pt->g_w) && (y < pt->g_y + pt->g_h) )
  360.         return(TRUE);
  361.     else
  362.         return(FALSE);
  363. } /* inside */
  364.  
  365.  
  366. /*------------------------------*/
  367. /*    grect_to_array        */
  368. /*------------------------------*/
  369. VOID
  370. grect_to_array(area, array)    /* convert x,y,w,h to upr lt x,y and    */
  371. GRECT    *area;            /*              lwr rt x,y    */
  372. WORD    *array;
  373. {
  374.     *array++ = area->g_x;
  375.     *array++ = area->g_y;
  376.     *array++ = area->g_x + area->g_w - 1;
  377.     *array = area->g_y + area->g_h - 1;
  378. }
  379.  
  380.  
  381. /*------------------------------*/
  382. /*    rast_op            */
  383. /*------------------------------*/
  384. VOID
  385. rast_op(mode, s_area, s_mfdb, d_area, d_mfdb)    /* bit block level trns    */
  386. WORD    mode;
  387. GRECT    *s_area, *d_area;
  388. MFDB    *s_mfdb, *d_mfdb;
  389. {
  390.     WORD    pxy[8];
  391.  
  392.     grect_to_array(s_area, pxy);
  393.     grect_to_array(d_area, &pxy[4]);
  394.     vro_cpyfm(vdi_handle, mode, pxy, s_mfdb, d_mfdb);
  395. }
  396.  
  397.  
  398. /*------------------------------*/
  399. /*    do_open            */
  400. /*------------------------------*/
  401. VOID
  402. do_open(wh, org_x, org_y, x, y, w, h)    /* grow and open specified wdw    */
  403. WORD    wh;
  404. WORD    org_x, org_y;
  405. WORD    x, y, w, h;
  406. {
  407.     graf_growbox(org_x, org_y, 21, 21, x, y, w, h);
  408.     wind_open(wh, x, y, w, h);
  409. }
  410.  
  411.  
  412. /*------------------------------*/
  413. /*    do_close        */
  414. /*------------------------------*/
  415. VOID
  416. do_close(wh, org_x, org_y)    /* close and shrink specified window    */
  417. WORD    wh;
  418. WORD    org_x, org_y;
  419. {
  420.     WORD    x, y, w, h;
  421.  
  422.     wind_get(wh, WF_CURRXYWH, &x, &y, &w, &h);
  423.     wind_close(wh);
  424.     graf_shrinkbox(org_x, org_y, 21, 21, x, y, w, h);
  425. }
  426.  
  427.  
  428. /*------------------------------*/
  429. /*    hndl_dial        */
  430. /*------------------------------*/
  431. WORD
  432. hndl_dial(tree, def, x, y, w, h)    /* center, display and get input*/
  433. LONG    tree;                /*   from specified dialogue box*/
  434. WORD    def;
  435. WORD    x, y, w, h;
  436. {
  437.     WORD    xdial, ydial, wdial, hdial;
  438.     WORD    exit_obj;
  439.  
  440.     form_center(tree, &xdial, &ydial, &wdial, &hdial);
  441.     form_dial(0, x, y, w, h, xdial, ydial, wdial, hdial);
  442.     form_dial(1, x, y, w, h, xdial, ydial, wdial, hdial);
  443.     objc_draw(tree, ROOT, MAX_DEPTH, xdial, ydial, wdial, hdial);
  444.     exit_obj = form_do(tree, def);
  445.     form_dial(2, x, y, w, h, xdial, ydial, wdial, hdial);
  446.     form_dial(3, x, y, w, h, xdial, ydial, wdial, hdial);
  447.     return (exit_obj);
  448. }
  449.  
  450.  
  451. /*------------------------------*/
  452. /*    set_clip        */
  453. /*------------------------------*/
  454. VOID
  455. set_clip(clip_flag, s_area)    /* set clip to specified area    */
  456. WORD    clip_flag;
  457. GRECT    *s_area;
  458. {
  459.     WORD    pxy[4];
  460.  
  461.     grect_to_array(s_area, pxy);
  462.     vs_clip(vdi_handle, clip_flag, pxy);
  463. }
  464.  
  465.  
  466. /*------------------------------*/
  467. /*    align_x            */
  468. /*------------------------------*/
  469. WORD
  470. align_x(x)        /* forces word alignment for column position    */
  471. WORD    x;        /*   rounding to nearest word            */
  472. {
  473.     /*    return((x & 0xfff0) + ((x & 0x000c) ? 0x0010 : 0));    IBM */
  474.     return(x);    /* ATARI    */    
  475. }    
  476.  
  477.  
  478. /*
  479.  
  480. Page*/
  481. /************************************************************************/
  482. /************************************************************************/
  483. /****                                     ****/
  484. /****                Work Area Management             ****/
  485. /****                                     ****/
  486. /************************************************************************/
  487. /************************************************************************/
  488.  
  489.  
  490. /*------------------------------*/
  491. /*    set_work        */
  492. /*------------------------------*/
  493. VOID
  494. set_work(slider_update)        /* update undo area, clamping to page    */
  495. BOOLEAN    slider_update;        /*   edges, and updt sliders if req'd    */
  496. {
  497.     WORD    i;
  498.  
  499.     wind_get(dodle_whndl, WF_WORKXYWH,
  500.     &work_area.g_x, &work_area.g_y,
  501.     &work_area.g_w, &work_area.g_h);
  502.  
  503.     undo_area.g_w = work_area.g_w;
  504.     undo_area.g_h = work_area.g_h;
  505.     /**/                    /* clamp work area to page edges */
  506.     if ((i = undo_mfdb.fwp - (undo_area.g_x + undo_area.g_w)) < 0)
  507.         undo_area.g_x += i;
  508.     if ((i = undo_mfdb.fh - (undo_area.g_y + undo_area.g_h)) < 0)
  509.         undo_area.g_y += i;
  510.  
  511.     if (slider_update)
  512.     {
  513.         wind_set(dodle_whndl, WF_HSLIDE, umul_div(undo_area.g_x, 1000,
  514.             undo_mfdb.fwp - undo_area.g_w), 0, 0, 0);
  515.         wind_set(dodle_whndl, WF_VSLIDE, umul_div(undo_area.g_y, 1000,
  516.             undo_mfdb.fh - undo_area.g_h), 0, 0, 0);
  517.         wind_set(dodle_whndl, WF_HSLSIZ, umul_div(work_area.g_w, 1000,
  518.             undo_mfdb.fwp), 0, 0, 0);
  519.         wind_set(dodle_whndl, WF_VSLSIZ, umul_div(work_area.g_h, 1000,
  520.             undo_mfdb.fh), 0, 0, 0);
  521.     }
  522.  
  523.     undo_area.g_x = align_x(undo_area.g_x);
  524.     /* only use portion of work_area on scrn    */
  525.     rc_intersect(&scrn_area, &work_area);
  526.     undo_area.g_w = work_area.g_w;
  527.     undo_area.g_h = work_area.g_h;
  528. }
  529.  
  530.  
  531. /*------------------------------*/
  532. /*    save_work        */
  533. /*------------------------------*/
  534. VOID
  535. save_work()            /* copy work_area to undo_area buffer    */
  536. {
  537.     GRECT    tmp_area;
  538.  
  539.     rc_copy(&work_area,&tmp_area);
  540.     rc_intersect(&scrn_area,&tmp_area);
  541.     graf_mouse(M_OFF, 0x0L);
  542.     rast_op(3, &tmp_area, &scrn_mfdb, &undo_area, &undo_mfdb);
  543.     graf_mouse(M_ON, 0x0L);
  544. }
  545.  
  546.  
  547. /*------------------------------*/
  548. /*    restore_work        */
  549. /*------------------------------*/
  550. VOID
  551. restore_work()            /* restore work_area from undo_area    */
  552. {
  553.     GRECT    tmp_area;
  554.  
  555.     rc_copy(&work_area,&tmp_area);
  556.     rc_intersect(&scrn_area,&tmp_area);
  557.     graf_mouse(M_OFF, 0x0L);
  558.     rast_op(3, &undo_area, &undo_mfdb, &tmp_area, &scrn_mfdb);
  559.     graf_mouse(M_ON, 0x0L);
  560. }
  561.  
  562.  
  563. /*
  564.  
  565. Page*/
  566. /************************************************************************/
  567. /************************************************************************/
  568. /****                                     ****/
  569. /****                Object Tree Manipulation             ****/
  570. /****                                     ****/
  571. /************************************************************************/
  572. /************************************************************************/
  573.  
  574.  
  575. /*------------------------------*/
  576. /*    do_obj            */
  577. /*------------------------------*/
  578. VOID
  579. do_obj(tree, which, bit)    /* set specified bit in object state    */
  580. LONG    tree;
  581. WORD    which, bit;
  582. {
  583.     WORD    state;
  584.  
  585.     state = LWGET(OB_STATE(which));
  586.     LWSET(OB_STATE(which), state | bit);
  587. }
  588.  
  589.  
  590. /*------------------------------*/
  591. /*    undo_obj        */
  592. /*------------------------------*/
  593. VOID
  594. undo_obj(tree, which, bit)    /* clear specified bit in object state    */
  595. LONG    tree;
  596. WORD    which, bit;
  597. {
  598.     WORD    state;
  599.  
  600.     state = LWGET(OB_STATE(which));
  601.     LWSET(OB_STATE(which), state & ~bit);
  602. }
  603.  
  604. /*------------------------------*/
  605. /*    sel_obj            */
  606. /*------------------------------*/
  607. VOID
  608. sel_obj(tree, which)        /* turn on selected bit of spcfd object    */
  609. LONG    tree;
  610. WORD    which;
  611. {
  612.     do_obj(tree, which, SELECTED);
  613. }
  614.  
  615.  
  616. /*------------------------------*/
  617. /*    desel_obj        */
  618. /*------------------------------*/
  619. VOID
  620. desel_obj(tree, which)        /* turn off selected bit of spcfd object*/
  621. LONG    tree;
  622. WORD    which;
  623. {
  624.     undo_obj(tree, which, SELECTED);
  625. }
  626.  
  627.  
  628. /*------------------------------*/
  629. /*    enab_menu        */
  630. /*------------------------------*/
  631. VOID
  632. enab_menu(which)        /* enable specified menu item    */
  633. WORD    which;
  634. {
  635.     undo_obj(gl_menu, which, DISABLED);
  636. }
  637.  
  638. /*------------------------------*/
  639. /*    objc_xywh        */
  640. /*------------------------------*/
  641. VOID
  642. objc_xywh(tree, obj, p)        /* get x,y,w,h for specified object    */
  643. LONG    tree;
  644. WORD    obj;
  645. GRECT    *p;
  646. {
  647.     objc_offset(tree, obj, &p->g_x, &p->g_y);
  648.     p->g_w = LWGET(OB_WIDTH(obj));
  649.     p->g_h = LWGET(OB_HEIGHT(obj));
  650. }
  651.  
  652.  
  653. /*
  654.  
  655. Page*/
  656. /************************************************************************/
  657. /************************************************************************/
  658. /****                                     ****/
  659. /****                File Path Name Functions             ****/
  660. /****                                     ****/
  661. /************************************************************************/
  662. /************************************************************************/
  663.  
  664.  
  665. /*------------------------------*/
  666. /*    dial_name        */
  667. /*------------------------------*/
  668. WORD
  669. dial_name ( name )        /* dialogue box input filename    */
  670. BYTE    *name;
  671. {            
  672.     LONG    tree ;
  673.     LONG    ted_addr ;
  674.     BYTE    c ;    
  675.     WORD    i, j;
  676.     GRECT    box;
  677.  
  678.  
  679.     objc_xywh(gl_menu, DOODFILE, &box);
  680.     rsrc_gaddr( R_TREE, DOODSVAD, &tree) ;
  681.     ted_addr = LLGET(OB_SPEC(DOODNAME));
  682.     LLSET( ted_addr, ADDR(name) ) ;
  683.     LWSET( TE_TXTLEN(ted_addr),8);
  684.     name[0] = '\0';
  685.     if (hndl_dial(tree, DOODNAME, box.g_x, box.g_y, box.g_w, box.g_h) == DOODSOK)
  686.     {
  687.         i =
  688.             j =  0;
  689.         while (TRUE)
  690.         {
  691.             c = name[i++];
  692.             if (!c) 
  693.                 break ;
  694.             if ( (c != ' ') && (c != '_') )
  695.                 name[j++] = c ;
  696.         }
  697.         if ( *name )
  698.             strcpy( &name[j], ".DOO" ) ;
  699.         desel_obj(tree, DOODSOK);
  700.         return ((WORD) *name);
  701.     }
  702.     else
  703.     {
  704.         desel_obj(tree, DOODSCNL);
  705.         return (FALSE);
  706.     }
  707. }
  708.  
  709.  
  710. /*------------------------------*/
  711. /*    get_path        */
  712. /*------------------------------*/
  713. VOID
  714. get_path(tmp_path, spec)    /* get directory path name    */
  715. BYTE    *tmp_path, *spec;
  716. {
  717.     WORD    cur_drv;
  718.  
  719.     cur_drv = Dgetdrv();
  720.     tmp_path[0] = cur_drv + 'A';
  721.     tmp_path[1] = ':';
  722.     tmp_path[2] = '\\';
  723.         Dgetpath(ADDR(&tmp_path[3]), cur_drv+1);
  724.     if ((int)strlen(tmp_path) > 3)
  725.         strcat(tmp_path, "\\");
  726.     else
  727.         tmp_path[2] = '\0';
  728.     strcat(tmp_path, spec);
  729. }
  730.  
  731.  
  732. /*------------------------------*/
  733. /*    add_file_name        */
  734. /*------------------------------*/
  735. VOID
  736. add_file_name(dname, fname)    /* replace name at end of input file spec*/
  737. BYTE    *dname, *fname;
  738. {
  739.     BYTE    c;
  740.     WORD    ii;
  741.  
  742.  
  743.     ii = (int)strlen(dname);
  744.     while (ii && (((c = dname[ii-1])  != '\\') && (c != ':')))
  745.         ii--;
  746.     dname[ii] = '\0';
  747.     strcat(dname, fname);
  748. }
  749.  
  750.  
  751. /*------------------------------*/
  752. /*    get_file        */
  753. /*------------------------------*/
  754. WORD
  755. get_file(loop)            /* use file selector to get input file    */
  756. BOOLEAN    loop;
  757. {
  758.     WORD    fs_iexbutton;
  759.     BYTE    fs_iinsel[13];
  760.  
  761.     while (TRUE)
  762.     {
  763.         get_path(file_name, "*.DOO");
  764.         fs_iinsel[0] = '\0';
  765.  
  766.         fsel_input(ADDR(file_name), ADDR(fs_iinsel), &fs_iexbutton);
  767.         if (fs_iexbutton)
  768.         {
  769.             add_file_name(file_name, fs_iinsel);
  770.             file_handle = Fopen(ADDR(file_name),2);
  771.             dos_err = (file_handle < 0) ? -1 : 0;
  772.             if (!loop || (loop && !dos_err))
  773.                 return(1);
  774.         }
  775.         else
  776.             return (0);
  777.     }
  778. } /* get_file */
  779.  
  780.  
  781. /*
  782.  
  783. Page*/
  784. /************************************************************************/
  785. /************************************************************************/
  786. /****                                     ****/
  787. /****                Soft Cursor Support                 ****/
  788. /****                                     ****/
  789. /************************************************************************/
  790. /************************************************************************/
  791.  
  792.  
  793. /*------------------------------*/
  794. /*    cursor            */
  795. /*------------------------------*/
  796. VOID
  797. cursor(color)            /* turn cursor on,  color = pen_ink    */
  798. WORD    color;            /*   or cursor off, color = bkgr_color    */
  799. {
  800.     WORD    pxy[4];
  801.  
  802.     pxy[0] = key_xcurr + 1;
  803.     pxy[1] = key_ycurr + gl_hspace;
  804.     pxy[2] = key_xcurr + 1;
  805.     pxy[3] = key_ycurr - gl_hbox;
  806.  
  807.     vsl_color(vdi_handle,color);
  808.     vswr_mode(vdi_handle,MD_REPLACE);
  809.     vsl_type (vdi_handle,IP_1PATT);
  810.     vsl_width (vdi_handle,PEN_FINE);
  811.     v_pline(vdi_handle, 2, pxy);
  812. }
  813.  
  814.  
  815. /*------------------------------*/
  816. /*    curs_on            */
  817. /*------------------------------*/
  818. VOID
  819. curs_on()            /* turn 'soft' cursor 'on'    */
  820. {
  821.     cursor(pen_ink);
  822. }
  823.  
  824. /*------------------------------*/
  825. /*    curs_off        */
  826. /*------------------------------*/
  827. VOID
  828. curs_off()            /* turn 'soft' cursor 'off'    */
  829. {
  830.     cursor(bkgr_color);
  831. }
  832.  
  833.  
  834. /*
  835.  
  836. Page*/
  837. /************************************************************************/
  838. /************************************************************************/
  839. /****                                     ****/
  840. /****                Menu Handling                 ****/
  841. /****                                     ****/
  842. /************************************************************************/
  843. /************************************************************************/
  844.  
  845.  
  846. /*------------------------------*/
  847. /*    hdl_menu        */
  848. /*------------------------------*/
  849. WORD
  850. hdl_menu(title, item)
  851. WORD     title, item;
  852. {
  853.     WORD    done;
  854.     WORD    me_creturn;
  855.  
  856.     graf_mouse(ARROW, 0x0L);
  857.     done = FALSE;
  858.     switch (title) {
  859.     case DOODDESK:
  860.         if (item == DOODINFO)
  861.             do_about();
  862.         break;
  863.  
  864.     case DOODFILE:
  865.         switch (item)
  866.         {
  867.         case DOODLOAD:
  868.             do_load(TRUE);
  869.             break;
  870.         case DOODSAVE:
  871.             do_sav();
  872.             break;
  873.         case DOODSVAS:
  874.             do_savas();
  875.             break;
  876.         case DOODABAN:
  877.             file_handle = Fopen(ADDR(file_name),2);
  878.             do_load(FALSE);
  879.             break;
  880.         case DOODQUIT:
  881.             done = TRUE;
  882.             break;
  883.         }
  884.  
  885.     case DOODOPTS:
  886.         switch (item)
  887.         {
  888.         case DOODPENS:
  889.             do_penselect();
  890.             break;
  891.         case DOODERAP:
  892.             do_erase();
  893.             first_fill = TRUE;
  894.             break;
  895.         }
  896.  
  897.     case DOODCOLR:
  898.         switch (item)
  899.         {
  900.         case COLOR0:
  901.             pen_ink = SHADE0;
  902.             do_clnormal();
  903.             me_creturn = menu_icheck (gl_menu, COLOR0, SELECTED);
  904.             break;
  905.         case COLOR1:
  906.             pen_ink = SHADE1;
  907.             do_clnormal();
  908.             me_creturn = menu_icheck (gl_menu, COLOR1, SELECTED);
  909.             break;
  910.         case COLOR2:
  911.             pen_ink = SHADE2;
  912.             do_clnormal();
  913.             me_creturn = menu_icheck (gl_menu, COLOR2, SELECTED);
  914.             break;
  915.         case COLOR3:
  916.             pen_ink = SHADE3;
  917.             do_clnormal();
  918.             me_creturn = menu_icheck (gl_menu, COLOR3, SELECTED);
  919.             break;
  920.         case COLOR4:
  921.             pen_ink = SHADE4;
  922.             do_clnormal();
  923.             me_creturn = menu_icheck (gl_menu, COLOR4, SELECTED);
  924.             break;
  925.         case COLOR5:
  926.             pen_ink = SHADE5;
  927.             do_clnormal();
  928.             me_creturn = menu_icheck (gl_menu, COLOR5, SELECTED);
  929.             break;
  930.         case COLOR6:
  931.             pen_ink = SHADE6;
  932.             do_clnormal();
  933.             me_creturn = menu_icheck (gl_menu, COLOR6, SELECTED);
  934.             break;
  935.         case COLOR7:
  936.             pen_ink = SHADE7;
  937.             do_clnormal();
  938.             me_creturn = menu_icheck (gl_menu, COLOR7, SELECTED);
  939.             break;
  940.         case COLOR8:
  941.             pen_ink = SHADE8;
  942.             do_clnormal();
  943.             me_creturn = menu_icheck (gl_menu, COLOR8, SELECTED);
  944.             break;
  945.         case COLOR9:
  946.             pen_ink = SHADE9;
  947.             do_clnormal();
  948.             me_creturn = menu_icheck (gl_menu, COLOR9, SELECTED);
  949.             break;
  950.         case COLOR10:
  951.             pen_ink = SHADE10;
  952.             do_clnormal();
  953.             me_creturn = menu_icheck (gl_menu, COLOR10, SELECTED);
  954.             break;
  955.         case COLOR11:
  956.             pen_ink = SHADE11;
  957.             do_clnormal();
  958.             me_creturn = menu_icheck (gl_menu, COLOR11, SELECTED);
  959.             break;
  960.         case COLOR12:
  961.             pen_ink = SHADE12;
  962.             do_clnormal();
  963.             me_creturn = menu_icheck (gl_menu, COLOR12, SELECTED);
  964.             break;
  965.         case COLOR13:
  966.             pen_ink = SHADE13;
  967.             do_clnormal();
  968.             me_creturn = menu_icheck (gl_menu, COLOR13, SELECTED);
  969.             break;
  970.         case COLOR14:
  971.             pen_ink = SHADE14;
  972.             do_clnormal();
  973.             me_creturn = menu_icheck (gl_menu, COLOR14, SELECTED);
  974.             break;
  975.         case COLOR15:
  976.             pen_ink = SHADE15;
  977.             do_clnormal();
  978.             me_creturn = menu_icheck (gl_menu, COLOR15, SELECTED);
  979.             break;
  980.         }
  981.  
  982.         dodle_shade = pen_ink;
  983.  
  984.     }
  985.     menu_tnormal(gl_menu,title,TRUE);
  986.     graf_mouse(monumber, mofaddr);
  987.     return (done);
  988. }
  989.  
  990.  
  991. /*------------------------------*/
  992. /*    do_clnormal        */
  993. /*------------------------------*/
  994. VOID
  995. do_clnormal()    /*    set all color checks to NORMAL in color menu    */
  996. {
  997.     WORD    me_creturn;
  998.  
  999.     me_creturn = menu_icheck(gl_menu, COLOR0, NORMAL);
  1000.     me_creturn = menu_icheck(gl_menu, COLOR1, NORMAL);
  1001.     me_creturn = menu_icheck(gl_menu, COLOR2, NORMAL);
  1002.     me_creturn = menu_icheck(gl_menu, COLOR3, NORMAL);
  1003.     me_creturn = menu_icheck(gl_menu, COLOR4, NORMAL);
  1004.     me_creturn = menu_icheck(gl_menu, COLOR5, NORMAL);
  1005.     me_creturn = menu_icheck(gl_menu, COLOR6, NORMAL);
  1006.     me_creturn = menu_icheck(gl_menu, COLOR7, NORMAL);
  1007.     me_creturn = menu_icheck(gl_menu, COLOR8, NORMAL);
  1008.     me_creturn = menu_icheck(gl_menu, COLOR9, NORMAL);
  1009.     me_creturn = menu_icheck(gl_menu, COLOR10, NORMAL);
  1010.     me_creturn = menu_icheck(gl_menu, COLOR11, NORMAL);
  1011.     me_creturn = menu_icheck(gl_menu, COLOR12, NORMAL);
  1012.     me_creturn = menu_icheck(gl_menu, COLOR13, NORMAL);
  1013.     me_creturn = menu_icheck(gl_menu, COLOR14, NORMAL);
  1014.     me_creturn = menu_icheck(gl_menu, COLOR15, NORMAL);
  1015. }
  1016.  
  1017. /*------------------------------*/
  1018. /*    do_about        */
  1019. /*------------------------------*/
  1020. VOID
  1021. do_about()            /* display Doodle Info...     */
  1022. {
  1023.     LONG    tree;
  1024.     GRECT    box;
  1025.  
  1026.     objc_xywh(gl_menu, DOODDESK, &box);
  1027.     rsrc_gaddr(R_TREE, DOODINFD, &tree);
  1028.     hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
  1029.     desel_obj(tree, DOODOK);
  1030. }
  1031.  
  1032.  
  1033. /*------------------------------*/
  1034. /*    do_load            */
  1035. /*------------------------------*/
  1036. VOID
  1037. do_load(need_name)        /* load doodle picture file    */
  1038. BOOLEAN    need_name;
  1039. {
  1040.     if (!need_name || get_file(TRUE))
  1041.     {
  1042.         if (!dos_err)
  1043.         {
  1044.             Fread(file_handle, buff_size,buff_location);
  1045.             Fclose(file_handle);
  1046.             enab_menu(DOODSAVE);
  1047.             enab_menu(DOODABAN);
  1048.             restore_work();
  1049.         }
  1050.     }
  1051. }
  1052.  
  1053.  
  1054. /*------------------------------*/
  1055. /*    do_sav            */
  1056. /*------------------------------*/
  1057. VOID
  1058. do_sav()            /* save current named doodle picture    */
  1059. {
  1060.     if (*file_name)
  1061.     {
  1062.         file_handle = Fopen(ADDR(file_name),2);
  1063.         dos_err = (file_handle < 0) ? 1 : 0;
  1064.         if (dos_err)
  1065.             file_handle = Fcreate(ADDR(file_name),0);
  1066.         else
  1067.         {
  1068.             if (form_alert(1, string_addr(DOODOVWR)) == 2)
  1069.                 return;
  1070.         }
  1071.         Fwrite(file_handle, buff_size, buff_location);
  1072.         enab_menu(DOODSAVE);
  1073.         enab_menu(DOODABAN);
  1074.         Fclose(file_handle);
  1075.     }
  1076. }
  1077.  
  1078.  
  1079. /*------------------------------*/
  1080. /*    do_sav_as        */
  1081. /*------------------------------*/
  1082. VOID
  1083. do_savas()            /* save doodle picture as named    */
  1084. {
  1085.     BYTE    name[13];
  1086.  
  1087.     if (dial_name(&name[0]))
  1088.     {
  1089.         add_file_name(file_name, name);
  1090.         do_sav();
  1091.     }
  1092. }
  1093.  
  1094.  
  1095. /*------------------------------*/
  1096. /*    do_penselect        */
  1097. /*------------------------------*/
  1098. VOID
  1099. do_penselect()            /* use dialogue box to input selection    */
  1100. {                /*   of specified pen/eraser        */
  1101.     WORD    exit_obj;
  1102.     LONG    tree;
  1103.     GRECT    box;
  1104.  
  1105.     objc_xywh(gl_menu, DOODPENS, &box);
  1106.     rsrc_gaddr(R_TREE, DOODPEND, &tree);
  1107.     /**/            /* first setup current selection state    */
  1108.     if (dodle_pen == PEN_FINE)
  1109.     {
  1110.         sel_obj(tree, DOODFINE);
  1111.         desel_obj(tree, DOODMED);
  1112.         desel_obj(tree, DOODBRD);
  1113.     }
  1114.     else
  1115.         if (dodle_pen == PEN_MEDIUM)
  1116.         {
  1117.             sel_obj(tree, DOODMED);
  1118.             desel_obj(tree, DOODFINE);
  1119.             desel_obj(tree, DOODBRD);
  1120.         }
  1121.         else
  1122.         {
  1123.             sel_obj(tree, DOODBRD);
  1124.             desel_obj(tree, DOODFINE);
  1125.             desel_obj(tree, DOODMED);
  1126.         }
  1127.     if (dodle_shade == pen_ink && dood_fill == FALSE)
  1128.     {
  1129.         sel_obj(tree, DOODPEN);
  1130.         desel_obj(tree, DOODERSR);
  1131.         desel_obj(tree, DOODFILL);
  1132.     }
  1133.     else if (dodle_shade == pen_ink && dood_fill == TRUE)
  1134.     {
  1135.         desel_obj(tree, DOODPEN);
  1136.         desel_obj(tree, DOODERSR);
  1137.         sel_obj(tree, DOODFILL);
  1138.     }
  1139.     else
  1140.     {
  1141.         desel_obj(tree, DOODPEN);
  1142.         sel_obj(tree, DOODERSR);
  1143.         desel_obj(tree, DOODFILL);
  1144.     }
  1145.  
  1146.     /* get dialogue box input    */
  1147.  
  1148.     exit_obj = hndl_dial(tree, 0, box.g_x, box.g_y, box.g_w, box.g_h);
  1149.     if (exit_obj == DOODPSOK)
  1150.     {
  1151.         if (LWGET(OB_STATE(DOODFINE)) & SELECTED)
  1152.         {
  1153.             dodle_pen = PEN_FINE;
  1154.             dodle_height = char_fine;
  1155.         }
  1156.         else
  1157.             if (LWGET(OB_STATE(DOODMED)) & SELECTED)
  1158.             {
  1159.                 dodle_pen = PEN_MEDIUM;
  1160.                 dodle_height = char_medium;
  1161.             }
  1162.             else
  1163.             {
  1164.                 dodle_pen = PEN_BROAD;
  1165.                 dodle_height = char_broad;
  1166.             }
  1167.         if (LWGET(OB_STATE(DOODPEN)) & SELECTED)
  1168.         {
  1169.             dodle_shade = pen_ink;
  1170.             monumber = 5;
  1171.             mofaddr = 0x0L;
  1172.             dood_fill = FALSE;
  1173.         }
  1174.         else if (LWGET(OB_STATE(DOODERSR)) & SELECTED)
  1175.         {
  1176.             dodle_shade = bkgr_color;
  1177.             monumber = 255;
  1178.             mofaddr = (dodle_pen == PEN_FINE) ? ADDR((BYTE *)erase_fine) :
  1179.             (dodle_pen == PEN_MEDIUM) ? ADDR((BYTE *)erase_medium) :
  1180.             ADDR((BYTE *)erase_broad);
  1181.             dood_fill = FALSE;
  1182.         }
  1183.         else
  1184.         {
  1185.             dodle_shade = pen_ink;
  1186.             monumber = POINT_HAND;
  1187.             mofaddr = 0x0L;
  1188.             dood_fill = TRUE;
  1189.         }
  1190.  
  1191.         desel_obj(tree, DOODPSOK);
  1192.     }
  1193.     else
  1194.         desel_obj(tree, DOODCNCL);
  1195. }
  1196.  
  1197.  
  1198. /*------------------------------*/
  1199. /*    do_erase        */
  1200. /*------------------------------*/
  1201. VOID
  1202. do_erase()            /* clear the scrn and the undo buffer    */
  1203. {
  1204.     WORD    fo_aexbttn;
  1205.  
  1206.     fo_aexbttn = form_alert(0, string_addr(ERASEWRN));
  1207.  
  1208.     if (fo_aexbttn == 1)
  1209.     {
  1210.         rast_op(0, &scrn_area, &scrn_mfdb, &scrn_area, &undo_mfdb);
  1211.         restore_work();
  1212.     }
  1213. }
  1214. /*
  1215.  
  1216. Page*/
  1217. /************************************************************************/
  1218. /************************************************************************/
  1219. /****                                     ****/
  1220. /****                Keyboard Handling                 ****/
  1221. /****                                     ****/
  1222. /************************************************************************/
  1223. /************************************************************************/
  1224.  
  1225.  
  1226. /*------------------------------*/
  1227. /*    hndl_keyboard        */
  1228. /*------------------------------*/
  1229. WORD
  1230. hndl_keyboard()
  1231. {
  1232.     WORD    i;
  1233.     BYTE    str[2];
  1234.  
  1235.     if ((str[0] = kreturn) == 0x03)
  1236.         return(TRUE);
  1237.     graf_mouse(M_OFF, 0x0L);
  1238.     if (!key_input)
  1239.     {
  1240.         vsl_color(vdi_handle,dodle_shade);
  1241.         vswr_mode(vdi_handle,MD_TRANS);
  1242.         vsl_type (vdi_handle,IP_1PATT);
  1243.         vst_height(vdi_handle, dodle_height,
  1244.         &gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
  1245.         gl_hspace = gl_hbox - gl_hchar;
  1246.         set_clip(TRUE, &work_area);
  1247.         graf_mkstate(&key_xbeg, &key_ybeg, &i, &i);
  1248.         key_xcurr = ++key_xbeg;
  1249.         key_ycurr = --key_ybeg;
  1250.     }
  1251.     else
  1252.  
  1253.     /*    curs_off();    remove from color version 6/30/85    */
  1254.  
  1255.     str[1] = '\0';
  1256.     if (str[0] == 0x1A)
  1257.     {
  1258.         save_work();
  1259.         graf_mouse(M_ON, 0x0L);
  1260.         return(key_input = FALSE);
  1261.     }
  1262.     else
  1263.         if (str[0] == 0x0D)
  1264.         {
  1265.             key_ycurr += gl_hbox + gl_hspace;
  1266.             key_xcurr = key_xbeg;
  1267.         }
  1268.         else
  1269.             if (str[0] == 0x08)
  1270.             {
  1271.                 if (key_input && (key_xcurr != key_xbeg))
  1272.                 {
  1273.                     for (i = 0; i < gl_wbox; i++)
  1274.                     {
  1275.                         key_xcurr--;
  1276.                     /*    curs_off();    */
  1277.                     }
  1278.                 }
  1279.             }
  1280.             else
  1281.                 if ((str[0] >= ' ') && (str[0] <= 'z'))
  1282.                 {
  1283.                     str[1] = '\0';
  1284.                     vswr_mode(vdi_handle, MD_TRANS);
  1285.                     vst_color(vdi_handle, pen_ink);
  1286.                     v_gtext(vdi_handle, key_xcurr,
  1287.                     key_ycurr, str);
  1288.                     key_xcurr += gl_wbox;
  1289.                 }
  1290.     if (!key_input)
  1291.     {
  1292.         key_input = TRUE;
  1293.     }
  1294.     /*    curs_on();    remove from color version 6/30/85  */
  1295.     graf_mouse(M_ON, 0x0L);
  1296.     return(FALSE);
  1297. }
  1298.  
  1299.  
  1300.  
  1301. /*
  1302.  
  1303. Page*/
  1304. /************************************************************************/
  1305. /************************************************************************/
  1306. /****                                     ****/
  1307. /****                Message Handling                 ****/
  1308. /****                                     ****/
  1309. /************************************************************************/
  1310. /************************************************************************/
  1311.  
  1312.  
  1313. /*------------------------------*/
  1314. /*    hdl_message        */
  1315. /*------------------------------*/
  1316. /*MLOCAL*/    BOOLEAN    hdl_message()
  1317. {
  1318.     BOOLEAN    done; 
  1319.     WORD    wdw_hndl;
  1320.  
  1321.     done = FALSE;
  1322.     wdw_hndl = gl_rmsg[3];
  1323.     switch( gl_rmsg[0] )
  1324.     {
  1325.     case MN_SELECTED:
  1326.         done = hdl_menu(wdw_hndl, gl_rmsg[4]);
  1327.         break;
  1328.  
  1329.     case WM_REDRAW:
  1330.         do_redraw(wdw_hndl, (GRECT *) &gl_rmsg[4]);
  1331.         break;
  1332.  
  1333.     case WM_TOPPED:
  1334.         wind_set(wdw_hndl, WF_TOP, 0, 0, 0, 0);
  1335.         break;
  1336.     case WM_CLOSED:
  1337.         done = TRUE;
  1338.         break;
  1339.     case WM_FULLED:
  1340.         do_full(wdw_hndl);
  1341.         break;
  1342.     case WM_ARROWED:
  1343.         switch(gl_rmsg[4])
  1344.         {
  1345.         case WA_UPPAGE:
  1346.             undo_area.g_y = max(undo_area.g_y - undo_area.g_h, 0);
  1347.             break;
  1348.         case WA_DNPAGE:
  1349.             undo_area.g_y += undo_area.g_h;
  1350.             break;
  1351.         case WA_UPLINE:
  1352.             undo_area.g_y = max(undo_area.g_y - YSCALE(16), 0);
  1353.             break;
  1354.         case WA_DNLINE:
  1355.             undo_area.g_y += YSCALE(16);
  1356.             break;
  1357.         case WA_LFPAGE:
  1358.             undo_area.g_x = max(undo_area.g_x-undo_area.g_w, 0);
  1359.             break;
  1360.         case WA_RTPAGE:
  1361.             undo_area.g_x += undo_area.g_w;
  1362.             break;
  1363.         case WA_LFLINE:
  1364.             undo_area.g_x = max(undo_area.g_x - 16, 0);
  1365.             break;
  1366.         case WA_RTLINE:
  1367.             undo_area.g_x += 16;
  1368.             break;
  1369.         }
  1370.         set_work(TRUE);
  1371.         restore_work();
  1372.         break;
  1373.     case WM_HSLID:
  1374.         undo_area.g_x = align_x(umul_div(undo_mfdb.fwp - undo_area.g_w,
  1375.         gl_rmsg[4], 1000));
  1376.         wind_set(dodle_whndl, WF_HSLIDE, umul_div(undo_area.g_x, 1000,
  1377.         undo_mfdb.fwp - undo_area.g_w), 0, 0, 0);
  1378.         restore_work();
  1379.         break;
  1380.     case WM_VSLID:
  1381.         undo_area.g_y = umul_div(undo_mfdb.fh - undo_area.g_h,
  1382.         gl_rmsg[4],1000);
  1383.         wind_set(dodle_whndl, WF_VSLIDE, umul_div(undo_area.g_y, 1000,
  1384.         undo_mfdb.fh - undo_area.g_h), 0, 0, 0);
  1385.         restore_work();
  1386.         break;
  1387.     case WM_SIZED:
  1388.         wind_set(wdw_hndl, WF_CURRXYWH, align_x(gl_rmsg[4]) - 1,
  1389.         gl_rmsg[5], gl_rmsg[6], gl_rmsg[7]);
  1390.         set_work(TRUE);
  1391.         break;
  1392.     case WM_MOVED:
  1393.         gl_rmsg[4] = align_x(gl_rmsg[4]);
  1394.         wind_set(wdw_hndl, WF_CURRXYWH, align_x(gl_rmsg[4]) - 1,
  1395.         gl_rmsg[5], gl_rmsg[6], gl_rmsg[7]);
  1396.         set_work(FALSE);
  1397.         break;
  1398.     } /* switch */
  1399.     return(done);
  1400. } /* hdl_mesag */
  1401.  
  1402. /*------------------------------*/
  1403. /*    do_redraw        */
  1404. /*------------------------------*/
  1405. VOID
  1406. do_redraw(wh, area)        /* redraw specified area from undo bfr    */
  1407. WORD    wh;
  1408. GRECT    *area;
  1409. {
  1410.     GRECT    box;
  1411.     GRECT    dirty_source, dirty_dest;
  1412.  
  1413.     graf_mouse(M_OFF, 0x0L);
  1414.  
  1415.     wind_get(wh, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  1416.     while ( box.g_w && box.g_h )
  1417.     {
  1418.         if (rc_intersect(area, &box))
  1419.         {
  1420.             if (wh == dodle_whndl)
  1421.             {
  1422.                 rc_copy(&box, &dirty_dest);
  1423.                 if (rc_intersect(&work_area, &dirty_dest))
  1424.                 {
  1425.                     dirty_source.g_x = (dirty_dest.g_x - work_area.g_x)
  1426.                         + undo_area.g_x;
  1427.                     dirty_source.g_y = (dirty_dest.g_y - work_area.g_y)
  1428.                         + undo_area.g_y;
  1429.                     dirty_source.g_w = dirty_dest.g_w;
  1430.                     dirty_source.g_h = dirty_dest.g_h;
  1431.                     rast_op(3, &dirty_source, &undo_mfdb,
  1432.                     &dirty_dest, &scrn_mfdb);
  1433.                 }
  1434.             }
  1435.         }
  1436.         wind_get(wh, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  1437.     }
  1438.     graf_mouse(M_ON, 0x0L);
  1439. }
  1440.  
  1441. /*------------------------------*/
  1442. /*    do_full            */
  1443. /*------------------------------*/
  1444. VOID
  1445. do_full(wh)    /* depending on current window state, either make window*/
  1446. WORD    wh;    /*   full size -or- return to previous shrunken size    */
  1447. {
  1448.     GRECT    prev;
  1449.     GRECT    curr;
  1450.     GRECT    full;
  1451.  
  1452.     graf_mouse(M_OFF,0x0L);
  1453.     wind_get(wh, WF_CURRXYWH, &curr.g_x, &curr.g_y, &curr.g_w, &curr.g_h);
  1454.     wind_get(wh, WF_PREVXYWH, &prev.g_x, &prev.g_y, &prev.g_w, &prev.g_h);
  1455.     wind_get(wh, WF_FULLXYWH, &full.g_x, &full.g_y, &full.g_w, &full.g_h);
  1456.     if ( rc_equal(&curr, &full) )
  1457.     {                    /* is full now so change*/
  1458.         /**/                    /*   to previous    */
  1459.         graf_shrinkbox(prev.g_x, prev.g_y, prev.g_w, prev.g_h,
  1460.             full.g_x, full.g_y, full.g_w, full.g_h);
  1461.         wind_set(wh, WF_CURRXYWH, prev.g_x, prev.g_y, prev.g_w, prev.g_h);
  1462.         rc_copy(&save_area, &undo_area);
  1463.         set_work(TRUE);
  1464.         if ((prev.g_x == full.g_x) && (prev.g_y == full.g_y))
  1465.             do_redraw(wh, &work_area);
  1466.     }
  1467.     else
  1468.     {                    /* is not full so make    */
  1469.         /**/                    /*   it full        */
  1470.         rc_copy(&undo_area, &save_area);
  1471.         graf_growbox(curr.g_x, curr.g_y, curr.g_w, curr.g_h,
  1472.             full.g_x, full.g_y, full.g_w, full.g_h);
  1473.         wind_set(wh, WF_CURRXYWH, full.g_x, full.g_y, full.g_w, full.g_h);
  1474.         set_work(TRUE);
  1475.     }
  1476.     graf_mouse(M_ON,0x0L);
  1477. }
  1478. /*
  1479.  
  1480. Page*/
  1481. /************************************************************************/
  1482. /************************************************************************/
  1483. /****                                     ****/
  1484. /****                Mouse Handling                 ****/
  1485. /****                                     ****/
  1486. /************************************************************************/
  1487. /************************************************************************/
  1488.  
  1489.  
  1490. /*------------------------------*/
  1491. /*    hdl_mouse        */
  1492. /*------------------------------*/
  1493. WORD
  1494. hdl_mouse()
  1495. {
  1496.     BOOLEAN    done;
  1497.  
  1498.     if (m_out)
  1499.         graf_mouse(ARROW, 0x0L);
  1500.     else
  1501.         graf_mouse(monumber, mofaddr);
  1502.  
  1503.     m_out = !m_out;
  1504.     done = FALSE;
  1505.     return(done);
  1506. }
  1507.  
  1508.  
  1509. /*
  1510.  
  1511. Page*/
  1512. /************************************************************************/
  1513. /************************************************************************/
  1514. /****                                     ****/
  1515. /****                Button Handling                 ****/
  1516. /****                                     ****/
  1517. /************************************************************************/
  1518. /************************************************************************/
  1519.  
  1520.  
  1521. /*------------------------------*/
  1522. /*    hndl_button        */
  1523. /*------------------------------*/
  1524. WORD
  1525. hndl_button()
  1526. {
  1527.     WORD    done;
  1528.  
  1529.     done = FALSE;
  1530.     if (inside(mousex, mousey, &work_area))
  1531.     {
  1532.         if (dood_fill == TRUE)
  1533.             do_fill(mousex, mousey);
  1534.         else
  1535.             draw_pencil(mousex, mousey);
  1536.     }
  1537.     return(done);
  1538. }
  1539.  
  1540.  
  1541. /*------------------------------*/
  1542. /*    draw_pencil        */
  1543. /*------------------------------*/
  1544. WORD
  1545. draw_pencil(x, y)
  1546. UWORD    x, y;
  1547. {
  1548.     UWORD    pxy[4];
  1549.     WORD    done;
  1550.     UWORD    mflags;
  1551.     UWORD    locount, hicount;
  1552.     UWORD    ev_which, bbutton, kstate, kreturn, breturn;
  1553.  
  1554.     set_clip(TRUE, &work_area);
  1555.     pxy[0] = x;
  1556.     pxy[1] = y;
  1557.  
  1558.     vsl_color(vdi_handle,dodle_shade);
  1559.     vswr_mode(vdi_handle,MD_REPLACE);
  1560.     vsl_type (vdi_handle,IP_1PATT);
  1561.  
  1562.     if (dodle_shade == pen_ink)
  1563.     {
  1564.         vsl_width (vdi_handle,dodle_pen);
  1565.         vsl_ends(vdi_handle, 2, 2);
  1566.         hicount = 0;
  1567.         locount = 125;
  1568.         mflags = MU_BUTTON | MU_M1 | MU_TIMER;
  1569.         graf_mouse(M_OFF, 0x0L);
  1570.     }
  1571.     else
  1572.     {
  1573.         vsf_interior(vdi_handle, 1);
  1574.         vsf_color(vdi_handle, bkgr_color);
  1575.         mflags = MU_BUTTON | MU_M1;
  1576.     }
  1577.  
  1578.     done = FALSE;
  1579.     while (!done)
  1580.     {
  1581.         ev_which = evnt_multi(mflags,
  1582.         0x01, 0x01, 0x00, 
  1583.         1, pxy[0], pxy[1], 1, 1,
  1584.         0, 0, 0, 0, 0,
  1585.         ad_rmsg, locount, hicount,
  1586.         &pxy[2], &pxy[3], &bbutton, &kstate,
  1587.         &kreturn, &breturn);
  1588.  
  1589.         if (ev_which & MU_BUTTON)
  1590.         {
  1591.             if (!(mflags & MU_TIMER))
  1592.                 graf_mouse(M_OFF, 0x0L);
  1593.             if (dodle_shade == pen_ink)
  1594.                 v_pline(vdi_handle, 2, (WORD *) pxy);
  1595.             else
  1596.                 eraser((WORD) pxy[2], (WORD) pxy[3]);
  1597.             graf_mouse(M_ON, 0x0L);
  1598.             done = TRUE;
  1599.         }
  1600.         else
  1601.             if (ev_which & MU_TIMER)
  1602.             {
  1603.                 graf_mouse(M_ON, 0x0L);
  1604.                 mflags = MU_BUTTON | MU_M1;
  1605.             }
  1606.             else
  1607.             {
  1608.                 if (!(mflags & MU_TIMER))
  1609.                     graf_mouse(M_OFF, 0x0L);
  1610.                 if (dodle_shade == pen_ink)
  1611.                 {
  1612.                     v_pline(vdi_handle, 2, (WORD *) pxy);
  1613.                     mflags = MU_BUTTON | MU_M1 | MU_TIMER;
  1614.                 }
  1615.                 else
  1616.                 {
  1617.                     eraser((WORD) pxy[2], (WORD) pxy[3]);
  1618.                     graf_mouse(M_ON,0x0L);
  1619.                 }
  1620.                 pxy[0] = pxy[2];
  1621.                 pxy[1] = pxy[3];
  1622.             }
  1623.     } /* while */
  1624.  
  1625.     set_clip(FALSE, &work_area);
  1626.     save_work();
  1627. }
  1628.  
  1629.  
  1630. /*------------------------------*/
  1631. /*    eraser            */
  1632. /*------------------------------*/
  1633. VOID
  1634. eraser(x, y)            /* erase rectangle of eraser size at x,y */
  1635. WORD    x, y;
  1636. {
  1637.     WORD    erase_xy[4];
  1638.  
  1639.     if (dodle_pen == PEN_FINE)
  1640.     {
  1641.         erase_xy[0] = x - 2;
  1642.         erase_xy[1] = y - 1;
  1643.         erase_xy[2] = x + 2;
  1644.         erase_xy[3] = y + 1;
  1645.     }
  1646.     else
  1647.         if (dodle_pen == PEN_MEDIUM)
  1648.         {
  1649.             erase_xy[0] = x - 4;
  1650.             erase_xy[1] = y - 2;
  1651.             erase_xy[2] = x + 4;
  1652.             erase_xy[3] = y + 2;
  1653.         }
  1654.         else
  1655.         {
  1656.             erase_xy[0] = x - 6;
  1657.             erase_xy[1] = y - 3;
  1658.             erase_xy[2] = x + 6;
  1659.             erase_xy[3] = y + 3;
  1660.         }
  1661.     vr_recfl(vdi_handle, erase_xy);
  1662. }
  1663.  
  1664. /*----------------------------------------------*/
  1665. /*    do_fill        HK 6/30/85        */
  1666. /*----------------------------------------------*/
  1667. WORD
  1668. do_fill(x, y)
  1669. WORD x, y;
  1670. {
  1671.     WORD    index;
  1672.  
  1673.     vsf_interior(vdi_handle, IP_1PATT);
  1674.     vsf_color(vdi_handle, pen_ink);
  1675.     index = -1;    /* for complete fill */
  1676.  
  1677.     graf_mouse(M_OFF, 0x0L);
  1678.     v_contourfill(vdi_handle, x, y, index);
  1679.     save_work();
  1680.     graf_mouse(M_ON, 0x0L);
  1681.     
  1682.     if (first_fill == TRUE)
  1683.     {
  1684.         bkgr_color = pen_ink;
  1685.         first_fill = FALSE;
  1686.     }
  1687. }
  1688.  
  1689. /*
  1690.  
  1691. Page*/
  1692. /************************************************************************/
  1693. /************************************************************************/
  1694. /****                                     ****/
  1695. /****                Doodle Event Handler             ****/
  1696. /****                                     ****/
  1697. /************************************************************************/
  1698. /************************************************************************/
  1699.  
  1700. /*------------------------------*/
  1701. /*    dodle            */
  1702. /*------------------------------*/
  1703. dodle()
  1704. {
  1705.     BOOLEAN    done;
  1706.  
  1707.     key_input = FALSE;
  1708.     done = FALSE;
  1709.     while( !done )        /* loop handling user input until done    */
  1710.     {
  1711.         ev_which = evnt_multi(MU_BUTTON | MU_MESAG | MU_M1 | MU_KEYBD,
  1712.         0x02, 0x01, 0x01, 
  1713.         m_out,
  1714.         (UWORD) work_area.g_x, (UWORD) work_area.g_y,
  1715.         (UWORD) work_area.g_w, (UWORD) work_area.g_h,
  1716.         0, 0, 0, 0, 0,
  1717.         ad_rmsg, 0, 0, 
  1718.         &mousex, &mousey, &bstate, &kstate,
  1719.         &kreturn, &bclicks);
  1720.  
  1721.         wind_update(BEG_UPDATE);
  1722.  
  1723.         if (!(ev_which & MU_KEYBD))
  1724.         {
  1725.             if (key_input)
  1726.             {
  1727. /*                curs_off();    */
  1728.                 key_input = FALSE;
  1729.                 save_work();
  1730.             }
  1731.         }
  1732.  
  1733.         if (ev_which & MU_BUTTON)
  1734.             done = hndl_button();
  1735.  
  1736.         if (ev_which & MU_M1)
  1737.             done = hdl_mouse();
  1738.  
  1739.         if (ev_which & MU_MESAG)
  1740.             done = hdl_message();
  1741.  
  1742.         if (ev_which & MU_KEYBD)
  1743.             done = hndl_keyboard();
  1744.  
  1745.         wind_update(END_UPDATE);
  1746.     }
  1747. }
  1748. /*
  1749.  
  1750. Page*/
  1751. /************************************************************************/
  1752. /************************************************************************/
  1753. /****                                     ****/
  1754. /****                Termination                     ****/
  1755. /****                                     ****/
  1756. /************************************************************************/
  1757. /************************************************************************/
  1758.  
  1759.  
  1760. /*------------------------------*/
  1761. /*    dodle_term        */
  1762. /*------------------------------*/
  1763. dodle_term(term_type)
  1764. WORD    term_type;
  1765. {
  1766.     switch (term_type)    /* NOTE: all cases fall through        */
  1767.     {
  1768.         case (0 /* normal termination */):
  1769.             do_close(dodle_whndl, gl_wfull/2, gl_hfull/2);
  1770.             wind_delete(dodle_whndl);
  1771.         case (3):
  1772.             menu_bar(0x0L, FALSE);
  1773.             Mfree(undo_mfdb.mp);
  1774.         case (2):
  1775.             v_clsvwk( vdi_handle );
  1776.         case (1):
  1777.             appl_exit();
  1778.         case (4):
  1779.             break;
  1780.     }
  1781. }
  1782.  
  1783. /*
  1784.  
  1785. Page*/
  1786. /************************************************************************/
  1787. /************************************************************************/
  1788. /****                                     ****/
  1789. /****                Initialization                 ****/
  1790. /****                                     ****/
  1791. /************************************************************************/
  1792. /************************************************************************/
  1793.  
  1794.  
  1795. /*------------------------------*/
  1796. /*    dodle_init        */
  1797. /*------------------------------*/
  1798. WORD
  1799. dodle_init()
  1800. {
  1801.     WORD    work_in[11];
  1802.     WORD    i;
  1803.     WORD    me_creturn;
  1804.     gl_apid = appl_init();            /* initialize libraries    */
  1805.     if (gl_apid == -1)
  1806.         return(4);
  1807.     wind_update(BEG_UPDATE);
  1808.     graf_mouse(HOURGLASS, 0x0L);
  1809.     if (!rsrc_load( ADDR("DOODLE.RSC") ))
  1810.     {
  1811.         graf_mouse(ARROW, 0x0L);
  1812.         form_alert(1,
  1813.         ADDR("[3][Fatal Error !|DOODLE.RSC|File Not Found][ Abort ]"));
  1814.         return(1);
  1815.     }
  1816.     /* open virtual workstation */
  1817.     /* allocate undo buffer    */
  1818.     for (i=0; i<10; i++)
  1819.     {
  1820.         work_in[i]=1;
  1821.     }
  1822.     work_in[10]=2;
  1823.  
  1824.     gem_handle = graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
  1825.     vdi_handle = gem_handle;
  1826.     v_opnvwk(work_in,&vdi_handle,work_out);
  1827.  
  1828.     if (vdi_handle == 0)
  1829.         return(1);
  1830.  
  1831.     scrn_width = work_out[0] + 1;
  1832.     scrn_height = work_out[1] + 1;
  1833.     scrn_xsize = work_out[3];
  1834.     scrn_ysize = work_out[4];
  1835.  
  1836.     char_fine = work_out[46];
  1837.     char_medium = work_out[48];
  1838.     char_broad = char_medium * 2;
  1839.  
  1840.     vq_extnd(vdi_handle, 1, work_out);
  1841.     scrn_planes = work_out[4];
  1842.  
  1843.     undo_mfdb.fwp = scrn_width;
  1844.     undo_mfdb.fww = undo_mfdb.fwp>>4;
  1845.     undo_mfdb.fh = scrn_height;
  1846.     undo_mfdb.np = scrn_planes;
  1847.     undo_mfdb.ff = 0;
  1848.  
  1849.     buff_size = (LONG)(undo_mfdb.fwp>>3) *
  1850.         (LONG)undo_mfdb.fh *
  1851.         (LONG)undo_mfdb.np;
  1852.     buff_location =
  1853.         undo_mfdb.mp  = Malloc(buff_size);
  1854.     if (undo_mfdb.mp == 0)
  1855.         return(2);
  1856.     scrn_area.g_x = 0;
  1857.     scrn_area.g_y = 0;
  1858.     scrn_area.g_w = scrn_width;
  1859.     scrn_area.g_h = scrn_height;
  1860.     scrn_mfdb.mp = 0x0L;
  1861.  
  1862.     rc_copy(&scrn_area, &undo_area);
  1863.     rast_op(0, &undo_area, &scrn_mfdb, &undo_area, &undo_mfdb);
  1864.  
  1865.     ad_rmsg = ADDR((BYTE *) &gl_rmsg[0]);
  1866.  
  1867.     wind_get(DESK, WF_WORKXYWH, &gl_xfull, &gl_yfull, &gl_wfull, &gl_hfull);
  1868.  
  1869.     /* initialize menu    */
  1870.     rsrc_gaddr(R_TREE, DOODMENU, &gl_menu);
  1871.     do_clnormal();
  1872.     me_creturn = menu_icheck (gl_menu, COLOR1, SELECTED);
  1873.  
  1874.     /* show menu        */
  1875.     menu_bar(gl_menu, TRUE);    
  1876.  
  1877.     dodle_whndl = wind_create(0x0fef, gl_xfull - 1, gl_yfull,
  1878.     gl_wfull, gl_hfull);
  1879.     if (dodle_whndl == -1)
  1880.     {
  1881.         form_alert(1, string_addr(DOODNWDW));
  1882.         return(3);
  1883.     }
  1884.  
  1885.     graf_mouse(HOURGLASS, 0x0L);
  1886.     wind_set(dodle_whndl, WF_NAME,
  1887.     " Dr. Doodle Window ", 0, 0);
  1888.     gl_xfull = align_x(gl_xfull);
  1889.     do_open(dodle_whndl, gl_wfull/2, gl_hfull/2, align_x(gl_xfull),
  1890.         gl_yfull, gl_wfull, gl_hfull);
  1891.     wind_get(dodle_whndl, WF_WORKXYWH,
  1892.     &work_area.g_x, &work_area.g_y,
  1893.     &work_area.g_w, &work_area.g_h);
  1894.  
  1895.     set_work(TRUE);
  1896.     rc_copy (&undo_area, &save_area);
  1897.  
  1898.     graf_mouse(ARROW,0x0L);
  1899.     wind_update(END_UPDATE);
  1900.     return(0);
  1901. }
  1902. /*
  1903.  
  1904. Page*/
  1905. /************************************************************************/
  1906. /************************************************************************/
  1907. /****                                     ****/
  1908. /****                Main Program                 ****/
  1909. /****                                     ****/
  1910. /************************************************************************/
  1911. /************************************************************************/
  1912.  
  1913.  
  1914. /*------------------------------*/
  1915. /*    main()            */
  1916. /*------------------------------*/
  1917. main()
  1918. {
  1919.     WORD    term_type;
  1920.  
  1921.     if (!(term_type = dodle_init()))
  1922.         dodle();
  1923.     dodle_term(term_type);
  1924. }
  1925.  
  1926. /*
  1927. * umul_div() 
  1928. */
  1929.  
  1930. int umul_div(m1, m2, d1)
  1931. unsigned int m1;
  1932. unsigned int m2;
  1933. unsigned int d1;
  1934. {
  1935.     unsigned int x;
  1936.  
  1937.     x = m2;
  1938.     x = x << 1;
  1939.     x *= m1;
  1940.     x /= d1;
  1941.     x += 1;
  1942.     x = x >> 1;
  1943.  
  1944.     return(x);
  1945. }
  1946.