home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 420.lha / OdinLibrary_v2.7 / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-01  |  11.6 KB  |  438 lines

  1. /****************************************************************
  2.   draw.c V1.2
  3.   Created 30-Aug-90 by Peter Ørbæk
  4.   Last modified 2-Sep-90 by Peter Ørbæk
  5.   This is in the Public Domain.
  6.   Demo of some features of odin.library
  7.   Draws lines in multiple windows
  8.   Compiles with Aztec C3.40A, certainly not very ANSI-like
  9.   NB. Use tabsize = 3 for best looks
  10. *****************************************************************/
  11.  
  12. #include    "exec/types.h"
  13. #include    "exec/ports.h"
  14. #include    "exec/memory.h"
  15. #include    "exec/interrupts.h"
  16. #include    "exec/semaphores.h"
  17. #include    "exec/tasks.h"
  18. #include    "graphics/graphint.h"
  19. #include    "graphics/rastport.h"
  20. #include    "graphics/text.h"
  21. #include    "intuition/intuition.h"
  22. #include    "stdio.h"
  23. #include    "odin.h"
  24.  
  25. /* function return-types */
  26. void *OpenLibrary(),*AllocRemember();
  27. int strlen();
  28. char *strcpy(),*strcat();
  29. struct Window *OpenWindow();
  30. struct MsgPort *CreatePort();
  31. void *GetMsg();
  32.  
  33. /* global data */
  34. void *IntuitionBase,*GfxBase;
  35. void *OdinBase;
  36. struct SignalSemaphore ss,sem;
  37.  
  38. /* for debugging, surround evt. printf's with this */
  39. #define CR(s) ObtainSemaphore(&ss); { s } ReleaseSemaphore(&ss);
  40.  
  41. /*****************************************************************/
  42.  
  43. /* create menu from simple data */
  44. struct Menu *create_menu(menutitle,text,num)
  45. char *text[], *menutitle;
  46. int num;
  47. {
  48.     struct Remember *rk;
  49.     struct Menu *menu;
  50.     struct MenuItem *item,*prev_item;
  51.     struct IntuiText *tt;
  52.     int i;
  53.  
  54.     rk = NULL;
  55.     menu = (struct Menu *)AllocRemember(&rk,
  56.             (long)sizeof(struct Menu),MEMF_CLEAR|MEMF_PUBLIC);
  57.     if(menu == NULL) goto cleanup;
  58.  
  59.     menu->Width = 10*strlen(menutitle);
  60.     menu->Height = 10*num+5;
  61.     menu->Flags = MENUENABLED;
  62.     menu->MenuName = (BYTE *)menutitle;
  63.     
  64.     for(i = 0; i < num; i++) {
  65.         item = (struct MenuItem *)AllocRemember(&rk,(long)sizeof(struct MenuItem),MEMF_CLEAR|MEMF_PUBLIC);
  66.         if(item == NULL) goto cleanup;
  67.  
  68.         if(i == 0) menu->FirstItem = item;
  69.         if(i > 0) prev_item->NextItem = item;
  70.         item->TopEdge = 10*i;
  71.         item->Width = 10*strlen(text[i]);
  72.         item->Height = 10;
  73.         item->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
  74.  
  75.         tt = (struct IntuiText *)AllocRemember(&rk,(long)sizeof(struct IntuiText),MEMF_CLEAR|MEMF_PUBLIC);
  76.         if(tt == NULL) goto cleanup;
  77.  
  78.         tt->FrontPen = 0; tt->BackPen = 1;
  79.         tt->DrawMode = JAM2;
  80.         tt->IText = (UBYTE *)text[i];
  81.  
  82.         item->ItemFill = (APTR)tt;
  83.         prev_item = item;
  84.     }
  85.  
  86.     FreeRemember(&rk,FALSE);
  87.     return menu;
  88.  
  89.     cleanup:
  90.         {
  91.             FreeRemember(&rk,TRUE);
  92.             return NULL;
  93.         }
  94.  
  95. }
  96.  
  97. /* free memory used by Menu */
  98. void destroy_menu(menu)
  99. struct Menu *menu;
  100. {
  101.     struct MenuItem *item,*next_item;
  102.     struct IntuiText *tt;
  103.  
  104.     item = menu->FirstItem;
  105.     FreeMem(menu,(long)sizeof(struct Menu));
  106.  
  107.     while(item != NULL) {
  108.         FreeMem(item->ItemFill,(long)sizeof(struct IntuiText));
  109.         next_item = item->NextItem;
  110.         FreeMem(item,(long)sizeof(struct MenuItem));
  111.         item = next_item;
  112.     }
  113. }
  114.  
  115. /*********************************************************************/
  116.  
  117. /* envelope used to communicate refresher<->windowmanager */
  118. struct DrawEnv {
  119.     Envelope e;
  120.     int type;            /* what type of action to take */
  121.     struct Window *window;
  122.     char *cmdname;        /* name of envelope that holds command */
  123.     char *replyname;    /* name of envelope that is used to reply */
  124. };
  125.  
  126. /* draw a line in a non-GZZ window */
  127. void line(rp,x,y,x1,y1)
  128. struct RastPort *rp;
  129. int x,y,x1,y1;
  130. {
  131.     x += 4; x1 += 4;            /* don't write over the windowframe */
  132.     y += 10; y1 += 10;
  133.     Move(rp,(long)x,(long)y);
  134.     Draw(rp,(long)x1,(long)y1);
  135. }
  136.  
  137. /* sub-routine for drawing the graphics, polls for commands from manager */
  138. struct DrawEnv *draw_pattern(rp,w,h,envname)
  139. struct RastPort *rp;
  140. UWORD w,h;
  141. char *envname;
  142. {
  143.     UWORD    x,y;
  144.     struct DrawEnv *env;
  145.  
  146.     w -= 8+14; h -= 14;        /* adjust for borders */
  147.  
  148.     SetDrMd(rp,JAM2+COMPLEMENT);
  149.     SetAPen(rp,1L); SetBPen(rp,0L);
  150.     while(1) {
  151.         for(x = 0; x < w; x += 2) {
  152.             line(rp,x,0,w-x,h);
  153.             if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
  154.         }
  155.         for(y = 0; y < h; y += 2) {
  156.             line(rp,w,y,0,h-y);
  157.             if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
  158.         }
  159.         for(x = 0; x < w; x += 2) {
  160.             line(rp,x,0,x,h);
  161.             if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
  162.         }
  163.         for(y = 0; y < h; y += 2) {
  164.             line(rp,0,y,w,y);
  165.             if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
  166.         }
  167.     }
  168. }
  169.  
  170. /* DrawerEnv.type's */
  171. #define DRAWER_RESIZED 1    /* sent when new size is settled upon */
  172. #define DRAWER_QUIT 2        /* ask refresher to die */
  173. #define DRAWER_SUSPEND 3    /* ask refresher to wait */
  174.  
  175. /* body for each of the refreshers tasks (drawer) */
  176. Envelope *drawing(drawenv)
  177. struct DrawEnv *drawenv;
  178. {
  179.     struct RastPort *myrp;
  180.     int w,h,active;
  181.     struct DrawEnv *env;
  182.  
  183.     myrp = drawenv->window->RPort;
  184.     w = drawenv->window->Width;
  185.     h = drawenv->window->Height;
  186.     active = TRUE;
  187.  
  188.     do {
  189.         env = draw_pattern(myrp,w,h,drawenv->cmdname);
  190.         switch(env->type) {
  191.             case DRAWER_QUIT:
  192.                 active = FALSE;    /* don't dispose ! */
  193.                 break;
  194.             case DRAWER_SUSPEND:
  195.                 /* tell windowmanager we are waiting */
  196.                 OutEmptyEnvelope(drawenv->replyname);
  197.                 DisposeEnvelope(env);
  198.                 /* wait for user to resize window */
  199.                 env = (struct DrawEnv *)AwaitNamedEnvelope(drawenv->cmdname);
  200.                 myrp = env->window->RPort;
  201.                 w = env->window->Width;
  202.                 h = env->window->Height;
  203.                 DisposeEnvelope(env);
  204.                 SetRast(myrp,0L);
  205.                 RefreshWindowFrame(drawenv->window);
  206.                 break;                
  207.         }
  208.     } while(active);
  209.  
  210.     return (Envelope *)drawenv;
  211. }
  212.  
  213. /**************************************************************************/
  214.  
  215. /* WindowPack.cmd defs */
  216. #define MASTER_SPAWN 1    /* ask master-process (first one) to spawn new window */
  217. #define MASTER_DIE 2        /* tell master that this process is dead */
  218. #define MASTERNAME "MasterProcess"    /* envelope-name to comm. with master */
  219.  
  220. /* this kind of envelope is used to communicate between managers and master */
  221. struct WindowPack {
  222.     Envelope e;
  223.     /* first the params from master to handler transfered at startup */
  224.     struct NewWindow nw;
  225.     char *taskname;        /* name of refreshertask to start */
  226.     struct Menu *menu;    /* menu to add */
  227.     /* second the params. from handler to master eg. for spawning */
  228.     int cmd;
  229.     struct Window *window;
  230. };
  231.  
  232. /* body of the windowmanagers */
  233. Envelope *windowhandler(wp)
  234. struct WindowPack *wp;
  235. {
  236.     struct Window *win;        /* the window handled here */
  237.     BOOL active = TRUE;        /* are we running still? */
  238.     struct IntuiMessage *imsg;    /* the intuimsg from UserPort */
  239.     struct DrawEnv drawenv,*te,*de;    /* for communication with drawer task */
  240.     char cmdname[30];            /* name of envelope to pass commands to drawer */
  241.     char drawerreply[30];    /* drawer can reply with this name */
  242.     struct WindowPack *ae;    /* comm. windowhandler<->mastertask */
  243.  
  244.     /* generate unique names for comms. with drawer */
  245.     UniqueName(strcpy(&cmdname[0],"dName"));
  246.     UniqueName(strcpy(&drawerreply[0],"dReply"));
  247.  
  248.     CR(printf("cmd: %s reply: %s\n",cmdname,drawerreply);)
  249.  
  250.     /* init parts of NewWindow-struct common to all windows */
  251.     wp->nw.Width = 300; wp->nw.Height = 100;
  252.     wp->nw.DetailPen = 0; wp->nw.BlockPen = 1;
  253.     wp->nw.IDCMPFlags = REFRESHWINDOW|
  254.             MENUPICK|
  255.             CLOSEWINDOW|
  256.             SIZEVERIFY|
  257.             NEWSIZE;
  258.     wp->nw.Flags = WINDOWSIZING|
  259.             WINDOWDRAG|
  260.             WINDOWDEPTH|
  261.             WINDOWCLOSE|
  262.             SIMPLE_REFRESH|
  263.             ACTIVATE;
  264.     wp->nw.Type = WBENCHSCREEN;
  265.     wp->nw.MinWidth = 40; wp->nw.MaxWidth = 640;
  266.     wp->nw.MinHeight = 30; wp->nw.MaxHeight = -1;
  267.  
  268.     /* open my window */
  269.     wp->cmd = MASTER_DIE;        /* prepare for evt. failure */
  270.     win = OpenWindow(&wp->nw);
  271.     if(win == NULL) return (Envelope *)wp;
  272.  
  273.     /* set up the menu */
  274.     SetMenuStrip(win,wp->menu);
  275.  
  276.     /* init parameters for drawer-task */
  277.     te = (struct DrawEnv *)CreateEnvelope(wp->taskname,(long)sizeof(struct DrawEnv));
  278.     te->e.e_proc = drawing;
  279.     te->replyname = &drawerreply[0];
  280.     te->cmdname = &cmdname[0];
  281.     te->window = win;
  282.  
  283.     /* create new task for drawer */
  284.     Eval(te,0L,4000L,EVAL_TASK);
  285.  
  286.     /* the messagehandler loop */
  287.     do {
  288.         WaitPort(win->UserPort);
  289.         imsg = (struct IntuiMessage *)GetMsg(win->UserPort);
  290.  
  291.         switch(imsg->Class) {
  292.             case SIZEVERIFY:
  293.                 de = (struct DrawEnv *)CreateEnvelope(&cmdname[0],(long)sizeof(struct DrawEnv));
  294.                 if(de) {
  295.                     de->type = DRAWER_SUSPEND;
  296.                     Out(de);
  297.                     DisposeEnvelope(AwaitNamedEnvelope(&drawerreply[0]));
  298.                 }
  299.                 break;
  300.             case NEWSIZE:
  301.                 de = (struct DrawEnv *)CreateEnvelope(&cmdname[0],(long)sizeof(struct DrawEnv));
  302.                 de->type = DRAWER_RESIZED;
  303.                 de->window = win;
  304.                 Out(de);
  305.                 break;
  306.             case REFRESHWINDOW:
  307.                 SetRast(win->RPort,0L);
  308.                 RefreshWindowFrame(win);
  309.                 break;
  310.             case MENUPICK:
  311.                 switch(ITEMNUM(imsg->Code)) {
  312.                     case NOITEM:
  313.                         break;
  314.                     case 0: /* try to spawn new window */
  315.                         ae = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
  316.                         if(ae) {
  317.                             ae->cmd = MASTER_SPAWN;
  318.                             ae->window = win;
  319.                             Out(ae);
  320.                         }
  321.                         break;
  322.                     case 1: /* quit, same as closebox */
  323.                         active = FALSE;
  324.                         break;
  325.                     default:
  326.                         break;
  327.                 }
  328.                 break;
  329.             case CLOSEWINDOW:
  330.                 active = FALSE;
  331.                 break;
  332.             default:
  333.                 break;
  334.         }
  335.         ReplyMsg(imsg);
  336.     } while(active);
  337.  
  338.     /* ask drawer-task to die. */
  339.     InitEnvelope(&drawenv,&cmdname[0],(long)sizeof(struct DrawEnv),0L);
  340.     drawenv.type = DRAWER_QUIT;
  341.     Out(&drawenv);
  342.  
  343.     /* erase menu */
  344.     ClearMenuStrip(win);
  345.  
  346.     /* wait for drawer-task to die */
  347.     DisposeEnvelope(AwaitNamedEnvelope(wp->taskname));
  348.  
  349.     /* close window and die */
  350.     CloseWindow(win);
  351.     return (Envelope *)wp;    /* cmd field already set up to MASTER_DIE */
  352. }
  353.  
  354. /************************************************************************/
  355.  
  356. char *mtitle = "Main menu";    /* title of the menu */
  357.  
  358. char *items[] = {                /* args to create_menu() */
  359.     "Spawn new",
  360.     "Quit     "
  361. };
  362.  
  363. main()
  364. {
  365.     struct WindowPack *wp,*args;    /* for comms. with windowmanagers */
  366.     int running = 0;        /* number of windowmanagers running */
  367.     struct Menu *menu;    /* menu for windows */
  368.     char name[30][30];    /* holds names of refresher tasks */
  369.  
  370.     OdinBase = IntuitionBase = GfxBase = NULL;
  371.     menu = NULL;
  372.  
  373.     /* open various libs */
  374.     if(!(OdinBase = OpenLibrary("RAM:odin.library",0L))) goto do_exit;
  375.     if(!(GfxBase = OpenLibrary("graphics.library",0L))) goto do_exit;
  376.     if(!(IntuitionBase = OpenLibrary("intuition.library",0L))) goto do_exit;
  377.  
  378.     InitSemaphore(&ss);    /* used in CR() macro */
  379.     UniqueName(NULL);        /* init first suffix */
  380.  
  381.     /* create shared menu */
  382.     if(!(menu = create_menu(mtitle,items,2))) {
  383.         printf("didn't create menu\n");
  384.         goto do_exit;
  385.     }
  386.  
  387.     /* create parameters to windowmanager */
  388.     wp = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
  389.     wp->nw.LeftEdge = 0; wp->nw.TopEdge = 0;
  390.     wp->nw.Title = (UBYTE *)"Initial Window";
  391.     wp->e.e_proc = windowhandler;
  392.     wp->taskname = "initrefresh";    /* name of refreshertask */
  393.     wp->menu = menu;
  394.  
  395.     /* start initial windowhandler as separate task */    
  396.     if(!Eval(wp,1L,8000L,EVAL_PROCESS)) {
  397.         printf("couldn't create initial windowmanager-task\n");
  398.         goto do_exit;
  399.     }
  400.     running++;
  401.  
  402.     /* messagehandling-loop */
  403.     do {
  404.         args = (struct WindowPack *)AwaitNamedEnvelope(MASTERNAME);
  405.         switch(args->cmd) {
  406.             case MASTER_SPAWN:
  407.                 /* create parameters to windowmanager */
  408.                 wp = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
  409.                 if(wp) {
  410.                     wp->nw.LeftEdge = args->window->LeftEdge+10;
  411.                     wp->nw.TopEdge = args->window->TopEdge+20;
  412.                     wp->nw.Title = (UBYTE *)"Secondary Window";
  413.                     wp->e.e_proc = windowhandler;
  414.                     wp->taskname = UniqueName(strcpy(&name[running][0],"refresh"));
  415.                     CR(printf("taskname: %s\n",wp->taskname);)
  416.                     wp->menu = menu;
  417.                     /* spawn new task if possible */
  418.                     if(Eval(wp,1L,8000L,EVAL_PROCESS)) running++;
  419.                 }
  420.                 break;
  421.             case MASTER_DIE:
  422.                 running--;
  423.                 break;
  424.             default:
  425.                 break;
  426.         }
  427.         DisposeEnvelope(args);
  428.     } while(running);
  429.  
  430.     do_exit:
  431.         {
  432.             if(menu) destroy_menu(menu);    /* free memory used by the menu */
  433.             if(IntuitionBase) CloseLibrary(IntuitionBase);
  434.             if(GfxBase) CloseLibrary(GfxBase);
  435.             if(OdinBase) CloseLibrary(OdinBase);
  436.         }
  437. }
  438.