home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / applications / xlispstat / src / src1.lzh / Amiga / amiiviewwindow3.c < prev    next >
C/C++ Source or Header  |  1990-10-11  |  21KB  |  540 lines

  1. /* AmiIviewWindow3.c - Low Level Window Objects for Amiga              */
  2. /* Copyright (c) 1990 by J.K. Lindsey                                  */
  3. /* Additions to XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney     */
  4. /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
  5. /* You may give out copies of this software; for conditions see the    */
  6. /* file COPYING included with this distribution.                       */
  7.  
  8. #include <proto/exec.h>
  9. #include <proto/intuition.h>
  10. #include <proto/graphics.h>
  11. #include <graphics/gfxmacros.h>
  12. #include <exec/memory.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include "autil2.h"
  16. #include "plot2.h"
  17. #include "xlisp.h"
  18. #include "osdef.h"
  19. #include "xlproto.h"
  20. #include "xlsproto.h"
  21. #include "Stproto.h"
  22. #include "osproto.h"
  23. #include "amivar.h"
  24. #include "xlsvar.h"
  25.  
  26. /* forward declarations */
  27. void draw_bitmap(StGWWinInfo *,int,int,int,int,char *,int);
  28.  
  29. /**************************************************************************/
  30. /**                                                                      **/
  31. /**                       Utility Function                               **/
  32. /**                                                                      **/
  33. /**************************************************************************/
  34.  
  35. static int dbmove(StGWWinInfo *gwinfo,int *x,int *y){
  36. /*printf("left=%d top=%d width=%d height=%d\n",gwinfo->clip_rect.left,gwinfo->clip_rect.top,
  37. gwinfo->clip_rect.width,gwinfo->clip_rect.height);*/
  38.    if(/*!gwinfo->clipped&&*/(*x<0||*y<0||*x>gwinfo->canvasWidth||*y>gwinfo->canvasHeight))return(1);
  39.    else if(!dbflag&&gwinfo->clipped&&(*x<gwinfo->clip_rect.left||*y<gwinfo->clip_rect.top||
  40.    *x>gwinfo->clip_rect.left+gwinfo->clip_rect.width||
  41.    *y>gwinfo->clip_rect.top+gwinfo->clip_rect.height))return(1);
  42.    else if(!dbflag){
  43.       rp=gwinfo->window->RPort; /* necessary for linked windows */
  44.       *x+=gwinfo->window->BorderLeft;
  45.       *y+=gwinfo->window->BorderTop;}
  46.    return(0);}
  47.  
  48. void scroll_clip(StGWWinInfo *gwinfo,int *x,int *y){
  49.    int width,height;
  50.    StGWGetViewRect(gwinfo,0,0,&width,&height);
  51.    if(gwinfo->hasVscroll&&height<gwinfo->canvasHeight){
  52.       (*y)+=(gwinfo->view_v*(gwinfo->canvasHeight-height))/MAXPOT;}
  53.    if(gwinfo->hasHscroll&&width<gwinfo->canvasWidth){
  54.       (*x)+=(gwinfo->view_h*(gwinfo->canvasWidth-width))/MAXPOT;}}
  55.  
  56. /**************************************************************************/
  57. /**                                                                      **/
  58. /**                       Initialization Functions                       **/
  59. /**                                                                      **/
  60. /**************************************************************************/
  61.  
  62. #define NUMSYMBOLS 18
  63. #define SYMROWS     5
  64.  
  65. typedef struct {
  66.    short left,top,width,height;
  67.    short image[SYMROWS];
  68.    LVAL refcon;}
  69. Symbol;
  70.  
  71. static Symbol chip Symbols[NUMSYMBOLS];
  72.  
  73. static void InitSymbol(int sym,int left,int top,int width,int height){
  74.    Symbols[sym].width=width;
  75.    Symbols[sym].height=height;
  76.    Symbols[sym].left=left;
  77.    Symbols[sym].top=top;}
  78.  
  79. void initialize_static_globals(void){
  80.    InitSymbol(0, 0, 0, 2, 2);
  81.    Symbols[0].image[0]=0x8000;
  82.    InitSymbol(1, 0, 0, 2, 2);
  83.    Symbols[1].image[0]=0xC000;
  84.    InitSymbol(2, 0, 0, 2, 2);
  85.    Symbols[2].image[0]=0xC000;
  86.    Symbols[2].image[1]=0x8000;
  87.    InitSymbol(3, 0, 0, 2, 2);
  88.    Symbols[3].image[0]=Symbols[3].image[1]=0xC000;
  89.    InitSymbol(4, 2, 2, 4, 4);
  90.    Symbols[4].image[0]=Symbols[4].image[3]=0x6000;
  91.    Symbols[4].image[1]=Symbols[4].image[2]=0x9000;
  92.    InitSymbol(5, 2, 2, 4, 4);
  93.    Symbols[5].image[0]=Symbols[5].image[3]=0x6000;
  94.    Symbols[5].image[1]=Symbols[5].image[2]=0xF000;
  95.    InitSymbol(6, 3, 3, 5, 5);
  96.    Symbols[6].image[0]=Symbols[6].image[4]=0x2000;
  97.    Symbols[6].image[1]=Symbols[6].image[3]=0x5000;
  98.    Symbols[6].image[2]=0x8800;
  99.    InitSymbol(7, 3, 3, 5, 5);
  100.    Symbols[7].image[0]=Symbols[7].image[4]=0x2000;
  101.    Symbols[7].image[1]=Symbols[7].image[3]=0x7000;
  102.    Symbols[7].image[2]=0xF800;
  103.    InitSymbol(8, 3, 3, 5, 5);
  104.    Symbols[8].image[0]=Symbols[8].image[4]=Symbols[8].image[1]=Symbols[8].image[3]=0x2000;
  105.    Symbols[8].image[2]=0xF800;
  106.    InitSymbol(9, 3, 3, 5, 5);
  107.    Symbols[9].image[0]=Symbols[9].image[4]=0x7000;
  108.    Symbols[9].image[1]=Symbols[9].image[3]=0xA800;
  109.    Symbols[9].image[2]=0xF800;
  110.    InitSymbol(10, 2, 2, 4, 4);
  111.    Symbols[10].image[0]=Symbols[10].image[3]=0xF000;
  112.    Symbols[10].image[1]=Symbols[10].image[2]=0x9000;
  113.    InitSymbol(11, 2, 2, 4, 4);
  114.   Symbols[11].image[0]=Symbols[11].image[3]=Symbols[11].image[1]=Symbols[11].image[2]=0xF000;
  115.    InitSymbol(12, 3, 3, 5, 5);
  116.    Symbols[12].image[0]=0x7000;
  117.    Symbols[12].image[1]=Symbols[12].image[2]=0x8800;
  118.    Symbols[12].image[3]=0x5000;
  119.    Symbols[12].image[4]=0x2000;
  120.    InitSymbol(13, 3, 3, 5, 5);
  121.    Symbols[13].image[0]=Symbols[13].image[3]=0x7000;
  122.    Symbols[13].image[1]=Symbols[13].image[2]=0xF800;
  123.    Symbols[13].image[4]=0x2000;
  124.    InitSymbol(14, 3, 3, 5, 5);
  125.    Symbols[14].image[0]=0x2000;
  126.    Symbols[14].image[1]=0x5000;
  127.    Symbols[14].image[2]=Symbols[14].image[3]=0x8800;
  128.    Symbols[14].image[4]=0x7000;
  129.    InitSymbol(15, 3, 3, 5, 5);
  130.    Symbols[15].image[0]=0x2000;
  131.    Symbols[15].image[1]=Symbols[15].image[4]=0x7000;
  132.    Symbols[15].image[2]=Symbols[15].image[3]=0xF800;
  133.    InitSymbol(16, 3, 3, 5, 5);
  134.    Symbols[16].image[2]=0x2000;
  135.    Symbols[16].image[0]=Symbols[16].image[4]=0x8800;
  136.    Symbols[16].image[1]=Symbols[16].image[3]=0x5000;
  137.    InitSymbol(17, 3, 3, 5, 5);
  138.    Symbols[17].image[2]=0x2000;
  139.    Symbols[17].image[0]=Symbols[17].image[4]=Symbols[17].image[1]=Symbols[17].image[3]=0xD800;}
  140.  
  141. /**************************************************************************/
  142. /**                                                                      **/
  143. /**                  Line and Rectangle Drawing Functions                **/
  144. /**                                                                      **/
  145. /**************************************************************************/
  146.  
  147. static struct TmpRas tmpRas;
  148. static struct AreaInfo areaInfo;
  149.  
  150. static void drawline(short a,short b,short c,short d){
  151.    Move(rp,a,b);
  152.    Draw(rp,c,d);}
  153.  
  154. static void draw_object(StGWWinInfo *gwinfo,int what,int how,int a,int b,int c,int d){
  155.    static short xy[10]={0,0,0,0,0,0,0,0,0,0};
  156.    static struct Border bd={0,0,0,0,0,5,xy,0};
  157.    struct Window *w;
  158.    PLANEPTR planePtr;
  159.    short areabuffer[5],i;
  160.    int cc,dd;
  161.    if(!gwinfo||!(w=gwinfo->window))return;
  162. /*printf("what = %c how = %c a = %d b = %d c = %d d = %d\n",what,how,a,b,c,d);
  163. printf("clipping=%d dbflag=%d\n",gwinfo->clipped,dbflag);*/
  164.    if(dbmove(gwinfo,&a,&b))return;
  165.    if(what=='R'||what=='O'){
  166.       cc=a+c;
  167.       dd=b+d;
  168.       if(!dbflag){
  169.          cc-=w->BorderLeft;
  170.          dd-=w->BorderTop;}
  171.       if(dbmove(gwinfo,&cc,&dd))return;}
  172.    if(how=='E')SetAPen(rp,gwinfo->backColor);
  173.    switch(what) {
  174.       case 'L': {
  175.          if(dbmove(gwinfo,&c,&d))return;
  176.          drawline((short)a,(short)b,(short)c,(short)d);
  177.          if(gwinfo->lineWidth>1){
  178.             if(a-c<b-d)drawline((short)a,(short)(b+1),(short)c,(short)(d+1));
  179.             else drawline((short)(a+1),(short)b,(short)(c+1),(short)d);
  180.             if(gwinfo->lineWidth>2){
  181.                if(a-c<b-d)drawline((short)a,(short)(b-1),(short)c,(short)(d-1));
  182.                else drawline((short)(a-1),(short)b,(short)(c-1),(short)d);}}
  183.          break;}
  184.       case 'P': {
  185.          WritePixel(rp,(short)a,(short)b);
  186.          break;}
  187.       case 'R': {
  188.          switch (how) {
  189.             case 'E': 
  190.             case 'P': {
  191.                RectFill(rp,(short)a,(short)b,(short)(a+c-1),(short)(b+d-1));
  192.                break;}
  193.             case 'F': {
  194.                bd.LeftEdge=a;
  195.                bd.TopEdge=b;
  196.                bd.FrontPen=gwinfo->drawColor;
  197.                bd.BackPen=gwinfo->backColor;
  198.                bd.DrawMode=gwinfo->drawMode;
  199.                xy[2]=xy[4]=c-1;
  200.                xy[5]=xy[7]=d-1;
  201.                DrawBorder(rp,&bd,0,0);
  202.                if(gwinfo->lineWidth>1){
  203.                   bd.LeftEdge++;
  204.                   bd.TopEdge++;
  205.                   xy[2]=xy[4]=c-3;
  206.                   xy[5]=xy[7]=d-3;
  207.                   DrawBorder(rp,&bd,0,0);
  208.                   if(gwinfo->lineWidth>2){
  209.                      bd.LeftEdge-=2;
  210.                      bd.TopEdge-=2;
  211.                      xy[2]=xy[4]=c+1;
  212.                      xy[5]=xy[7]=d+1;
  213.                      DrawBorder(rp,&bd,0,0);}}
  214.                break;}}
  215.          break;}
  216.       case 'O': {
  217.          switch(how) {
  218.             case 'E':
  219.             case 'P': {
  220.                if(!(planePtr=AllocRaster(screenw,screenh)))xlfail("unable to allocate raster");
  221.                for(i=0;i<5;i++)areabuffer[i]=0;
  222.                InitArea(&areaInfo,areabuffer,2);
  223.                rp->AreaInfo=&areaInfo;
  224.                InitTmpRas(&tmpRas,planePtr,RASSIZE(screenw,screenh));
  225.                rp->TmpRas=&tmpRas;
  226.                AreaEllipse(rp,(short)(a+c/2),(short)(b+d/2),(short)(c/2),(short)(d/2));
  227.                AreaEnd(rp);
  228.                FreeRaster(planePtr,screenw,screenh);
  229.                break;}
  230.             case 'F': {
  231.                SetOPen(rp,gwinfo->drawColor);
  232.                DrawEllipse(rp,(short)(a+c/2),(short)(b+d/2),(short)(c/2),(short)(d/2));
  233.                if(gwinfo->lineWidth>1){
  234.                   DrawEllipse(rp,(short)(a+c/2),(short)(b+d/2),(short)(c/2-1),(short)(d/2-1));
  235.                   if(gwinfo->lineWidth>2){
  236.                      DrawEllipse(rp,(short)(a+c/2),(short)(b+d/2),(short)(c/2+1),(short)(d/2+1));}}
  237.                BNDRYOFF(rp);
  238.                break;}}
  239.          break;}}
  240.    if(how=='E')SetAPen(rp,gwinfo->drawColor);}
  241.  
  242. static void draw_poly(StGWWinInfo *gwinfo,char how,int n,short *p,int from_origin){
  243.    int i,x,y;
  244.    struct Window *w;
  245.    PLANEPTR planePtr;
  246.    short *areabuffer;
  247.    if(!gwinfo||!(w=gwinfo->window)||n<=0)return;
  248.    x=p[0];
  249.    y=p[1];
  250.    if(dbmove(gwinfo,&x,&y))return;
  251.    p[0]=x;
  252.    p[1]=y;
  253.    for(i=1;i<n;i++){
  254.       x=p[2*i];
  255.       y=p[2*i+1];
  256.       if(dbmove(gwinfo,&x,&y))return;
  257.       p[2*i]=x;
  258.       p[2*i+1]=y;}
  259.    if(how=='E')SetAPen(rp,gwinfo->backColor);
  260.    if(!from_origin)for(i=1;i<n;i++){
  261.       p[2*i]=p[2*i]+p[2*i-2];
  262.       p[2*i+1]=p[2*i+1]+p[2*i-1];}
  263.    switch(how){
  264.       case 'E':
  265.       case 'P': {
  266.          if(!(planePtr=AllocRaster(screenw,screenh)))xlfail("unable to allocate raster");
  267.          if(!(areabuffer=calloc(1,5*n*sizeof(short))))xlfail("unable to allocate raster buffer");
  268.          InitArea(&areaInfo,areabuffer,n);
  269.          rp->AreaInfo=&areaInfo;
  270.          InitTmpRas(&tmpRas,planePtr,RASSIZE(screenw,screenh));
  271.          rp->TmpRas=&tmpRas;
  272.          AreaMove(rp,p[0],p[1]);
  273.          for(i=1;i<n;i++)AreaDraw(rp,p[2*i],p[2*i+1]);
  274.          AreaEnd(rp);
  275.          free(areabuffer);
  276.          FreeRaster(planePtr,screenw,screenh);
  277.          break;}
  278.       case 'F': {
  279.          Move(rp,p[0],p[1]);
  280.          PolyDraw(rp,n,p);
  281.          break;}}
  282.    if(how=='E')SetAPen(rp,gwinfo->drawColor);}
  283.  
  284. void StGWDrawLine(StGWWinInfo *gwinfo,int x1,int y1,int x2,int y2){
  285.   draw_object(gwinfo,'L','0',x1,y1,x2,y2);}
  286.  
  287. void StGWDrawPoint(StGWWinInfo *gwinfo,int x,int y){
  288.   draw_object(gwinfo,'P','0',x,y,0,0);}
  289.  
  290. void StGWEraseRect(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  291.    draw_object(gwinfo,'R','E',left,top,width,height);}
  292.  
  293. void StGWFrameRect(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  294.   draw_object(gwinfo,'R','F',left,top,width,height);} 
  295.  
  296. void StGWPaintRect(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  297.   draw_object(gwinfo,'R','P',left,top,width,height);}
  298.  
  299. void StGWEraseOval(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  300.   draw_object(gwinfo,'O','E',left,top,width,height);}
  301.  
  302. void StGWFrameOval(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  303.   draw_object(gwinfo,'O','F',left,top,width,height);}
  304.  
  305. void StGWPaintOval(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  306.   draw_object(gwinfo,'O','P',left,top,width,height);}
  307.  
  308. void StGWEraseArc(StGWWinInfo *gwinfo,int left,int top,int width,int height,double angle1,double angle2){
  309.    /*draw_arc(gwinfo,'E',left,top,width,height,angle1,angle2);}*/
  310.    xlfail("not supported 25"); }
  311.  
  312. void StGWFrameArc(StGWWinInfo *gwinfo,int left,int top,int width,int height,double angle1,double angle2){
  313.    /*draw_arc(gwinfo,'F',left,top,width,height,angle1,angle2);}*/
  314.    xlfail("not supported 26"); }
  315.  
  316. void StGWPaintArc(StGWWinInfo *gwinfo,int left,int top,int width,int height,double angle1,double angle2){
  317.    /*draw_arc(gwinfo,'P',left,top,width,height,angle1,angle2);}*/
  318.    xlfail("not supported 24"); }
  319.  
  320. void StGWErasePoly(StGWWinInfo *gwinfo,int n,short *p,int from_origin){
  321.    draw_poly(gwinfo,'E',n,p,from_origin);}
  322.  
  323. void StGWFramePoly(StGWWinInfo *gwinfo,int n,short *p,int from_origin){
  324.    draw_poly(gwinfo,'F',n,p,from_origin);}
  325.  
  326. void StGWPaintPoly(StGWWinInfo *gwinfo,int n,short *p,int from_origin){
  327.    draw_poly(gwinfo,'P',n,p,from_origin);}
  328.  
  329. /**************************************************************************/
  330. /**                                                                      **/
  331. /**                            Text Functions                            **/
  332. /**                                                                      **/
  333. /**************************************************************************/
  334.  
  335. int StGWTextAscent(StGWWinInfo *gwinfo){
  336.    return((int)window->RPort->TxBaseline);}
  337.  
  338. int StGWTextDescent(StGWWinInfo *gwinfo){
  339.    return((int)(window->RPort->TxHeight-window->RPort->TxBaseline));}
  340.  
  341. int StGWTextWidth(StGWWinInfo *gwinfo,char *text){
  342.    return((int)TextLength(window->RPort,text,strlen(text)));}
  343.  
  344. void StGWDrawString(StGWWinInfo *gwinfo,char *s,int x,int y){
  345.    struct Window *w;
  346.    if(!s||!gwinfo||!(w=gwinfo->window))return;
  347.    if(dbmove(gwinfo,&x,&y))return;
  348. /*printf("x=%d y=%d s=%s\n",x,y,s);*/
  349.    Move(rp,(short)x,(short)(y+1));
  350.    Text(rp,s,strlen(s));}
  351.  
  352. void StGWDrawText(StGWWinInfo *gwinfo,char *text,int x,int y,int h,int v){
  353.    int FontAscent,string_width;
  354.    if(!text||!gwinfo)return;
  355.    FontAscent=StGWTextAscent(gwinfo);
  356.    string_width=StGWTextWidth(gwinfo,text);
  357.    if(v==1)y+=FontAscent;
  358.    if(h==1)x-=string_width/2;
  359.    if(h==2)x-=string_width;
  360.    StGWDrawString(gwinfo,text,x,y);}
  361.  
  362. static void DrawCharUp(struct Window *w,char myChar,int x,int y){
  363.    short i,j,hch,wch;
  364.    char dc,bc;
  365.    StGWWinInfo *gwinfo;
  366.    gwinfo=(StGWWinInfo *)w->UserData;
  367.    dc=gwinfo->drawColor;
  368.    bc=gwinfo->backColor;
  369.    if(dbmove(gwinfo,&x,&y))return;
  370.    hch=rp->TxHeight;
  371.    wch=rp->TxWidth;
  372.    SetAPen(&rp1,dc);
  373.    SetAPen(&rp2,dc);
  374.    SetBPen(&rp1,bc);
  375.    SetDrMd(&rp1,w->RPort->DrawMode);
  376.    SetDrMd(&rp2,w->RPort->DrawMode);
  377.    SetRast(&rp1,bc);
  378.    SetRast(&rp2,bc);
  379.    Move(&rp1,0,rp->TxBaseline);
  380.    Text(&rp1,&myChar,1);
  381.    for(i=0;i<wch;i++)for(j=0;j<hch;j++)if(ReadPixel(&rp1,i,j)==dc)WritePixel(&rp2,j,8-i);
  382.    ClipBlit(&rp2,0,0,rp,x,y-wch,hch,wch,0xC0);}
  383.  
  384. void StGWDrawStringUp(StGWWinInfo *gwinfo,char *s,int x,int y){
  385.    struct Window *w;
  386.    char str[2];
  387.    int n;
  388.    if(!s||!gwinfo||!(w=gwinfo->window))return;
  389.    str[1] = '\0';
  390.    for(n=strlen(s);n>0;n--,s++){
  391.       DrawCharUp(w,*s,x,y);
  392.       str[0]=*s;
  393.          y-=StGWTextWidth(gwinfo,str);}}
  394.  
  395. void StGWDrawTextUp(StGWWinInfo *gwinfo,char *text,int x,int y,int h,int v){
  396.    int FontAscent,string_width;
  397.    if(!text||!gwinfo)return;
  398.    FontAscent=StGWTextAscent(gwinfo);
  399.    string_width=StGWTextWidth(gwinfo,text);
  400.    if(v==1)x+=FontAscent;
  401.    if(h==1)y+=string_width/2;
  402.    if(h==2)y+=string_width;
  403.    StGWDrawStringUp(gwinfo,text,x,y);}
  404.  
  405. /**************************************************************************/
  406. /**                                                                      **/
  407. /**                           Symbol Functions                           **/
  408. /**                                                                      **/
  409. /**************************************************************************/
  410.  
  411. void StGWSetSymRefCon(int index,LVAL rc){
  412.    if(index<NUMSYMBOLS)Symbols[index].refcon=rc;}
  413.  
  414. LVAL StGWGetSymRefCon(int index){
  415.    if(index<NUMSYMBOLS)return(Symbols[index].refcon);
  416.    else return(0);}
  417.  
  418. void StGWGetSymbolSize(int sym,int *width,int *height){
  419.    *width=Symbols[sym].width;
  420.    *height=Symbols[sym].height;}
  421.  
  422. void StGWDrawSymbol(StGWWinInfo *gwinfo,int sym,int x,int y){
  423.    if(sym<0||sym>=NUMSYMBOLS)return;
  424.    draw_bitmap(gwinfo,x-(int)Symbols[sym].left,y-(int)Symbols[sym].top,
  425.    Symbols[sym].width,Symbols[sym].height,(char *)Symbols[sym].image,2);}
  426.  
  427. void StGWReplaceSymbol(StGWWinInfo *gwinfo,int oldsym,int newsym,int x,int y){
  428.    int oldwidth,oldheight,newwidth,newheight;
  429.    if(oldsym>=NUMSYMBOLS||newsym>=NUMSYMBOLS)return;
  430.    StGWGetSymbolSize(oldsym,&oldwidth,&oldheight);
  431.    StGWGetSymbolSize(newsym,&newwidth,&newheight);
  432.    if(oldwidth>newwidth||oldheight>newheight){
  433.       StGWEraseRect(gwinfo,x-Symbols[oldsym].left,y-Symbols[oldsym].top,
  434.       oldwidth,oldheight);}
  435.    StGWDrawSymbol(gwinfo,newsym,x,y);}
  436.  
  437. /**************************************************************************/
  438. /**                                                                      **/
  439. /**                           Bitmap Functions                           **/
  440. /**                                                                      **/
  441. /**************************************************************************/
  442.  
  443. static void draw_bitmap(StGWWinInfo *gwinfo,int left,int top,int width,int height,char *image,int modulus){
  444.    struct Window *w;
  445.    if(!gwinfo||!(w=gwinfo->window))return;
  446. /*printf("bitmap left=%d top=%d width=%d height=%d\n",left,top,width,height);*/
  447.    if(dbmove(gwinfo,&left,&top))return;
  448.    SetDrMd(rp,gwinfo->symbolMode);
  449.    BltTemplate(image,0,modulus,rp,left,top,width,height);   SetBPen(rp,gwinfo->backColor);
  450.    SetDrMd(rp,gwinfo->drawMode);}
  451.  
  452. void StGWDrawBitmap(StGWWinInfo *gwinfo,int left,int top,int width,int height,char *image){
  453.    unsigned short *im;
  454.    int rowwords,i,j,l,m;
  455.    rowwords=width/16+1;
  456.    if(rowwords*height<=0)return;
  457.    if(!(im=AllocMem(rowwords*height*2,MEMF_CHIP|MEMF_CLEAR)))return;
  458.    for(i=0;i<height;i++)for(j=0;j<rowwords;j++){
  459.       for(l=0;l<16;l++){
  460.          m=j*16+l;
  461.          if(m<width&&image[i*width+m])im[i*rowwords+j]|=(1<<(15-l));}}
  462.    draw_bitmap(gwinfo,left,top,width,height,(char *)im,2*rowwords);
  463.    FreeMem(im,rowwords*height*2);}
  464.  
  465.  
  466. /**************************************************************************/
  467. /**                                                                      **/
  468. /**                         Buffering Functions                          **/
  469. /**                                                                      **/
  470. /**************************************************************************/
  471.  
  472. static int bufflevel=0;
  473.  
  474. void StGWStartBuffering(StGWWinInfo *gwinfo){
  475.    if(!gwinfo||!gwinfo->window)return;
  476.    bufflevel++;
  477.    if(dbflag)return;
  478.    dbflag=1;
  479.    rp=&dbrp;
  480.    SetRast(rp,gwinfo->backColor);}
  481. /*
  482. void StGWBufferToScreen(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  483.    struct Window *w;
  484.    if(!gwinfo||!(w=gwinfo->window))return;
  485.    if(bufflevel>0)bufflevel--;
  486.    if(bufflevel>0)return;
  487.    if(dbflag){
  488.       left+=w->BorderLeft;
  489.       top+=w->BorderTop;
  490.       ClipBlit(&dbrp,left,top,w->RPort,left,top,width,height,0xC0);
  491.       dbflag=0;
  492.       rp=w->RPort;}}
  493. */
  494. void StGWBufferToScreen(StGWWinInfo *gwinfo,int left,int top,int width,int height){
  495.    struct Window *w;
  496.    int vwidth,vheight,bleft,btop;
  497.    if(!gwinfo||!(w=gwinfo->window))return;
  498.    if(bufflevel>0)bufflevel--;
  499.    if(bufflevel>0)return;
  500.    if(dbflag){
  501.       dbflag=0;
  502.       rp=w->RPort;
  503.       if(left>=0&&top>=0){
  504.          bleft=left;
  505.          btop=top;
  506.          StGWGetViewRect(gwinfo,0,0,&vwidth,&vheight);
  507. /*printf("buffer left=%d top=%d width=%d height=%d\n",left,top,width,height);*/
  508.          if(gwinfo->hasHscroll&&vwidth<gwinfo->canvasWidth){
  509.             bleft+=(gwinfo->view_h*(gwinfo->canvasWidth-vwidth))/MAXPOT;}
  510.          if(gwinfo->hasVscroll&&vheight<gwinfo->canvasHeight){
  511.             btop+=(gwinfo->view_v*(gwinfo->canvasHeight-vheight))/MAXPOT;}
  512.          ClipBlit(&dbrp,bleft,btop,rp,left+(int)w->BorderLeft,
  513.          top+(int)w->BorderTop,width,height,0xC0);}}}
  514.  
  515. /**************************************************************************/
  516. /**                                                                      **/
  517. /**                         Miscellaneous Functions                      **/
  518. /**                                                                      **/
  519. /**************************************************************************/
  520.  
  521. extern unsigned short icon[];
  522.  
  523. void StGWDumpImage(StGWWinInfo *gwinfo,char *fname,double scale){
  524.    struct Window *w;
  525.    unsigned long flags;
  526.    int test;
  527.    if(gwinfo&&(w=gwinfo->window)){
  528.       WindowToFront(w);
  529.       flags=w->IDCMPFlags;
  530.       Dodo(w,0);
  531.       wfile(fname);
  532.       test=SaveWindow(w,fname,w->BorderLeft,w->BorderTop,
  533.       w->Width-w->BorderRight-w->BorderLeft,w->Height-w->BorderTop-w->BorderBottom);
  534.       Dodo(w,flags);
  535.       if(test)xlfail("IFF save failed");}}
  536.  
  537. void StGWResetBuffer(){
  538.    bufflevel=dbflag=0;}
  539.  
  540.