-- TJaMGraphicsImpl.mesa -- Last changed by Doug Wyatt, 20-Nov-81 12:36:43 -- Last changed by Bill Paxton, July 8, 1982 8:46 am -- Last changed by McGregor, June 10, 1982 4:10 pm DIRECTORY Graphics, GraphicsOps, GraphicsBasic USING [Vec], CGVector USING [Sub, Cross], InputFocus USING [CaptureButtons, ReleaseButtons], Rope USING [Concat, FromRefText], Spline USING [Ref, New, Knot, Enter], TIPUser USING [InstantiateNewTIPTable], Cursors USING [SetCursor], WindowManager USING [RestoreCursor], Menus USING [Menu, MenuProc, CreateMenu, InsertMenuEntry], ViewerClasses USING [Viewer, ViewerClass, ViewerClassRec], ViewerMenus USING [Destroy, Move, Grow, Close], ViewerOps USING [DestroyViewer, PaintViewer, RegisterViewerClass, CreateViewer], JaMBasic USING [Object], JaMInternal USING [Frame], JaMOps USING [defaultFrame, PopInteger, PushInteger, PushReal, PopReal, PopString, PushBoolean, PopBoolean, RegisterExplicit, SetAbort, StringText], JaMTypeScript USING [GetTypeScript, NotifyBeforeDestroy, SetMouseProc], JaMGraphics, TJaMGraphics, TJaMGraphicsPrivate; TJaMGraphicsImpl: MONITOR IMPORTS JaMOps, JaMTypeScript, TJaMGraphics, TJaMGraphicsPrivate, InputFocus, Graphics, GraphicsOps, CGVector, Menus, Rope, Spline, TIPUser, ViewerMenus, ViewerOps, WindowManager, Cursors EXPORTS JaMGraphics, TJaMGraphics, TJaMGraphicsPrivate = { OPEN J: JaMOps, G: Graphics, E: GraphicsOps, Vector: CGVector, JaMGraphics, TJaMGraphics, TJaMGraphicsPrivate; jamGraphicsClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec _ [ paint: Paint, notify: InputNotify, destroy: AboutToDestroy, tipTable: TIPUser.InstantiateNewTIPTable["JaMGraphics.TIP"] ]]; JReloadTIP: PROC [frame: Frame] = { ReloadTIP[] }; ReloadTIP: PUBLIC PROC = { jamGraphicsClass.tipTable _ TIPUser.InstantiateNewTIPTable["JaMGraphics.TIP"] }; Vec: TYPE = GraphicsBasic.Vec; GetDC: PUBLIC PROCEDURE RETURNS[G.Context] = { info: Info _ GetInfo[J.defaultFrame]; IF info = NIL THEN RETURN [NIL]; RETURN[info.dc] }; PopString: PROC [info: Info] = { J.StringText[J.PopString[info.frame.opstk],LOOPHOLE[info.text, LONG STRING]]; }; JGetViewer: PROC [frame: Frame] = { tool: ViewerClasses.Viewer _ JaMTypeScript.GetTypeScript[frame]; IF tool=NIL THEN RETURN; -- error [] _ Create[frame,tool]; }; Create: PUBLIC PROC [ frame: Frame, typescript: ViewerClasses.Viewer, iconic: BOOLEAN _ FALSE] RETURNS [viewer: ViewerClasses.Viewer] = { info: Info; menu: Menus.Menu; { -- extra block to make info defined in scope of UNWIND ENABLE UNWIND => -- something went wrong while creating the viewer IF viewer#NIL THEN DestroyViewer[viewer] ELSE IF info#NIL THEN ForgetInfo[frame]; IF (info _ GetInfo[frame]) # NIL THEN RETURN; info _ CreateInfo[frame]; info.bitmap _ E.NewBitmap[bmw,bmh]; info.spline _ Spline.New[]; info.font _ E.DefaultFont[]; info.text _ NEW[TEXT[256]]; menu _ Menus.CreateMenu[]; Menus.InsertMenuEntry[menu, "Reset", Reset]; Menus.InsertMenuEntry[menu, "Mouse", CaptureFocusButton]; Menus.InsertMenuEntry[menu, "Interrupt", InterruptButton]; Menus.InsertMenuEntry[menu, "Destroy", ViewerMenus.Destroy]; Menus.InsertMenuEntry[menu, "<-->", ViewerMenus.Move]; Menus.InsertMenuEntry[menu, "Grow", ViewerMenus.Grow]; Menus.InsertMenuEntry[menu, "Close", ViewerMenus.Close]; viewer _ ViewerOps.CreateViewer[flavor: $JaMGraphics, info: [data: info, name: Rope.Concat[typescript.name,"Graphics "], iconic: iconic, scrollable: FALSE]]; viewer.menu _ menu; info.viewer _ viewer; info.typescript _ typescript; JaMTypeScript.NotifyBeforeDestroy[typescript,JDestroyViewer]; }}; Reset: Menus.MenuProc = { frame: Frame _ NARROW[viewer.data,Info].frame; InitDC[frame]; JErase[frame] }; CaptureFocusButton: Menus.MenuProc = { info: Info _ NARROW[viewer.data]; frame: Frame _ info.frame; JCaptureButtons[frame] }; InterruptButton: Menus.MenuProc = { info: Info _ NARROW[viewer.data]; frame: Frame _ info.frame; J.SetAbort[frame,TRUE]; SetPlace[info,0,0]; SetBug[info,0,0] }; JDestroyViewer: PROCEDURE [frame: Frame] = { -- returns true if already have a viewer for this frame info: Info _ GetInfo[frame]; IF info = NIL THEN RETURN; DestroyViewer[info.viewer]; }; DestroyViewer: PROC [viewer: ViewerClasses.Viewer] = { AboutToDestroy[viewer]; ViewerOps.DestroyViewer[viewer]; }; AboutToDestroy: PROC [self: ViewerClasses.Viewer] = { info: Info _ NARROW[self.data]; ForgetInfo[info.frame]; }; Paint: ENTRY PROCEDURE [self: ViewerClasses.Viewer, context: G.Context, whatChanged: REF ANY, clear: BOOLEAN] = { ENABLE UNWIND => NULL; info: Info _ NARROW[self.data]; IF whatChanged=NIL THEN { -- reestablish context and erase info.initdc _ G.CopyContext[context]; InitDC[info.frame]; IF ~clear THEN { -- cannot simply call JErase because of monitor deadlock mark: G.Mark _ G.Save[info.dc]; G.SetColor[info.dc, G.white]; G.DrawBox[info.dc,G.GetBounds[info.dc]]; G.Restore[info.dc,mark] }; RETURN }; info.proc[info]; }; Painter: PUBLIC PROCEDURE[proc: PROC [Graphics.Context], frame: Frame _ NIL] = { info: Info; CallBack: PROC [info: Info] = { proc[info.dc] }; IF frame=NIL THEN frame _ J.defaultFrame; info _ GetInfo[frame]; info.proc _ CallBack; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; InitDC: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.dc _ G.CopyContext[info.initdc]; }; PushDC: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; [] _ G.Save[info.dc]; }; PopDC: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; G.Restore[info.dc]; }; GetVec: PROCEDURE [frame: Frame] RETURNS[Vec] = { y: REAL _ J.PopReal[frame.opstk]; x: REAL _ J.PopReal[frame.opstk]; RETURN[[x,y]] }; GetPoint: PROCEDURE [frame: Frame] RETURNS[x,y: REAL] = { y _ J.PopReal[frame.opstk]; x _ J.PopReal[frame.opstk]; RETURN[x,y] }; PutPoint: PROCEDURE[frame: Frame, x,y: REAL] = { J.PushReal[frame.opstk,x]; J.PushReal[frame.opstk,y] }; Rect: TYPE = RECORD[xmin,ymin,xmax,ymax: REAL]; GetRect: PROCEDURE [frame: Frame] RETURNS[r: Rect] = { [r.xmax,r.ymax] _ GetPoint[frame]; [r.xmin,r.ymin] _ GetPoint[frame]; RETURN[r]; }; PutRect: PROCEDURE[frame: Frame, r: Rect] = { PutPoint[frame,r.xmin,r.ymin]; PutPoint[frame,r.xmax,r.ymax]; }; JSetVw: PROCEDURE [frame: Frame] = { rt: Rect _ GetRect[frame]; rf: Rect _ GetRect[frame]; -- *** fix this -- SetView[dc,@rf,@rt]; }; JClipArea: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; G.ClipArea[info.dc]; }; JClipEOArea: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; G.ClipArea[self: info.dc, parityFill: TRUE]; }; JClipXArea: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; G.ClipArea[self: info.dc, exclude: TRUE]; }; JClipBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; box: G.Box _ GetBox[frame]; G.ClipBox[info.dc, box]; }; JClipXBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; box: G.Box _ GetBox[frame]; G.ClipBox[info.dc,box,TRUE]; }; JTranslate: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; tx,ty: REAL; [tx,ty]_GetPoint[frame]; G.Translate[info.dc,tx,ty]; }; JScale: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; sx,sy: REAL; [sx,sy]_GetPoint[frame]; G.Scale[info.dc,sx,sy]; }; JRotate: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; a: REAL _ J.PopReal[frame.opstk]; G.Rotate[info.dc,a]; }; JSixPoint: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; f1,f2,f3,t1,t2,t3,df1,df2,dt1,dt2: Vec; adet: REAL; xx,xy,yx,yy,tx,ty: REAL; t3_GetVec[frame]; t2_GetVec[frame]; t1_GetVec[frame]; f3_GetVec[frame]; f2_GetVec[frame]; f1_GetVec[frame]; [[tx,ty]]_Vector.Sub[t1,f1]; dt1_Vector.Sub[t2,t1]; df1_Vector.Sub[f2,f1]; dt2_Vector.Sub[t3,t1]; df2_Vector.Sub[f3,f1]; adet_1.0/Vector.Cross[df1,df2]; xx_(dt1.x*df2.y-dt2.x*df1.y)*adet; xy_(df1.x*dt2.x-df2.x*dt1.x)*adet; yx_(dt1.y*df2.y-dt2.y*df1.y)*adet; yy_(df1.x*dt2.y-df2.x*dt1.y)*adet; G.Translate[info.dc,tx,ty]; G.Concat[info.dc,xx,xy,yx,yy] }; JConcat: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; xx,xy,yx,yy: REAL; yy _ J.PopReal[frame.opstk]; yx _ J.PopReal[frame.opstk]; xy _ J.PopReal[frame.opstk]; xx _ J.PopReal[frame.opstk]; G.Concat[info.dc,xx,xy,yx,yy]; }; JGetPos: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x,y: REAL; [x,y]_G.GetCP[info.dc]; PutPoint[frame,x,y]; }; JMoveTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x,y: REAL; [x,y]_GetPoint[frame]; G.MoveTo[info.dc,x,y]; }; JDrawTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawTo; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawTo: PROC [info: Info] = { x,y: REAL; [x,y]_GetPoint[info.frame]; G.DrawTo[info.dc,x,y]; -- UpdateViewer[info.frame]; }; JRelMoveTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x,y: REAL; [x,y]_GetPoint[frame]; G.MoveTo[info.dc,x,y,TRUE]; }; JRelDrawTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintRelDrawTo; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintRelDrawTo: PROC [info: Info] = { x,y: REAL; [x,y]_GetPoint[info.frame]; G.DrawTo[info.dc,x,y,TRUE]; -- UpdateViewer[info.frame]; }; JDrawBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawBox; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawBox: PROC [info: Info] = { box: G.Box _ GetBox[info.frame]; G.DrawBox[info.dc,box]; -- UpdateViewer[info.frame]; }; JCover: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintCover; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintCover: PROC [info: Info] = { G.DrawBox[info.dc,G.GetBounds[info.dc]]; -- UpdateViewer[info.frame]; }; JSetInvert: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; [] _ G.SetPaintMode[info.dc, invert]; }; JSetColor: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; i: LONG INTEGER _ J.PopInteger[frame.opstk]; G.SetColor[info.dc, LOOPHOLE[i]]; }; JSetFat: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; b: BOOLEAN _ J.PopBoolean[frame.opstk]; [] _ G.SetFat[info.dc,b]; }; JSetOpaque: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; b: BOOLEAN _ J.PopBoolean[frame.opstk]; [] _ G.SetPaintMode[info.dc,IF b THEN opaque ELSE transparent]; }; JErase: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; mark: G.Mark _ G.Save[info.dc]; G.SetColor[info.dc, G.white]; JCover[frame]; G.Restore[info.dc,mark]; }; JGetTouch: PROCEDURE [frame: Frame] = { mx,my: REAL; [mx,my] _ RealViewerMouse[frame,TRUE]; PutPoint[frame,mx,my]; }; JGetMouse: PROCEDURE [frame: Frame] = { mx,my: REAL; [mx,my] _ RealViewerMouse[frame,FALSE]; PutPoint[frame,mx,my]; }; MouseToUser: PROCEDURE[frame: Frame, x,y:INTEGER] = { PutPoint[frame,x,y]; }; JSetFont: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; PopString[info]; info.font _ G.MakeFont[Rope.FromRefText[info.text]]; }; JGetYMode: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; mode: E.YMode _ E.GetYMode[info.dc]; J.PushInteger[frame.opstk, IF mode=topDown THEN 1 ELSE 0]; }; JSetYMode: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; mode: LONG INTEGER _ J.PopInteger[frame.opstk]; E.SetYMode[info.dc,IF mode>0 THEN topDown ELSE bottomUp]; }; JDrawChar: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawChar; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawChar: PROC [info: Info] = { OPEN info; PopString[info]; IF text.length>0 THEN text.length _ 1; G.DrawText[self: dc, text: text, font: font]; -- UpdateViewer[frame]; }; JDrawText: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawText; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawText: PROC [info: Info] = { OPEN info; PopString[info]; G.DrawText[self: dc, text: text, font: font]; -- UpdateViewer[info.frame]; }; JCharBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; PopString[info]; IF info.text.length>0 THEN info.text.length _ 1; PushTextBox[frame,info.text]; }; JTextBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; PopString[info]; PushTextBox[frame,info.text]; }; JCharWidth: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; PopString[info]; IF info.text.length>0 THEN info.text.length _ 1; PushTextWidth[frame,info.text]; }; JTextWidth: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; PopString[info]; PushTextWidth[frame,info.text]; }; PushTextBox: PROCEDURE[frame: Frame, text: REF READONLY TEXT] = { info: Info _ GetInfo[frame]; xmin,xmax,ymin,ymax: REAL; [xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] _ G.TextBox[info.font,info.text]; J.PushReal[frame.opstk,xmin]; J.PushReal[frame.opstk,ymin]; J.PushReal[frame.opstk,xmax]; J.PushReal[frame.opstk,ymax]; }; PushTextWidth: PROCEDURE[frame: Frame, text: REF READONLY TEXT] = { info: Info _ GetInfo[frame]; xw,yw: REAL; [xw: xw, yw: yw] _ G.TextWidth[info.font,info.text]; J.PushReal[frame.opstk,xw]; J.PushReal[frame.opstk,yw]; }; JFontBox: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; xmin,xmax,ymin,ymax: REAL; [xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax] _ G.FontBox[info.font]; J.PushReal[frame.opstk,xmin]; J.PushReal[frame.opstk,ymin]; J.PushReal[frame.opstk,xmax]; J.PushReal[frame.opstk,ymax]; }; PutBox: PROC[frame: Frame, b: G.Box] = { PutPoint[frame,b.xmin,b.ymin]; PutPoint[frame,b.xmax,b.ymax]; }; GetBox: PROC [frame: Frame] RETURNS[G.Box] = { b: G.Box; [b.xmax,b.ymax] _ GetPoint[frame]; [b.xmin,b.ymin] _ GetPoint[frame]; RETURN[b]; }; JStartBoxing: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; E.BeginBox[info.dc]; }; JStopBoxing: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; b: G.Box _ E.EndBox[info.dc]; PutBox[frame,b]; }; JPushBox: PROCEDURE [frame: Frame] = { b: G.Box _ GetBox[frame]; -- G.PushClipBox[dc,b]; -- **** temporarily removed **** }; JPopBox: PROCEDURE [frame: Frame] = { -- G.PopClipBox[dc]; -- **** temporarily removed **** }; JVisible: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; J.PushBoolean[frame.opstk,G.Visible[info.dc]]; }; JLineTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x,y: REAL; [x,y]_GetPoint[frame]; G.LineTo[info.dc,x,y]; }; JCurveTo: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x1,y1,x2,y2,x3,y3: REAL; [x3,y3]_GetPoint[frame]; [x2,y2]_GetPoint[frame]; [x1,y1]_GetPoint[frame]; G.CurveTo[info.dc,x1,y1,x2,y2,x3,y3]; }; JRectangle: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; x0,y0,x1,y1: REAL; [x1,y1]_GetPoint[frame]; [x0,y0]_GetPoint[frame]; G.Rectangle[info.dc,x0,y0,x1,y1]; }; JClose: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; G.Close[info.dc]; }; JDrawArea: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawArea; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawArea: PROC [info: Info] = { G.DrawArea[info.dc]; -- UpdateViewer[info.frame]; }; JDrawEOArea: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawEOArea; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawEOArea: PROC [info: Info] = { G.DrawArea[info.dc,TRUE]; -- UpdateViewer[info.frame]; }; JDrawPath: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintDrawPath; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintDrawPath: PROC [info: Info] = { width: REAL _ J.PopReal[info.frame.opstk]; G.DrawPath[info.dc,width]; -- UpdateViewer[info.frame]; }; JKnot: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; y: REAL _ J.PopReal[frame.opstk]; x: REAL _ J.PopReal[frame.opstk]; Spline.Knot[info.spline,x,y]; }; JSpline: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; Spline.Enter[info.spline,info.dc,FALSE]; }; JCSpline: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; Spline.Enter[info.spline,info.dc,TRUE]; }; bmw: CARDINAL = 250; bmh: CARDINAL = 200; JBitmap: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; info.proc _ PaintBitmap; ViewerOps.PaintViewer[viewer: info.viewer, hint: client, whatChanged: info, clearClient: FALSE]; }; PaintBitmap: PROC [info: Info] = { E.DrawBitmap[info.dc,info.bitmap,bmw,bmh,0,0,0,bmh]; -- UpdateViewer[info.frame]; }; JSetTarget: PROC [frame: Frame] = { info: Info _ GetInfo[frame]; b: BOOLEAN _ J.PopBoolean[frame.opstk]; E.SetTargetBitmap[info.dc,IF b THEN info.bitmap ELSE NIL]; }; JCaptureButtons: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; InputFocus.CaptureButtons[info.viewer.class.notify, info.viewer.tipTable, info.viewer]; info.capturedButtons _ TRUE; Cursors.SetCursor[textPointer] }; JReleaseButtons: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; InputFocus.ReleaseButtons[]; WindowManager.RestoreCursor; info.capturedButtons _ FALSE }; JScreenCoords: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; y: REAL _ J.PopReal[frame.opstk]; x: REAL _ J.PopReal[frame.opstk]; [x, y] _ Graphics.UserToWorld[info.dc, x, y]; -- get screen coordinates J.PushReal[frame.opstk,x]; J.PushReal[frame.opstk,y]; }; JUserCoords: PROCEDURE [frame: Frame] = { info: Info _ GetInfo[frame]; y: REAL _ J.PopReal[frame.opstk]; x: REAL _ J.PopReal[frame.opstk]; [x, y] _ Graphics.WorldToUser[info.dc, x, y]; -- get user coordinates J.PushReal[frame.opstk,x]; J.PushReal[frame.opstk,y]; }; -- Initialization starts here Init: PROC = { frame: Frame _ J.defaultFrame; [] _ JaMTypeScript.SetMouseProc[MouseToUser]; ViewerOps.RegisterViewerClass[$JaMGraphics, jamGraphicsClass]; J.RegisterExplicit[frame,".initdc"L,InitDC]; J.RegisterExplicit[frame,".pushdc"L,PushDC]; J.RegisterExplicit[frame,".popdc"L,PopDC]; J.RegisterExplicit[frame,".setview"L,JSetVw]; J.RegisterExplicit[frame,".translate"L,JTranslate]; J.RegisterExplicit[frame,".scale"L,JScale]; J.RegisterExplicit[frame,".rotate"L,JRotate]; J.RegisterExplicit[frame,".sixpoint"L,JSixPoint]; J.RegisterExplicit[frame,".concat"L,JConcat]; J.RegisterExplicit[frame,".getpos"L,JGetPos]; J.RegisterExplicit[frame,".moveto"L,JMoveTo]; J.RegisterExplicit[frame,".rmoveto"L,JRelMoveTo]; J.RegisterExplicit[frame,".drawto"L,JDrawTo]; J.RegisterExplicit[frame,".rdrawto"L,JRelDrawTo]; J.RegisterExplicit[frame,".drawbox"L,JDrawBox]; J.RegisterExplicit[frame,".cover"L,JCover]; J.RegisterExplicit[frame,".setinvert"L,JSetInvert]; J.RegisterExplicit[frame,".setcolor"L,JSetColor]; J.RegisterExplicit[frame,".setfat"L,JSetFat]; J.RegisterExplicit[frame,".setopaque"L,JSetOpaque]; J.RegisterExplicit[frame,".touch"L,JGetTouch]; J.RegisterExplicit[frame,".mouse"L,JGetMouse]; J.RegisterExplicit[frame,".erase"L,JErase]; J.RegisterExplicit[frame,".setfont"L,JSetFont]; J.RegisterExplicit[frame,".drawchar"L,JDrawChar]; J.RegisterExplicit[frame,".drawtext"L,JDrawText]; J.RegisterExplicit[frame,".charbox"L,JCharBox]; J.RegisterExplicit[frame,".textbox"L,JTextBox]; J.RegisterExplicit[frame,".charwidth"L,JCharWidth]; J.RegisterExplicit[frame,".textwidth"L,JTextWidth]; J.RegisterExplicit[frame,".fontbox"L,JFontBox]; J.RegisterExplicit[frame,".initboxer"L,JStartBoxing]; J.RegisterExplicit[frame,".stopboxer"L,JStopBoxing]; J.RegisterExplicit[frame,".pushbox"L,JPushBox]; J.RegisterExplicit[frame,".popbox"L,JPopBox]; J.RegisterExplicit[frame,".visible"L,JVisible]; J.RegisterExplicit[frame,".cliparea"L,JClipArea]; J.RegisterExplicit[frame,".clipbox"L,JClipBox]; J.RegisterExplicit[frame,".lineto"L,JLineTo]; J.RegisterExplicit[frame,".curveto"L,JCurveTo]; J.RegisterExplicit[frame,".rect"L,JRectangle]; J.RegisterExplicit[frame,".close"L,JClose]; J.RegisterExplicit[frame,".drawarea"L,JDrawArea]; J.RegisterExplicit[frame,".draweoarea"L,JDrawEOArea]; J.RegisterExplicit[frame,".drawpath"L,JDrawPath]; J.RegisterExplicit[frame,".knot"L,JKnot]; J.RegisterExplicit[frame,".spline"L,JSpline]; J.RegisterExplicit[frame,".cspline"L,JCSpline]; J.RegisterExplicit[frame,".bitmap"L,JBitmap]; J.RegisterExplicit[frame,".clipeoarea"L,JClipEOArea]; J.RegisterExplicit[frame,".clipxarea"L,JClipXArea]; J.RegisterExplicit[frame,".clipxbox"L,JClipXBox]; J.RegisterExplicit[frame,".getymode"L,JGetYMode]; J.RegisterExplicit[frame,".setymode"L,JSetYMode]; J.RegisterExplicit[frame,".settarget"L,JSetTarget]; J.RegisterExplicit[frame,".destroyviewer"L,JDestroyViewer]; J.RegisterExplicit[frame,".getviewer"L,JGetViewer]; J.RegisterExplicit[frame,".screencoords"L,JScreenCoords]; J.RegisterExplicit[frame,".usercoords"L,JUserCoords]; J.RegisterExplicit[frame,".capturebuttons"L,JCaptureButtons]; J.RegisterExplicit[frame,".releasebuttons"L,JReleaseButtons]; J.RegisterExplicit[frame,".reloadTIP"L,JReloadTIP]; }; Init; }.