/********************************************************************** MEGABLIT.C - a GEM based drawing program 1/06/89 18:00 ------------------------------------------------------ Skeleton of GEM application (c) 1985 by Atari MEGABLIT routines (c) 1986,87,88,89 by Darek Mihocka This code was first written 3 years ago when I knew NOTHING about programming GEM. I tried to clean it up but I think it's a lost case! (Did I really write code like these. Scary!) It's been fixed up to use embedded resource trees and to compile under Laser C. I didn't even try to fix any bugs. It's hopeless! I added in comments here and there, as if that'll help anyone decrypt this code. **********************************************************************/ #include #include #include #include #include #include #include #include "megablit.h" #define TRUE 1 #define FALSE 0 #define WI_KIND (CLOSER|NAME|VSLIDE|HSLIDE|UPARROW|DNARROW|LFARROW|RTARROW) /* arrow messages Megamax forgot to include!! */ #define WA_UPPAGE 0 #define WA_DNPAGE 1 #define WA_UPLINE 2 #define WA_DNLINE 3 #define WA_LFPAGE 4 #define WA_RTPAGE 5 #define WA_LFLINE 6 #define WA_RTLINE 7 #define min(x,y) ((x>y) ? y : x ) #define max(x,y) ((x>y) ? x : y ) #define abs(x) ((x<0) ?-x : x ) #define swap(x,y) { x+=y; y=x-y; x-=y; } extern int gl_apid; /* bogus bindings not really needed */ int contrl[12], intin[128], ptsin[128], intout[128], ptsout[128]; int gl_wchar, gl_hchar, gl_wbox, gl_hbox; /* system sizes */ int phys_handle; /* physical workstation handle */ int handle; /* virtual workstation handle */ int wi_handle; /* window handle */ int top_window; /* handle of topped window */ int xdesk,ydesk,hdesk,wdesk; /* desktop area */ int xwork,ywork,hwork,wwork; /* work area */ int msgbuff[8]; /* event message buffer */ int keycode; /* keycode returned by event-keyboard */ int ret; /* dummy return variables */ char dummy[4]; int work_in[11]; /* Input to GSX parameter array */ int work_out[57]; /* Output from GSX parameter array */ int pxyarray[10]; /* input point array */ /* array of pointers to trees */ extern long rs_trindex[]; /* pointers to dialog box and menu bar */ OBJECT *dialog, *menu, *fill_box, *default_box, *objTitle; MFDB screen, copybuf, bigscreen, textscreen, undoscreen; /* memory definition blocks for buffers */ int rez, /* screen mode - 0=low 1=med 2=hi */ rscalex, rscaley, rplane, rwdwidth, rbigwidth, *buf, *bigbuf, /* pointer to copy buffer, and large buffer */ *textbuf, *undobuf, true_wwork, true_hwork, /* real wwork & hwork */ zoom_wwork, zoom_hwork, /* what they are during zoom */ zxwork, zywork, zwwork, zhwork, /* zoom window dimensions */ mag_x, mag_y, /* magnification factors during zoom */ zbox_x, zbox_y, /* co-ordinates of zoom box */ zbox_w, zbox_h, /* height of zoom box */ SnapSize, /* snap size in pixels */ LineWidth, /* line width in pixels */ drew, /* flag to re-draw the zoom window */ xsize, ysize , /* size of total picture (should be 1024x1024) */ xpos, ypos , /* position of left corner of window */ x_undo, y_undo, /* position when undo buffer saved */ x, y, /* screen co-ordinates of mouse */ x2, y2, /* opposite corner of rubber box */ ox, oy, /* original (x,y) used by LINE, etc. */ state, but, /* keyboard state and mouse button state */ draw_color, /* which of the 16 registers is being drawn with */ draw_mode, /* what type of drawing: line, circle, etc. */ copy_mode, /* 1-block 2-OR 3-XOR 4-reverse */ fill_flag, /* filled/unfilled polygons */ snap_flag, /* whether or not mouse snaps */ dump_flag , /* 0-no 1-starting a new dump 2-doing a dump */ zoom_flag, /* sez whether we have the zoom window on */ mdFill, /* fill pattern 0-35 */ mdLW, /* line width 0-4 */ mdSS, /* snap size 0-4 */ mdLS, /* line start in pixels */ mdLE, /* line end in pixels */ valid_fn, /* if current path and filename are valid */ block_mode , /* 0-off 1-getting copy block 2-copying */ blockw, blockh, /* width and height of block */ maxw, maxh, /* used by copy block routine to clip block */ mode_table[5], /* also used by above to select copy type */ arr_pnts[20] , /* used to pass VDI an array of co-ordinates */ Dheader[17]; /* DEGAS header */ char *path, selection[15], filename[80]; /* file I/O variables */ int palette[3][16] = { { 0x777, 0x700, 0x070, 0x007, 0x770, 0x463, 0x635, 0x555, 0x333, 0x166, 0x717, 0x661, 0x400, 0x040, 0x004, 0x000 }, { 0x777, 0x700, 0x070, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }, { 0x777, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 } }; int scalex[3] = {1,2,2}; int scaley[3] = {1,1,2}; int plane[3] = {4,2,1}; int wdwidth[3] = {20,40,40}; int bigwidth[3] = {24,48,48}; int mpLW[5] = { 1,3,5,7,9 }; int mpSS[5] = { 4,6,8,12,16 }; /****************************************************************/ open_vwork() { register int i; int handle; for(i=0;i<10;work_in[i++]=1) ; work_in[10]=2; /* raster co-ordinates */ handle=phys_handle; v_opnvwk(work_in,&handle,work_out); return(handle); } /****************************************************************/ set_clip(x,y,w,h) int x,y,w,h; { int clip[4]; clip[0]=x; clip[1]=y; clip[2]=x+w-1; clip[3]=y+h-1; vs_clip(handle,1,clip); } /****************************************************************/ open_window(name, options, x, y, width, height, wx, wy, ww, wh) char *name; int options, x, y, width, height; int *wx, *wy, *ww, *wh; { wi_handle=wind_create(options,x,y,width,height); wind_set(wi_handle, WF_NAME,name,0,0); graf_growbox(x+width/2,y+height/2, gl_wbox,gl_hbox,x,y,width,height); wind_open(wi_handle,x,y,width,height); wind_get(wi_handle,WF_WORKXYWH,wx,wy,ww,wh); return(wi_handle); } /****************************************************************/ do_redraw(xc,yc,wc,hc) int xc,yc,wc,hc; { GRECT t1,t2; graf_mouse(M_OFF,0L); wind_update(TRUE); t2.g_x=xc; t2.g_y=yc; t2.g_w=wc; t2.g_h=hc; wind_get(wi_handle,WF_FIRSTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h); while (t1.g_w && t1.g_h) { if (rc_intersect(&t2,&t1)) { set_clip(t1.g_x,t1.g_y,t1.g_w,t1.g_h); buf_to_scr (t1.g_x-xwork, t1.g_y-ywork, t1.g_w, t1.g_h); } wind_get(wi_handle,WF_NEXTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h); } if (zoom_flag) do_zoom(); set_clip(xwork,ywork,wwork,hwork); wind_update(FALSE); graf_mouse(M_ON,0L); } /****************************************************************/ do_dialog(dialog) register OBJECT *dialog; { int cx, cy, cw, ch, xc, yc, msg; form_center(dialog, &cx, &cy, &cw, &ch); scr_to_buf(cx-xwork,cy-ywork,cw+4,ch+4); /* buffer the box */ xc = cx + cw/2; yc = cy + ch/2; form_dial(FMD_START, cx, cy, cw, ch, cx, cy, cw, ch); form_dial(FMD_GROW, xc,yc,0,0, cx, cy, cw, ch); objc_draw(dialog, 0, 10, cx, cy, cw, ch); msg = form_do(dialog, 0); form_dial(FMD_SHRINK, xc,yc,0,0, cx, cy, cw, ch); form_dial(FMD_FINISH, 0,0,0,0, cx, cy, cw, ch); buf_to_scr(cx-xwork,cy-ywork,cw+4,ch+4); /* unbuffer the box */ return(msg); } /***************************************************************** ** init resource, allocate memory, initialize screen, and paint ** *****************************************************************/ main() { register long memfree; register int xpix, ypix; appl_init(); rez=Getrez(); rscalex=scalex[rez]; rscaley=scaley[rez]; rplane=plane[rez]; rwdwidth=wdwidth[rez]; rbigwidth=bigwidth[rez]; #ifdef NEVER if (!rsrc_load("megablit.rsc")) { /* load MEGABLIT.RSC file */ form_alert(1,"[0][ | no RCS | file | ][ oh ya! ]"); exit(0); } #else rsc_fix(); #endif buf = (int *) Malloc(32000L); /* allocate copy buffer */ undobuf = (int *) Malloc(32000L); /* allocate undo buffer */ memfree = Malloc(-1L); if (memfree<=60000L) { form_alert(1,"[0][ | Out of | Memory | ][ aack!! ]"); exit(0); } /* I've completely forgotten how this allocation of the buffer is supposed to work, but somehow it does! */ xpix=1; ypix=1; /* 320*200 or 640*400 */ if (memfree>=100000L) xpix *=2; /* a 64K screen - 640*200 or 1280*400*/ if (memfree>= 200000L) ypix *=2; /* a 128K screen - 640*400 or 1280*800 */ if (memfree>= 400000L) xpix *=2; /* a 256K screen - 1280*400 or 2560*800 */ if (memfree>= 800000L) ypix *=2; /* a 512K screen - 1280*800 or 2560*1600*/ /* size of MEGABLIT drawing area */ xsize=384*xpix*rscalex; ysize=256*ypix*rscaley; bigbuf = (int *) Malloc((long)xsize*(long)ysize/8L*(long)rplane); graf_mouse(M_OFF,0L); graf_mouse(OUTLN_CROSS,0L); bigscreen.fd_addr = (long) bigbuf; /* FDB for virtual screen */ bigscreen.fd_w = xsize; /* virtual screen size */ bigscreen.fd_h = ysize; bigscreen.fd_wdwidth = rbigwidth*xpix; /* # of integers in one line */ bigscreen.fd_stand = 0; /* pixel co-ordinates */ bigscreen.fd_nplanes = rplane; /* # of bit planes */ screen.fd_addr = Physbase(); /* FDB for desktop */ screen.fd_w = 320*xpix*rscalex; screen.fd_h = 200*ypix*rscaley; screen.fd_wdwidth = rwdwidth; screen.fd_stand = 0; screen.fd_nplanes = rplane; copybuf.fd_addr = (long) buf; /* FDB for copy buffer */ copybuf.fd_w = 320*xpix*rscalex; copybuf.fd_h = 200*ypix*rscaley; copybuf.fd_wdwidth = rwdwidth; copybuf.fd_stand = 0; copybuf.fd_nplanes = rplane; undoscreen.fd_addr = (long) undobuf; /* FDB for undo buffer */ undoscreen.fd_w = 320*ypix*rscalex; undoscreen.fd_h = 200*ypix*rscaley; undoscreen.fd_wdwidth = rwdwidth; undoscreen.fd_stand = 0; undoscreen.fd_nplanes = rplane; path = "A:\\*.PI1\000\000\000\000\000 "; path[0] = 'A' + Dgetdrv(); path[7] = rez + '1'; selection[0] = 0; valid_fn = FALSE; #ifdef NEVER rsrc_gaddr(0, DEFAULTS, &default_box); rsrc_gaddr(0, FILLS, &fill_box); rsrc_gaddr(0, MAIN_BAR, &menu); #else menu = (OBJECT *) rs_trindex[MAIN_BAR]; fill_box = (OBJECT *) rs_trindex[FILLS]; default_box = (OBJECT *) rs_trindex[DEFAULTS]; objTitle = (OBJECT *) rs_trindex[TITLE]; #endif menu_bar (menu,TRUE); phys_handle=graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox); wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk); handle = open_vwork(); open_window(" no name ", WI_KIND, xdesk, ydesk, wdesk, hdesk, &xwork, &ywork, &wwork, &hwork ); mode_table[1] = 3; /* conversion between the 16 copy types to 4 */ mode_table[2] = 7; mode_table[3] = 6; mode_table[4] = 8; true_wwork = wwork; true_hwork = hwork; zoom_wwork = wwork/2; zoom_hwork = hwork; zbox_w = zbox_h = 16; /* 16*16 zoom box */ draw_color = 1; /* black */ menu[COLOR1].ob_state |= CHECKED; /* initialize BLACK checkmark */ set_color(draw_color); copy_mode = 1; /* destructive draw */ menu[REPLACE].ob_state ^= CHECKED; /* initialize REPLACE checkmark */ snap_flag = fill_flag = FALSE; draw_mode = DRAW; menu[draw_mode].ob_state ^= CHECKED; /* initialize DRAW checkmark */ zoom_flag = FALSE; menu[ZOOM].ob_state &= ~CHECKED; vswr_mode(handle,copy_mode); vsf_perimeter(handle,0); clear_work(); /* clear out work area and initialize position */ /* disable cursor */ graf_mouse(ARROW,0L); graf_mouse(M_ON,0L); do_dialog(objTitle); /* show title... */ multi(); /* ... and paint!! */ /* enable cursor */ wind_close(wi_handle); graf_shrinkbox(xwork+wwork/2,ywork+hwork/2, gl_wbox,gl_hbox,xwork,ywork,wwork,hwork); wind_delete(wi_handle); menu_bar (menu,FALSE); v_clsvwk(handle); Mfree(bigbuf); /* give memory back to nice operating system */ Mfree(buf); appl_exit(); /* bye bye */ } /***************************************************************** ** anything that ever happens goes through the multi() routine ** *****************************************************************/ multi() { register int event, quit=0; do { event = evnt_multi(MU_MESAG | MU_BUTTON | MU_KEYBD, 1,1,TRUE , 0,0,0,0,0, 0,0,0,0,0, msgbuff,0,0,&x,&y,&but,&state,&keycode,&ret); if (snap_flag) snap (&x,&y); drew = FALSE; /* modified zoom window flag */ wind_update(TRUE); if (event & MU_KEYBD) { keycode = (keycode>>8)&0x00FF; if (keycode==0x61) undo_to_scr(); else if (keycode==0x62) do_dialog(objTitle);; } else if (event & MU_MESAG) { switch (msgbuff[0]) { case MN_SELECTED: switch(msgbuff[3]) { case DESK: do_dialog(objTitle);; menu_tnormal(menu,DESK,1); break; case FILE: switch (msgbuff[4]) { case M_LOAD: if (get_fn()) load_file(filename); break; case M_SAVE: valid_fn = get_fn(); if (!valid_fn) break; case M_UPDATE: if (valid_fn) save_file(filename); else form_alert(1, "[0][ | Currently | untitled! | ][ forgot! ]"); break; case M_QUIT: quit = 2 - form_alert(1, "[0][ | Leaving??? | ][ Yes | No ]"); break; case M_NEW: if (1== (form_alert(1, "[0][ | Start | fresh?? | ][ Yes | No! ]"))) clear_work(); break; } menu_tnormal(menu,FILE,1); break; case OPTIONS: { int selection; selection=msgbuff[4]; switch (selection) { case ZOOM_IN: if (zoom_flag && zbox_w>4) { zbox_w /= 2; zbox_h /= 2; drew=TRUE; } break; case ZOOM_OUT: if (zoom_flag && zbox_w<64) { zbox_w *= 2; zbox_h *= 2; drew=TRUE; } break; case OPT_FILL: select_fill(); break; case OPT_OTHR: select_other(); break; default: if (rez==2 && selection!=COLOR0 && selection!=COLOR1) break; if (rez==1 && selection!=COLOR0 && selection!=COLOR1 && selection!=COLOR2 && selection!=COLOR3) break; menu[COLOR0].ob_state &= ~CHECKED; menu[COLOR1].ob_state &= ~CHECKED; menu[COLOR2].ob_state &= ~CHECKED; menu[COLOR3].ob_state &= ~CHECKED; menu[COLOR4].ob_state &= ~CHECKED; menu[COLOR5].ob_state &= ~CHECKED; menu[COLOR6].ob_state &= ~CHECKED; menu[COLOR7].ob_state &= ~CHECKED; menu[COLOR8].ob_state &= ~CHECKED; menu[COLOR9].ob_state &= ~CHECKED; menu[COLORA].ob_state &= ~CHECKED; menu[COLORB].ob_state &= ~CHECKED; menu[COLORC].ob_state &= ~CHECKED; menu[COLORD].ob_state &= ~CHECKED; menu[COLORE].ob_state &= ~CHECKED; menu[COLORF].ob_state &= ~CHECKED; menu[selection].ob_state |= CHECKED; /* This is NOT the way to do this. Simply sorting the object and doing draw_color = selection - COLOR0; would have worked! */ switch (selection) { case COLOR0: draw_color = 0; break; case COLOR1: draw_color = 1; break; case COLOR2: draw_color = 2; break; case COLOR3: draw_color = 3; break; case COLOR4: draw_color = 4; break; case COLOR5: draw_color = 5; break; case COLOR6: draw_color = 6; break; case COLOR7: draw_color = 7; break; case COLOR8: draw_color = 8; break; case COLOR9: draw_color = 9; break; case COLORA: draw_color = 0xA; break; case COLORB: draw_color = 0xB; break; case COLORC: draw_color = 0xC; break; case COLORD: draw_color = 0xD; break; case COLORE: draw_color = 0xE; break; case COLORF: draw_color = 0xF; break; } set_color(draw_color); break; } menu_tnormal(menu,OPTIONS,1); } case MODE: switch (msgbuff[4]) { case POINT: case DRAW: case LINE: case RAY: case BOX: case ARC: case PIE: case ELLIPSE: case RND_BOX: case POLYGON: menu[draw_mode].ob_state ^= CHECKED; draw_mode = msgbuff[4]; menu[draw_mode].ob_state ^= CHECKED; block_mode = 0; /* de-activate block_mode */ menu[COPY].ob_state &= ~CHECKED; menu[MARK].ob_state &= ~CHECKED; menu[DELETE].ob_state &= ~CHECKED; break; case FILL: menu[FILLFLAG].ob_state ^= CHECKED; fill_flag ^= TRUE; break; case SNAP: menu[SNAPFLAG].ob_state ^= CHECKED; snap_flag ^= TRUE; break; case REPLACE: copy_mode = 1; menu[REPLACE].ob_state |= CHECKED; menu[TRANSP].ob_state &= ~CHECKED; menu[XOR].ob_state &= ~CHECKED; menu[INVERSE].ob_state &= ~CHECKED; break; case TRANSP: copy_mode = 2; menu[REPLACE].ob_state &= ~CHECKED; menu[TRANSP].ob_state |= CHECKED; menu[XOR].ob_state &= ~CHECKED; menu[INVERSE].ob_state &= ~CHECKED; break; case XOR: copy_mode = 3; menu[REPLACE].ob_state &= ~CHECKED; menu[TRANSP].ob_state &= ~CHECKED; menu[XOR].ob_state |= CHECKED; menu[INVERSE].ob_state &= ~CHECKED; break; case INVERSE: copy_mode = 4; menu[REPLACE].ob_state &= ~CHECKED; menu[TRANSP].ob_state &= ~CHECKED; menu[XOR].ob_state &= ~CHECKED; menu[INVERSE].ob_state |= CHECKED; break; case MARK: block_mode = 1; menu[MARK].ob_state |= CHECKED; menu[COPY].ob_state &= ~CHECKED; menu[DELETE].ob_state &= ~CHECKED; break; case COPY: block_mode = (blockh+blockw) ? 2 : 0; menu[COPY].ob_state &= ~CHECKED; menu[MARK].ob_state &= ~CHECKED; menu[DELETE].ob_state &= ~CHECKED; if (block_mode) menu[COPY].ob_state |= CHECKED; break; case DELETE: block_mode = 3; menu[MARK].ob_state &= ~CHECKED; menu[COPY].ob_state &= ~CHECKED; menu[DELETE].ob_state |=CHECKED; break; case ZOOM: menu[ZOOMFLAG].ob_state ^= CHECKED; zoom_flag ^= TRUE; if (zoom_flag) { scr_to_buf(0,0,wwork,hwork); wwork = zoom_wwork; hwork = zoom_hwork; buf_to_scr(0,0,wwork,hwork); update_slider(1,1); update_slider(-1,-1); drew=FALSE; } else { scr_to_buf(0,0,wwork,hwork); wwork = true_wwork; hwork = true_hwork; buf_to_scr(0,0,wwork,hwork); update_slider(1,1); update_slider(-1,-1); } break; case UNDO: undo_to_scr(); break; } menu_tnormal(menu,MODE,1); break; } case WM_REDRAW: do_redraw(msgbuff[4],msgbuff[5],msgbuff[6],msgbuff[7]); break; case WM_NEWTOP: case WM_TOPPED: scr_to_buf(0,0,wwork,hwork); wind_set(wi_handle,WF_TOP,0,0,0,0); break; case WM_CLOSED: quit++; break; case WM_VSLID: update_slider(0, /*dx=0*/ (int)((long)msgbuff[4]*((long)(ysize-hwork))/1000L)-ypos); break; case WM_HSLID: update_slider( (int)((long)msgbuff[4]*((long)(xsize-wwork))/1000L)-xpos,0); break; case WM_ARROWED: drew = TRUE; switch(msgbuff[4]) { case WA_UPPAGE: update_slider(0,-hwork/2); break; case WA_DNPAGE: update_slider(0,hwork/2); break; case WA_LFPAGE: update_slider(-wwork/2,0); break; case WA_RTPAGE: update_slider(wwork/2,0); break; case WA_UPLINE: update_slider(0,-8); break; case WA_DNLINE: update_slider(0,8); break; case WA_LFLINE: update_slider(-8,0); break; case WA_RTLINE: update_slider(8,0); break; } /* switch (msgbuff[4]) */ } /* switch (msgbuff[0]) */ if (!fill_flag) graf_mouse(OUTLN_CROSS,0L); /* restore crosshairs */ else graf_mouse(THICK_CROSS,0L); } else { drew = TRUE; vswr_mode(handle,copy_mode); /* go to proper blitting mode */ scr_to_undo(); /* UNDO wasn't picked, so update */ if (zoom_flag && x>= zxwork) /* if inside zoom box... */ { int zx, zy, ar[4], z, ozx = -1, ozy = -1, sel=FALSE; do { zx = (x-zxwork-2); zy = (y-zywork-2); if (zx%mag_x || zy%mag_y) /* null zones between big pixels */ { zx /= mag_x; zy /= mag_y; if (zx>=0 && zx=0 && zy=0 && zx=0 && zy24)?3:2); vsf_style(handle,mdFill%24); vsf_color(handle,draw_color); v_contourfill(handle,x,y,-1); graf_mouse(M_ON,0L); } break; case LINE: ox = x; oy = y; rubber_shape(LINE,ox,oy,&x2,&y2); graf_mouse(M_OFF,0L); vsl_ends(handle,mdLS,mdLE); vsl_width(handle,LineWidth); v_pline(handle,2,arr_pnts); graf_mouse(M_ON,0L); break; case POLYGON: { int points=1, ar[40]; ar[0] = x2 = x; ar[1] = y2 = y; do { ox = x2; oy = y2; rubber_shape(LINE,ox,oy,&x2,&y2); graf_mouse(M_OFF,0L); v_pline(handle,2,arr_pnts); graf_mouse(M_ON,0L); ar[points*2] = x2; ar[points*2+1] = y2; points++; } while (x2!=ox || y2!=oy); if (fill_flag) { graf_mouse(M_OFF,0L); v_fillarea(handle,points,ar); graf_mouse(M_ON,0L); } } break; case RAY: arr_pnts[0] = x; arr_pnts[1] = y; do { arr_pnts[2] = x; arr_pnts[3] = y; graf_mouse(M_OFF,0L); vsl_ends(handle,mdLS,mdLE); vsl_width(handle,LineWidth); v_pline(handle,2,arr_pnts); graf_mouse(M_ON,0L); wait_mouse(&x,&y,&but); } while (but); break; case BOX: rubber_shape(BOX,x,y,&x2,&y2); graf_mouse(M_OFF,0L); vsl_ends(handle,0,0); vsl_width(handle,LineWidth); if (fill_flag) { arr_pnts[0] = x; arr_pnts[1] = y; arr_pnts[2] = x2; arr_pnts[3] = y2; v_bar(handle,arr_pnts); /* fill in the interior */ } else v_pline(handle,5,arr_pnts); graf_mouse(M_ON,0L); break; case ELLIPSE: rubber_shape(ELLIPSE,x,y,&x2,&y2); graf_mouse(M_OFF,0L); if (fill_flag) v_ellipse(handle,(x+x2)/2,(y+y2)/2,(x2-x)/2,(y2-y)/2); else v_ellarc(handle,(x+x2)/2,(y+y2)/2,(x2-x)/2,(y2-y)/2,0,3595); graf_mouse(M_ON,0L); break; case RND_BOX: rubber_shape(BOX,x,y,&x2,&y2); arr_pnts[0] = x; arr_pnts[1] = y; arr_pnts[2] = x2; arr_pnts[3] = y2; graf_mouse(M_OFF,0L); if (fill_flag) v_rfbox(handle,arr_pnts); else v_rbox(handle,arr_pnts); graf_mouse(M_ON,0L); break; case ARC: case PIE: { int xx, yy, rr, ang1, ang2, ang3, txx, tyy, tang1, tang3, trr; vq_mouse(handle,&but,&x,&y); if (!but) break; if (snap_flag) snap (&x,&y); rubber_shape(LINE,x,y,&x2,&y2); ox = x; oy = y; txx = tyy = trr = tang1 = tang3 = 0; evnt_mouse(1,x,y,1,1,&x,&y,&but,&state); graf_mouse(POINT_HAND,0L); /* do a pointed hand for arc */ vswr_mode(handle,3); do { /* draw arcs when button up */ pts_to_arc(ox,oy,x,y,x2,y2,&xx,&yy,&rr); ang1 = calc_angle(xx,yy,ox,oy); ang2 = calc_angle(xx,yy,x,y); ang3 = calc_angle(xx,yy,x2,y2); if (ang2blockw) maxw=blockw; if (maxh>blockh) maxh=blockh; arr_pnts[2] = maxw; arr_pnts[3] = maxh; arr_pnts[4] = max(x,xwork); arr_pnts[5] = max(y,ywork); arr_pnts[6] = max(x,xwork)+maxw; arr_pnts[7] = max(y,ywork)+maxh; if ((maxw>0) && (maxh>0)) { graf_mouse(M_OFF,0L); vro_cpyfm(handle,mode_table[copy_mode], arr_pnts,©buf,&screen); graf_mouse(M_ON,0L); } wait_mouse(&x,&y,&but); } while(but); } /* if mark or copy */ else if (block_mode==3) { /* delete a new block */ int blockw, blockh; rubber_shape(BOX,x,y,&x2,&y2); if (x20) --tp; strcpy (&filename[tp+1],selection); return stat; } /****************************************************************/ load_file(fn) char *fn; { register int fhand, stat; int ar[8]; if ((fhand = Fopen(fn,O_RDONLY))<0) goto err_close; if ((stat=Fread (fhand,34L,&Dheader[0]))<0) goto err_close; if ((stat=Fread (fhand,32000L,buf))<0) goto err_close; Fclose (fhand); valid_fn = TRUE; if (xpos>xsize-wwork) xpos = xsize-wwork; if (ypos>ysize-hwork) ypos = ysize-hwork; ar[0] = 0; /* copy file from copy buffer to big screen buffer */ ar[1] = 0; ar[2] = 320*rscalex-1; ar[3] = 200*rscaley-1; ar[4] = xpos; ar[5] = ypos; ar[6] = xpos+320*rscalex-1; ar[7] = ypos+200*rscaley-1; graf_mouse(M_OFF,0L); vro_cpyfm(handle,mode_table[copy_mode],ar,©buf,&bigscreen); buf_to_scr(0,0,wwork,hwork); /* and update window display */ Setpalette(&Dheader[1]); blockh = blockw = 0; wind_set(wi_handle, WF_NAME,fn,0,0); graf_mouse(M_ON,0L); return(0); err_close: Fclose (fhand); form_alert(1,"[0][ | Error | loading | picture | ][ darn ]"); } /****************************************************************/ save_file(fn) char* fn; { register int fhand, stat; int ar[8]; register int cc; for (cc=0; cc<16; cc++) Dheader[cc+1]= Setcolor(cc,-1); graf_mouse(M_OFF,0L); scr_to_buf(0,0,wwork,hwork); /* save screen to big buffer */ if (xpos>xsize-wwork) xpos = xsize-wwork; /* then make sure picture fits */ if (ypos>ysize-hwork) ypos = ysize-hwork; ar[4] = 0; /* copy file from big screen buffer to copy buffer */ ar[5] = 0; ar[6] = 320*rscalex-1; ar[7] = 200*rscaley-1; ar[0] = xpos; ar[1] = ypos; ar[2] = xpos+320*rscalex-1; ar[3] = ypos+200*rscaley-1; Dheader[0] = Getrez(); vro_cpyfm(handle,3,ar,&bigscreen,©buf); buf_to_scr(0,0,wwork,hwork); /* and update window display */ graf_mouse(M_ON,0L); if ((fhand = Fcreate(fn,0))<0) goto err_close2; if ((stat=Fwrite (fhand,34L,&Dheader[0]))<0) goto err_close2; if ((stat=Fwrite (fhand,32000L,buf))<0) goto err_close2; Fclose (fhand); valid_fn = TRUE; return(0); err_close2: Fclose (fhand); form_alert(1,"[0][ | error | writing | picture | ][ darn ]"); } /****************************************************************/ /* This function is given the co-ordinates of 3 points */ /* and it tries to calculate the centre and radius of */ /* a circle that passes through the 3 points. */ pts_to_arc(px1,py1,px2,py2,px3,py3,xx,yy,rr) int px1,py1,px2,py2,px3,py3, *xx, *yy, *rr; { register long rad, rad2; double a1, b1, a2, b2, a3, b3, num, den, cx, cy; a1 = (double) px1; b1 = (double) py1; a2 = (double) px2; b2 = (double) py2; a3 = (double) px3; b3 = (double) py3; num = (b1-b2)*(b1-b3)*(b3-b2) - a1*(a2-a1)*(b3-b2) + a3*(a2-a3)*(b1-b2); den = (a2-a3)*(b1-b2) - (a2-a1)*(b3-b2); if (den) cx = (num/den + a2)/2; /* a solution for x center */ else cx = 0; /* a straight line */ num = (a1-a2)*(a1-a3)*(a3-a2) - b1*(b2-b1)*(a3-a2) + b3*(b2-b3)*(a1-a2); den = (b2-b3)*(a1-a2) - (b2-b1)*(a3-a2); if (den) cy = (num/den + b2)/2; /* a solution for y center */ else cy = 0; /* a straight line */ rad2 = (long)((a3-cx)*(a3-cx) + (b3-cy)*(b3-cy)); /* radius ^ 2 */ if (rad2>250000L) rad2=250000; for (rad=0L; rad*rad0) return(900); if (dx==0 && dy<0) return(2700); if (dx>=0 && dy==0) return(0); if (dx<0 && dy==0) return(1800); a = abs(dx); b = abs(dy); slope = (double)(b)/(double)(a); angle = atan(slope)*1800.0/3.14159265; /* 0 to 900 decidegrees */ if (dx<0) angle = 1800.0-angle; if (dy<0) angle = 3600.0-angle; return( (int)angle ); } /****************************************************************/ wait_mouse (x, y, but) register int *x, *y, *but; { int oldx, oldy, oldbut; vq_mouse(handle,&oldbut,&oldx,&oldy); if (snap_flag) snap(&oldx,&oldy); do { vq_mouse(handle,but,x,y); if (snap_flag) snap (x,y); } while (*x==oldx && *y==oldy & *but==oldbut); } /****************************************************************/ rubber_shape (shape_type,xstart,ystart, xend, yend) int xstart,ystart, shape_type, *xend, *yend; { int curx=xstart, cury=ystart, radx, rady, not_pressed=TRUE; vswr_mode(handle,3); vsl_udsty(handle,0xA8A8); vsl_type(handle,7); /* dotted lines */ vsl_width(handle,1); arr_pnts[0]= arr_pnts[2] = arr_pnts[4] = arr_pnts[6] =arr_pnts[8] = xstart; arr_pnts[1] = arr_pnts[3] =arr_pnts[5] = arr_pnts[7] = arr_pnts[9]= ystart; wait_mouse(&curx,&cury,&but,&state); while (but | not_pressed) { if (but) not_pressed = FALSE; graf_mouse(M_OFF,0L); if (shape_type==LINE) { arr_pnts[2] = curx; arr_pnts[3] = cury; v_pline(handle,2,arr_pnts); } else { arr_pnts[2] = curx; arr_pnts[4] = curx; arr_pnts[5] = cury; arr_pnts[7] = cury; v_pline(handle,5,arr_pnts); if (shape_type==ELLIPSE) { radx = (curx-xstart)/2; rady = (cury-ystart)/2; v_ellarc(handle,xstart+radx,ystart+rady,radx,rady,0,3595); } } graf_mouse(M_ON,0L); wait_mouse(&curx,&cury,&but,&state); graf_mouse(M_OFF,0L); if (shape_type==LINE) v_pline(handle,2,arr_pnts); else { v_pline(handle,5,arr_pnts); /* undraw shape as moving or exiting */ if (shape_type==ELLIPSE) v_ellarc(handle,xstart+radx,ystart+rady,radx,rady,0,3595); } graf_mouse(M_ON,0L); }; vswr_mode(handle,copy_mode); /* restore drawing mode */ vsl_type(handle,1); *xend = curx; *yend = cury; } /****************************************************************/ clear_work() { /* erase work area */ register long word, limit; register int *zap; zap = bigbuf; limit = (long)(xsize)*(long)(ysize)/16L*(long)rplane; for (word=0; wordob_x; yFill = yTop + obj->ob_y; obj->ob_flags = SELECTABLE | EXIT; vsf_interior(handle,(FillT>23)?3:2); vsf_style(handle,FillT%24); vsf_color(handle,draw_color); v_contourfill(handle,xFill+8,yFill+8,-1); } obj = &fill_box[FILLSHOW]; xFill = xTop + obj->ob_x + 3; yFill = yTop + obj->ob_y + 2; wFill = obj->ob_width-1; hFill = obj->ob_height+1; ar[0] = xFill; ar[1] = yFill; ar[2] = xFill; ar[3] = yFill+hFill; ar[4] = xFill+wFill; ar[5] = yFill+hFill; ar[6] = xFill+wFill; ar[7] = yFill; vsf_interior(handle,(mdFill>23)?3:2); vsf_style(handle,mdFill%24); vsf_color(handle,draw_color); v_fillarea(handle,4,ar); graf_mouse(M_ON,0L); do { but = form_do(fill_box, 0); fill_box[but].ob_state &= ~SELECTED; FillT=0; if (but==FILL_OK) while (mpStyleObj[FillT] != but) FillT++; else if (but!=FILL_NO) { objc_draw(fill_box, but, 1, 0,0, 639,399); while (mpStyleObj[FillT] != but) FillT++; mdFill=FillT; vsf_interior(handle,(mdFill>23)?3:2); vsf_style(handle,mdFill%24); graf_mouse(M_OFF,0L); v_fillarea(handle,4,ar); graf_mouse(M_ON,0L); } else mdFill=oldFill; } while ((but!=FILL_OK) && (but!=FILL_NO)); form_dial(FMD_SHRINK, xc,yc,0,0, cx, cy, cw, ch); form_dial(FMD_FINISH, 0,0,0,0, cx, cy, cw, ch); buf_to_scr(cx-xwork,cy-ywork,cw+4,ch+4); /* unbuffer the box */ } /****************************************************************/ int mpLWObj[5] = { LW1, LW3, LW5, LW7, LW9 }; int mpSSObj[5] = { SS4, SS6, SS8, SS12, SS16 }; int mpLSObj[3] = { LS_SQR, LS_ARROW, LS_RND }; int mpLEObj[3] = { LE_SQR, LE_ARROW, LE_RND }; select_other() { int but; int cx, cy, cw, ch, xc, yc; int mdT; form_center(default_box, &cx, &cy, &cw, &ch); set_clip(cx, cy, cw, ch); scr_to_buf(cx-xwork,cy-ywork,cw+4,ch+4); /* buffer the box */ xc = cx + cw/2; yc = cy + ch/2; form_dial(FMD_START, cx, cy, cw, ch, cx, cy, cw, ch); form_dial(FMD_GROW, xc,yc,0,0, cx, cy, cw, ch); for (mdT=0; mdT<5;) { default_box[mpLWObj[mdT]].ob_state &= ~SELECTED; default_box[mpSSObj[mdT++]].ob_state &= ~SELECTED; } for (mdT=0; mdT<3;) { default_box[mpLSObj[mdT]].ob_state &= ~SELECTED; default_box[mpLEObj[mdT++]].ob_state &= ~SELECTED; } default_box[mpLWObj[mdLW]].ob_state |= SELECTED; default_box[mpSSObj[mdSS]].ob_state |= SELECTED; default_box[mpLSObj[mdLS]].ob_state |= SELECTED; default_box[mpLEObj[mdLE]].ob_state |= SELECTED; graf_mouse(M_OFF,0L); objc_draw(default_box, 0, 10, cx, cy, cw, ch); graf_mouse(M_ON,0L); but = form_do(default_box, 0); default_box[but].ob_state &= ~SELECTED; if (but==OTHER_OK) { for (mdT=0; mdT<5; mdT++) { if (default_box[mpLWObj[mdT]].ob_state & SELECTED) mdLW = mdT; if (default_box[mpSSObj[mdT]].ob_state & SELECTED) mdSS = mdT; } for (mdT=0; mdT<3; mdT++) { if (default_box[mpLSObj[mdT]].ob_state & SELECTED) mdLS = mdT; if (default_box[mpLEObj[mdT]].ob_state & SELECTED) mdLE = mdT; } } form_dial(FMD_SHRINK, xc,yc,0,0, cx, cy, cw, ch); form_dial(FMD_FINISH, 0,0,0,0, cx, cy, cw, ch); buf_to_scr(cx-xwork,cy-ywork,cw+4,ch+4); /* unbuffer the box */ LineWidth = mpLW[mdLW]; SnapSize = mpSS[mdSS]; } /****************************************************************/ snap (px, py) register int *px, *py; { register int x = *px+SnapSize/3, y = *py+SnapSize/3; *px -= x%SnapSize; *py -= y%SnapSize; } /****************************************************************/