home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / haswinlib / c / sprite < prev    next >
Encoding:
Text File  |  1991-02-04  |  19.2 KB  |  543 lines

  1. /* > $.CLIB.C.sprite
  2.  *
  3.  *      HASWIN Graphics Library
  4.  *     =========================
  5.  *
  6.  *      Copyright (C) H.A.Shaw 1990.
  7.  *              Howard A. Shaw.
  8.  *              The Unit for Space Sciences,
  9.  *              Room 165,
  10.  *              Physics Building,
  11.  *              University of Kent at Canterbury.
  12.  *              Canterbury.
  13.  *              Kent.  CT2 7NJ
  14.  *      You may use and distribute this code freely, however please leave
  15.  *      it alone.  If you find bugs (and there will be many) please contact
  16.  *      me and the master source can be modified.  If you keep me informed
  17.  *      of who you give copies of this to then I can get release upgrades
  18.  *      to them.
  19.  *
  20.  *      Routines to deal with Sprites.  I hope to expand this later.
  21.  */
  22. #include "includes.h"
  23.  
  24. #define MAXAREA 8       /* we may search 8 sprite areas                    */
  25.  
  26. static  int     **areaslist[MAXAREA] = { &haswin_usersprites, 
  27.                                          &haswin_haswinsprites,
  28.                                          0,
  29.                                          0,
  30.                                          0,
  31.                                          0,
  32.                                          0,
  33.                                          0 };
  34.  
  35. /*
  36.  *      add a new user sprite area for HASWIN to search for sprites.
  37.  */
  38. int haswin_addspritearea(int **area) {
  39.  
  40.         int     i;
  41.  
  42.         for (i=0; i<MAXAREA; i++) {
  43.                 if (areaslist[i] == 0) {
  44.                         areaslist[i] = area;
  45.                         return(HASWIN_TRUE);
  46.                 }
  47.         }
  48.         return(HASWIN_FALSE);
  49. }
  50.  
  51. /*
  52.  *      remove a user sprite area from HASWINs search list.
  53.  */
  54. int haswin_removespritearea(int **area) {
  55.  
  56.         int     i;
  57.  
  58.         for (i=0; i<MAXAREA; i++) {
  59.                 if (areaslist[i] == area) {
  60.                         areaslist[i] = 0;
  61.                         return(HASWIN_TRUE);
  62.                 }
  63.         }
  64.         return(HASWIN_FALSE);
  65. }
  66.  
  67. /*
  68.  *      perform a sprite operation.
  69.  *      We take the sprite name given and look it up in the different
  70.  *      sprite areas.  We set R0, R1 and R2 according to what we find
  71.  *      and then do the operation.
  72.  */
  73. int haswin_spriteop(char *name, _kernel_swi_regs *regs) {
  74.  
  75.         int                     i;
  76.         _kernel_swi_regs        tmpregs, ans;
  77.  
  78.         if (name == 0) {
  79.                 /* no sprite name, just do operation as it is */
  80.                 return(haswin_swi(OS_Sprite_operation, regs));
  81.         }
  82.         /*
  83.          *      search through the areaslist list and try the operation.
  84.          */
  85.         for (i=0; i<MAXAREA; i++) {
  86.                 if ((areaslist[i] == 0) || (*areaslist[i] == 0))
  87.                         /* unused areas have the pointer =0 */
  88.                         continue;
  89.                 tmpregs.r[0] = 0x118;
  90.                 tmpregs.r[1] = (int)(*areaslist[i]);
  91.                 tmpregs.r[2] = (int)name;
  92.                 if (_kernel_swi(OS_Sprite_operation, &tmpregs, &ans) == 0) {
  93.                         if (tmpregs.r[2] == ans.r[2])
  94.                                 regs->r[0] = (regs->r[0] & 0xFF) | 0x100;
  95.                         else {
  96.                                 regs->r[0] = (regs->r[0] & 0xFF) | 0x200;
  97.                                 regs->r[2] = ans.r[2];
  98.                         }
  99.                         regs->r[1] = (int)(*areaslist[i]);
  100.                         return(haswin_swi(OS_Sprite_operation, regs));
  101.                 }
  102.         }
  103.         /*
  104.          *      try the operation in the WIMP area.
  105.          */
  106.         tmpregs.r[0] = 0x18;
  107.         tmpregs.r[2] = (int)name;
  108.         if (_kernel_swi(HASWIN_Sprite_operation, &tmpregs, &ans) == 0) {
  109.                 regs->r[0] = (regs->r[0] & 0xFF);
  110.                 regs->r[2] = (int)name;
  111.                 return(haswin_swi(HASWIN_Sprite_operation, regs));
  112.         }
  113.         /*
  114.          *      try the operation in the SYSTEM area.
  115.          */
  116.         regs->r[0] = (regs->r[0] & 0xFF);
  117.         regs->r[2] = (int)name;
  118.         return(haswin_swi(HASWIN_Sprite_operation, regs));
  119. }
  120.  
  121. int haswin_getspritearea(int area) {
  122.  
  123.         area &= SPRITE_AREA_MASK;
  124.         switch (area) {
  125.         case SPRITE_SYSTEM_AREA:
  126.                 return(0);
  127.         case SPRITE_USER_AREA:
  128.                 /* unused areas have the pointer =0 */
  129.                 if (haswin_usersprites)
  130.                         return((int)haswin_usersprites);
  131.                 else
  132.                         return(-1);
  133.         case SPRITE_WIMP_AREA:
  134.         case SPRITE_RISCOS_AREA:
  135.                 return(1);
  136.         case SPRITE_HASWIN_AREA:
  137.                 /* unused areas have the pointer =0 */
  138.                 if (haswin_haswinsprites)
  139.                         return((int)haswin_haswinsprites);
  140.                 else
  141.                         return(-1);
  142.         default:
  143.                 return(-1);
  144.         }
  145. }
  146.  
  147. /*
  148.  *      find the sprite named 'name'.  Return the area it is in, else
  149.  *      return (-1).
  150.  */
  151. int haswin_findsprite(char *name) {
  152.  
  153.         int                     i;
  154.         _kernel_swi_regs        regs, ans;
  155.  
  156.         /*
  157.          *      search through the areaslist list.
  158.          */
  159.         regs.r[0] = 0x128;
  160.         regs.r[2] = (int)name;
  161.         for (i=0; i<MAXAREA; i++) {
  162.                 if ((areaslist[i] == 0) || (*areaslist[i] == 0))
  163.                         continue;
  164.                 regs.r[1] = (int)(*areaslist[i]);
  165.                 /* unused areas have the pointer =0 */
  166.                 if (regs.r[1]) {
  167.                         if (_kernel_swi(OS_Sprite_operation,®s,&ans) == 0)
  168.                                 return((int)(*areaslist[i]));
  169.                 }
  170.         }
  171.         /*
  172.          *      search the WIMP area.
  173.          */
  174.         regs.r[0] = 0x028;
  175.         regs.r[2] = (int)name;
  176.         if (_kernel_swi(HASWIN_Sprite_operation, ®s, &ans) == 0)
  177.                 return(1);
  178.         /*
  179.          *      search the system area.
  180.          */
  181.         regs.r[0] = 0x028;
  182.         regs.r[1] = 0;
  183.         regs.r[2] = (int)name;
  184.         if (_kernel_swi(OS_Sprite_operation, ®s, &ans) == 0)
  185.                 return(0);
  186.         return(HASWIN_UNKNOWN);
  187. }
  188.  
  189. /*
  190.  *      clear the sprite area given and change it to "size" bytes.
  191.  *      Return a pointer to the possibly moved area.  If the "area" pointer
  192.  *      is 0 on entry then a new area is created.
  193.  */
  194. int *haswin_clearsprites(int size, int *area) {
  195.  
  196.         _kernel_swi_regs  regs;
  197.  
  198.         if (size <= 0) {
  199.                 if (area)
  200.                         haswin_free(area);
  201.                 return(0);
  202.         }
  203.         size += 16;     /* add space for sprite area header */
  204.         area = haswin_realloc(area, size, "haswin_clearusersprites", "sprite area");
  205.         area[0] = size;
  206.         area[1] = 0;
  207.         area[2] = 16;
  208.         area[3] = 16;
  209.         regs.r[0] = 0x109;
  210.         regs.r[1] = (int)area;
  211.         haswin_spriteop(0, ®s);
  212.         return(area);
  213. }
  214.  
  215. /*
  216.  *      add sprites to the area given.  The area pointer might change
  217.  *      because we check the file size and ensure that there is enough
  218.  *      room by re-allocating if required.  Return the area pointer.
  219.  */
  220. int *haswin_addsprites(char *filename, int *area) {
  221.  
  222.         _kernel_swi_regs  regs;
  223.         int               size;
  224.  
  225.         if ((!filename) || (filename[0] == '\0'))
  226.                 return(area);
  227.         /* get catalogue entry for file */
  228.         regs.r[0] = 17;
  229.         regs.r[1] = (int)filename;
  230.         if ((!haswin_swi(OS_File, ®s)) || (regs.r[0] != 1)) {
  231.                 haswin_interrorprintf("cannot find sprite file '%s'",filename);
  232.                 return(area);
  233.         }
  234.         size = regs.r[4] + 4;        /* + 1 word for luck */
  235.         /* if no sprite area then create one to fit file */
  236.         if (!area)
  237.                 area = haswin_clearsprites(size, 0);
  238.         if (!area) {
  239.                 haswin_interrorprintf("cannot create sprite area for '%s'", filename);
  240.                 return(HASWIN_FALSE);
  241.         }
  242.         /* add size to that of existing sprites in sprite area +16 for
  243.            sprite control block */
  244.         size += area[3] + 16;
  245.         if (size > area[0]) {
  246.                 /* bigger than area, so extend area */
  247.                 area = haswin_realloc(area, size, "haswin_addusersprites", "sprite area");
  248.                 area[0] = size;
  249.         }
  250.         regs.r[0] = 0x10B;
  251.         regs.r[1] = (int)area;
  252.         regs.r[2] = (int)filename;
  253.         haswin_spriteop(0, ®s);
  254.         return(area);
  255. }
  256.  
  257. void haswin_clearusersprites(int size) {
  258.  
  259.         haswin_usersprites = haswin_clearsprites(size, haswin_usersprites);
  260. }
  261.  
  262. void haswin_clearhaswinsprites(int size) {
  263.  
  264.         haswin_haswinsprites=haswin_clearsprites(size,haswin_haswinsprites);
  265. }
  266.  
  267. int haswin_addusersprites(char *name) {
  268.  
  269.         if ((haswin_usersprites=haswin_addsprites(name, haswin_usersprites)) == 0)
  270.                 return(HASWIN_FALSE);
  271.         return(HASWIN_TRUE);
  272. }
  273.  
  274. int haswin_addhaswinsprites(char *name) {
  275.  
  276.         if ((haswin_haswinsprites=haswin_addsprites(name, haswin_haswinsprites)) == 0)
  277.                 return(HASWIN_FALSE);
  278.         return(HASWIN_TRUE);
  279. }
  280.  
  281. int haswin_loadusersprites(char *filename) {
  282.  
  283.         if ((!filename) || (filename[0] == '\0'))
  284.                 return(HASWIN_FALSE);
  285.         haswin_clearusersprites(0);
  286.         return(haswin_addusersprites(filename));
  287. }
  288.  
  289. int haswin_saveusersprites(char *filename) {
  290.  
  291.         _kernel_swi_regs        regs;
  292.  
  293.         if ((!filename) || (filename[0] == '\0'))
  294.                 return(HASWIN_FALSE);
  295.         regs.r[0] = 0x10C;
  296.         regs.r[1] = (int)haswin_usersprites;
  297.         regs.r[2] = (int)filename;
  298.         haswin_spriteop(0, ®s);
  299.         return(HASWIN_TRUE);
  300. }
  301.  
  302. int haswin_makesprite(char *name, int *area, int x, int y, int mode) {
  303.  
  304.         _kernel_swi_regs        regs;
  305.  
  306.         if ((!name) || (x <= 0) || (y <= 0) || (mode < 0))
  307.                 return(HASWIN_FALSE);
  308.         /* create a new sprite for the window.  The size is the size of the
  309.            window and the mode, palette etc. are setup */
  310.         regs.r[0] = 0x10F;              /* create a new sprite */
  311.         regs.r[1] = (int)area;
  312.         regs.r[2] = (int)name;
  313.         regs.r[3] = 1;                  /* include palette data */
  314.         regs.r[4] = x;                  /* width                */
  315.         regs.r[5] = y;                  /* height               */
  316.         regs.r[6] = mode;               /* screen mode          */
  317.         return(haswin_spriteop(0, ®s));
  318. }
  319.  
  320. int haswin_makeusersprite(char *name, int x, int y, int mode) {
  321.  
  322.         return(haswin_makesprite(name, haswin_usersprites, x, y, mode));
  323. }
  324.  
  325. int haswin_makehaswinsprite(char *name, int x, int y, int mode) {
  326.  
  327.         return(haswin_makesprite(name, haswin_haswinsprites, x, y, mode));
  328. }
  329.  
  330. int haswin_deletesprite(char *name, int *area) {
  331.  
  332.         _kernel_swi_regs        regs;
  333.  
  334.         if ((!name) || (haswin_findsprite(name) != (int)area))
  335.                 return(HASWIN_FALSE);
  336.         regs.r[0] = 0x119;              /* delete a sprite */
  337.         regs.r[1] = (int)area;
  338.         regs.r[2] = (int)name;
  339.         return(haswin_spriteop(0, ®s));
  340. }
  341.  
  342. int haswin_deleteusersprite(char *name) {
  343.  
  344.         return(haswin_deletesprite(name, haswin_usersprites));
  345. }
  346.  
  347. int haswin_deletehaswinsprite(char *name) {
  348.  
  349.         return(haswin_deletesprite(name, haswin_haswinsprites));
  350. }
  351.  
  352. /*
  353.  *      create a new sprite called "name" in area "area" and then remember
  354.  *      the sprite so that redraws in the window cause the sprite to be
  355.  *      updated.  Then force a complete redraw of the window as if it were
  356.  *      on top.  When this is done VDU redirection is switched off by
  357.  *      haswin_poll() called routines by setting the sprite field "win" to 0.
  358.  *      Then force a complete redraw of the window as it was.
  359.  *      If called as haswin_windowtosprite(0,0) initialise.
  360.  *      If called with either win or sname 0 then do nothing.
  361.  */
  362. int haswin_windowtosprite(window *win, char *sname, int *area) {
  363.  
  364.         _kernel_swi_regs        regs;
  365.         int                     wptr[11], oldbhan, flgs, winx, winy;
  366.         window                  *slide, *pane;
  367.  
  368.         if ((!win) && (!sname)) {
  369.                 /* no window, or name so initialise and cancel everything */
  370.                 haswin_spritejob.savearea = 0;
  371.                 haswin_spritejob.name = 0;
  372.                 haswin_spritejob.win = 0;
  373.                 return(HASWIN_TRUE);
  374.         }
  375.         if ((!win) || (!sname))
  376.                 return(HASWIN_FALSE);
  377.  
  378.         flgs = haswin_getwindowflags(win);
  379.         if (haswin_findsprite(sname) == (int)area)
  380.                 /* sprite already exists */
  381.                 return(HASWIN_FALSE);
  382.         /* get all the window info needed into the window block */
  383.         haswin_updatefullwindowinfo(win);
  384.         wptr[ 0] = ((int *)win->win)[ 0];
  385.         wptr[ 1] = ((int *)win->win)[ 1];
  386.         wptr[ 2] = ((int *)win->win)[ 2];
  387.         wptr[ 3] = ((int *)win->win)[ 3];
  388.         wptr[ 4] = ((int *)win->win)[ 4];
  389.         wptr[ 5] = ((int *)win->win)[ 5];
  390.         wptr[ 6] = ((int *)win->win)[ 6];
  391.         wptr[ 7] = ((int *)win->win)[10];
  392.         wptr[ 8] = ((int *)win->win)[11];
  393.         wptr[ 9] = ((int *)win->win)[12];
  394.         wptr[10] = ((int *)win->win)[13];
  395.         oldbhan = wptr[6];
  396.         /* create a new sprite for the window.  The size is the size of the
  397.            window and the mode is the current screen mode */
  398.         winx = wptr[ 9]-wptr[7];
  399.         if (flgs & WINDOW_V_SCROLL)
  400.                 winx+=40;
  401.         winx = (winx>>haswin_readvduvariable(VDUVAR_XEigFactor))+2;
  402.         winy = wptr[10]-wptr[8];
  403.         if (flgs & WINDOW_TITLE_BAR)
  404.                 winy+=40;
  405.         if (flgs & WINDOW_H_SCROLL)
  406.                 winy+=40;
  407.         winy = (winy>>haswin_readvduvariable(VDUVAR_YEigFactor))+2;
  408.         haswin_makesprite(sname, area, winx, winy,
  409.                haswin_readvduvariable(VDUVAR_ModeNumber));
  410.  
  411.         regs.r[0] = 0x3E;       /* get size of sprite area */
  412.         if (!haswin_spriteop(sname, ®s))
  413.                 return(HASWIN_FALSE);
  414.         haswin_spritejob.savearea = haswin_malloc(regs.r[3],
  415.                                  "haswin_windowtosprite", "save area");
  416.         haswin_spritejob.name = haswin_malloc(strlen(sname)+1,
  417.                                  "haswin_windowtosprite", "sprite name");
  418.         strcpy(haswin_spritejob.name, sname);
  419.         haswin_spritejob.savearea[0] = 0;
  420.  
  421.         /* disconnect this window from any slides or panes */
  422.         slide = win->slide;
  423.         pane = win->pane;
  424.         win->slide = win->pane = 0;
  425.  
  426.         /* now close the window and poll until it is closed */
  427.         haswin_closewindow(win);
  428.         while ((win->flags & WINDOW_OPEN))
  429.                 haswin_poll();
  430.  
  431.         haswin_spritejob.win = win->handle;
  432.         /* now open the window on top and redraw it */
  433.         haswin_openwindow(win, 0, 0, wptr[ 9]-wptr[ 7], wptr[10]-wptr[ 8],
  434.                                0, 0, -1);
  435.         haswin_redrawwindow(win, wptr[0]-win->orgx, wptr[2]-win->orgx,
  436.                                  wptr[1]-win->orgy, wptr[3]-win->orgy);
  437.  
  438.         /* poll until the sprite redirection is turned off */
  439.         while (haswin_spritejob.win)
  440.                 haswin_poll();
  441.         /* the WIMP is now wrong!  It thinks the window is on top, but it
  442.            doesn't know that the window was not actually drawn on the screen
  443.            but just in the sprite. */
  444.  
  445.         /* now close the window again and poll until it is closed */
  446.         haswin_closewindow(win);
  447.         while ((win->flags & WINDOW_OPEN))
  448.                 haswin_poll();
  449.  
  450.         /* finally open the window back where it was and redraw it */
  451.         haswin_openwindow(win, wptr[0], wptr[1], wptr[2], wptr[3],
  452.                                wptr[4], wptr[5], oldbhan);
  453.         if (flgs & WINDOW_OPEN) {
  454.                 haswin_redrawwindow(win,wptr[0]-win->orgx,wptr[2]-win->orgx,
  455.                                         wptr[1]-win->orgy,wptr[3]-win->orgy);
  456.         } else
  457.                 haswin_closewindow(win);
  458.         haswin_free(haswin_spritejob.name);
  459.         haswin_free(haswin_spritejob.savearea);
  460.         win->slide = slide;
  461.         win->pane = pane;
  462.         return(HASWIN_TRUE);
  463. }
  464.  
  465. /*
  466.  *      create a new sprite called "sname" in the area "area".  We make a
  467.  *      window the size of the icon with no borders, title or scroll bars.
  468.  *      Then we place a copy of the icon in it and redirect into a sprite.
  469.  *      We redraw the window, then delete it and bingo, icon in sprite!
  470.  */
  471. int haswin_icontosprite(icon *ic, char *sname, int *area) {
  472.  
  473.         window                  *twin;
  474.         _kernel_swi_regs        regs;
  475.         int                     blk[9];
  476.         int                     winx, winy;
  477.         
  478.         if (haswin_findsprite(sname) == (int)area)
  479.                 /* sprite already exists in area */
  480.                 return(HASWIN_FALSE);
  481.         twin=haswin_findwindowhandle(ic->whandle);
  482.         if ((int)twin <= 0)
  483.                 /* icon must be in window, not on icon bar */
  484.                 return(HASWIN_FALSE);
  485.         /*
  486.          *      make a window to put the icon in, this window is like
  487.          *      the real one it is in, except that this window has no
  488.          *      title or scroll bars.
  489.          */
  490.         twin=haswin_makewindow("", ic->ic[2]-ic->ic[0], ic->ic[3]-ic->ic[1],
  491. 0, 0, 0, 0, haswin_getwindowflags(twin) & ~(WINDOW_TITLE_BAR|WINDOW_V_SCROLL|WINDOW_H_SCROLL));
  492.         /* put a copy of the icon into this window, at 0,0 */
  493.         blk[0] = twin->handle;
  494.         blk[1] = 0;
  495.         blk[2] = ic->ic[1]-ic->ic[3];
  496.         blk[3] = ic->ic[2]-ic->ic[0];
  497.         blk[4] = 0;
  498.         blk[5] = ic->ic[4];
  499.         blk[6] = ic->ic[5];
  500.         blk[7] = ic->ic[6];
  501.         blk[8] = ic->ic[7];
  502.         regs.r[1] = (int)blk;
  503.         haswin_swi(HASWIN_Create_icon, ®s);
  504.         /* create the new sprite.  The size is the size of the icon and the
  505.            mode is the current screen mode */
  506.         winx = (ic->ic[2]-ic->ic[0])>>haswin_readvduvariable(VDUVAR_XEigFactor);
  507.         winy = (ic->ic[3]-ic->ic[1])>>haswin_readvduvariable(VDUVAR_YEigFactor);
  508.         haswin_makesprite(sname, area, winx, winy, 
  509.                haswin_readvduvariable(VDUVAR_ModeNumber));
  510.  
  511.         regs.r[0] = 0x3E;       /* get size of sprite area */
  512.         if (!haswin_spriteop(sname, ®s))
  513.                 return(HASWIN_FALSE);
  514.         haswin_spritejob.savearea = haswin_malloc(regs.r[3],
  515.                                  "haswin_windowtosprite", "save area");
  516.         haswin_spritejob.name = haswin_malloc(strlen(sname)+1,
  517.                                  "haswin_windowtosprite", "sprite name");
  518.         strcpy(haswin_spritejob.name, sname);
  519.         haswin_spritejob.savearea[0] = 0;
  520.  
  521.         haswin_spritejob.win = twin->handle;
  522.         /* now open the window on top and redraw it */
  523.         haswin_openwindow(twin,0,0,ic->ic[2]-ic->ic[0],ic->ic[3]-ic->ic[1],
  524.                 0, 0, -1);
  525.  
  526.         /* poll until the sprite redirection is turned off */
  527.         while (haswin_spritejob.win)
  528.                 haswin_poll();
  529.         /* the WIMP is now wrong!  It thinks the window is on top, but it
  530.            doesn't know that the window was not actually drawn on the screen
  531.            but just in the sprite. */
  532.         /* so close the window again and poll until it is closed */
  533.         haswin_closewindow(twin);
  534.         while ((twin->flags & WINDOW_OPEN))
  535.                 haswin_poll();
  536.         /* finished, so delete the window and free the used space */
  537.         haswin_deletewindow(twin);
  538.         haswin_free(haswin_spritejob.name);
  539.         haswin_free(haswin_spritejob.savearea);
  540.         return(HASWIN_TRUE);
  541. }
  542.  
  543.