home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- draw.c V1.2
- Created 30-Aug-90 by Peter Ørbæk
- Last modified 2-Sep-90 by Peter Ørbæk
- This is in the Public Domain.
- Demo of some features of odin.library
- Draws lines in multiple windows
- Compiles with Aztec C3.40A, certainly not very ANSI-like
- NB. Use tabsize = 3 for best looks
- *****************************************************************/
-
- #include "exec/types.h"
- #include "exec/ports.h"
- #include "exec/memory.h"
- #include "exec/interrupts.h"
- #include "exec/semaphores.h"
- #include "exec/tasks.h"
- #include "graphics/graphint.h"
- #include "graphics/rastport.h"
- #include "graphics/text.h"
- #include "intuition/intuition.h"
- #include "stdio.h"
- #include "odin.h"
-
- /* function return-types */
- void *OpenLibrary(),*AllocRemember();
- int strlen();
- char *strcpy(),*strcat();
- struct Window *OpenWindow();
- struct MsgPort *CreatePort();
- void *GetMsg();
-
- /* global data */
- void *IntuitionBase,*GfxBase;
- void *OdinBase;
- struct SignalSemaphore ss,sem;
-
- /* for debugging, surround evt. printf's with this */
- #define CR(s) ObtainSemaphore(&ss); { s } ReleaseSemaphore(&ss);
-
- /*****************************************************************/
-
- /* create menu from simple data */
- struct Menu *create_menu(menutitle,text,num)
- char *text[], *menutitle;
- int num;
- {
- struct Remember *rk;
- struct Menu *menu;
- struct MenuItem *item,*prev_item;
- struct IntuiText *tt;
- int i;
-
- rk = NULL;
- menu = (struct Menu *)AllocRemember(&rk,
- (long)sizeof(struct Menu),MEMF_CLEAR|MEMF_PUBLIC);
- if(menu == NULL) goto cleanup;
-
- menu->Width = 10*strlen(menutitle);
- menu->Height = 10*num+5;
- menu->Flags = MENUENABLED;
- menu->MenuName = (BYTE *)menutitle;
-
- for(i = 0; i < num; i++) {
- item = (struct MenuItem *)AllocRemember(&rk,(long)sizeof(struct MenuItem),MEMF_CLEAR|MEMF_PUBLIC);
- if(item == NULL) goto cleanup;
-
- if(i == 0) menu->FirstItem = item;
- if(i > 0) prev_item->NextItem = item;
- item->TopEdge = 10*i;
- item->Width = 10*strlen(text[i]);
- item->Height = 10;
- item->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
-
- tt = (struct IntuiText *)AllocRemember(&rk,(long)sizeof(struct IntuiText),MEMF_CLEAR|MEMF_PUBLIC);
- if(tt == NULL) goto cleanup;
-
- tt->FrontPen = 0; tt->BackPen = 1;
- tt->DrawMode = JAM2;
- tt->IText = (UBYTE *)text[i];
-
- item->ItemFill = (APTR)tt;
- prev_item = item;
- }
-
- FreeRemember(&rk,FALSE);
- return menu;
-
- cleanup:
- {
- FreeRemember(&rk,TRUE);
- return NULL;
- }
-
- }
-
- /* free memory used by Menu */
- void destroy_menu(menu)
- struct Menu *menu;
- {
- struct MenuItem *item,*next_item;
- struct IntuiText *tt;
-
- item = menu->FirstItem;
- FreeMem(menu,(long)sizeof(struct Menu));
-
- while(item != NULL) {
- FreeMem(item->ItemFill,(long)sizeof(struct IntuiText));
- next_item = item->NextItem;
- FreeMem(item,(long)sizeof(struct MenuItem));
- item = next_item;
- }
- }
-
- /*********************************************************************/
-
- /* envelope used to communicate refresher<->windowmanager */
- struct DrawEnv {
- Envelope e;
- int type; /* what type of action to take */
- struct Window *window;
- char *cmdname; /* name of envelope that holds command */
- char *replyname; /* name of envelope that is used to reply */
- };
-
- /* draw a line in a non-GZZ window */
- void line(rp,x,y,x1,y1)
- struct RastPort *rp;
- int x,y,x1,y1;
- {
- x += 4; x1 += 4; /* don't write over the windowframe */
- y += 10; y1 += 10;
- Move(rp,(long)x,(long)y);
- Draw(rp,(long)x1,(long)y1);
- }
-
- /* sub-routine for drawing the graphics, polls for commands from manager */
- struct DrawEnv *draw_pattern(rp,w,h,envname)
- struct RastPort *rp;
- UWORD w,h;
- char *envname;
- {
- UWORD x,y;
- struct DrawEnv *env;
-
- w -= 8+14; h -= 14; /* adjust for borders */
-
- SetDrMd(rp,JAM2+COMPLEMENT);
- SetAPen(rp,1L); SetBPen(rp,0L);
- while(1) {
- for(x = 0; x < w; x += 2) {
- line(rp,x,0,w-x,h);
- if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
- }
- for(y = 0; y < h; y += 2) {
- line(rp,w,y,0,h-y);
- if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
- }
- for(x = 0; x < w; x += 2) {
- line(rp,x,0,x,h);
- if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
- }
- for(y = 0; y < h; y += 2) {
- line(rp,0,y,w,y);
- if(env = (struct DrawEnv *)PollNamedEnvelope(envname)) return env;
- }
- }
- }
-
- /* DrawerEnv.type's */
- #define DRAWER_RESIZED 1 /* sent when new size is settled upon */
- #define DRAWER_QUIT 2 /* ask refresher to die */
- #define DRAWER_SUSPEND 3 /* ask refresher to wait */
-
- /* body for each of the refreshers tasks (drawer) */
- Envelope *drawing(drawenv)
- struct DrawEnv *drawenv;
- {
- struct RastPort *myrp;
- int w,h,active;
- struct DrawEnv *env;
-
- myrp = drawenv->window->RPort;
- w = drawenv->window->Width;
- h = drawenv->window->Height;
- active = TRUE;
-
- do {
- env = draw_pattern(myrp,w,h,drawenv->cmdname);
- switch(env->type) {
- case DRAWER_QUIT:
- active = FALSE; /* don't dispose ! */
- break;
- case DRAWER_SUSPEND:
- /* tell windowmanager we are waiting */
- OutEmptyEnvelope(drawenv->replyname);
- DisposeEnvelope(env);
- /* wait for user to resize window */
- env = (struct DrawEnv *)AwaitNamedEnvelope(drawenv->cmdname);
- myrp = env->window->RPort;
- w = env->window->Width;
- h = env->window->Height;
- DisposeEnvelope(env);
- SetRast(myrp,0L);
- RefreshWindowFrame(drawenv->window);
- break;
- }
- } while(active);
-
- return (Envelope *)drawenv;
- }
-
- /**************************************************************************/
-
- /* WindowPack.cmd defs */
- #define MASTER_SPAWN 1 /* ask master-process (first one) to spawn new window */
- #define MASTER_DIE 2 /* tell master that this process is dead */
- #define MASTERNAME "MasterProcess" /* envelope-name to comm. with master */
-
- /* this kind of envelope is used to communicate between managers and master */
- struct WindowPack {
- Envelope e;
- /* first the params from master to handler transfered at startup */
- struct NewWindow nw;
- char *taskname; /* name of refreshertask to start */
- struct Menu *menu; /* menu to add */
- /* second the params. from handler to master eg. for spawning */
- int cmd;
- struct Window *window;
- };
-
- /* body of the windowmanagers */
- Envelope *windowhandler(wp)
- struct WindowPack *wp;
- {
- struct Window *win; /* the window handled here */
- BOOL active = TRUE; /* are we running still? */
- struct IntuiMessage *imsg; /* the intuimsg from UserPort */
- struct DrawEnv drawenv,*te,*de; /* for communication with drawer task */
- char cmdname[30]; /* name of envelope to pass commands to drawer */
- char drawerreply[30]; /* drawer can reply with this name */
- struct WindowPack *ae; /* comm. windowhandler<->mastertask */
-
- /* generate unique names for comms. with drawer */
- UniqueName(strcpy(&cmdname[0],"dName"));
- UniqueName(strcpy(&drawerreply[0],"dReply"));
-
- CR(printf("cmd: %s reply: %s\n",cmdname,drawerreply);)
-
- /* init parts of NewWindow-struct common to all windows */
- wp->nw.Width = 300; wp->nw.Height = 100;
- wp->nw.DetailPen = 0; wp->nw.BlockPen = 1;
- wp->nw.IDCMPFlags = REFRESHWINDOW|
- MENUPICK|
- CLOSEWINDOW|
- SIZEVERIFY|
- NEWSIZE;
- wp->nw.Flags = WINDOWSIZING|
- WINDOWDRAG|
- WINDOWDEPTH|
- WINDOWCLOSE|
- SIMPLE_REFRESH|
- ACTIVATE;
- wp->nw.Type = WBENCHSCREEN;
- wp->nw.MinWidth = 40; wp->nw.MaxWidth = 640;
- wp->nw.MinHeight = 30; wp->nw.MaxHeight = -1;
-
- /* open my window */
- wp->cmd = MASTER_DIE; /* prepare for evt. failure */
- win = OpenWindow(&wp->nw);
- if(win == NULL) return (Envelope *)wp;
-
- /* set up the menu */
- SetMenuStrip(win,wp->menu);
-
- /* init parameters for drawer-task */
- te = (struct DrawEnv *)CreateEnvelope(wp->taskname,(long)sizeof(struct DrawEnv));
- te->e.e_proc = drawing;
- te->replyname = &drawerreply[0];
- te->cmdname = &cmdname[0];
- te->window = win;
-
- /* create new task for drawer */
- Eval(te,0L,4000L,EVAL_TASK);
-
- /* the messagehandler loop */
- do {
- WaitPort(win->UserPort);
- imsg = (struct IntuiMessage *)GetMsg(win->UserPort);
-
- switch(imsg->Class) {
- case SIZEVERIFY:
- de = (struct DrawEnv *)CreateEnvelope(&cmdname[0],(long)sizeof(struct DrawEnv));
- if(de) {
- de->type = DRAWER_SUSPEND;
- Out(de);
- DisposeEnvelope(AwaitNamedEnvelope(&drawerreply[0]));
- }
- break;
- case NEWSIZE:
- de = (struct DrawEnv *)CreateEnvelope(&cmdname[0],(long)sizeof(struct DrawEnv));
- de->type = DRAWER_RESIZED;
- de->window = win;
- Out(de);
- break;
- case REFRESHWINDOW:
- SetRast(win->RPort,0L);
- RefreshWindowFrame(win);
- break;
- case MENUPICK:
- switch(ITEMNUM(imsg->Code)) {
- case NOITEM:
- break;
- case 0: /* try to spawn new window */
- ae = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
- if(ae) {
- ae->cmd = MASTER_SPAWN;
- ae->window = win;
- Out(ae);
- }
- break;
- case 1: /* quit, same as closebox */
- active = FALSE;
- break;
- default:
- break;
- }
- break;
- case CLOSEWINDOW:
- active = FALSE;
- break;
- default:
- break;
- }
- ReplyMsg(imsg);
- } while(active);
-
- /* ask drawer-task to die. */
- InitEnvelope(&drawenv,&cmdname[0],(long)sizeof(struct DrawEnv),0L);
- drawenv.type = DRAWER_QUIT;
- Out(&drawenv);
-
- /* erase menu */
- ClearMenuStrip(win);
-
- /* wait for drawer-task to die */
- DisposeEnvelope(AwaitNamedEnvelope(wp->taskname));
-
- /* close window and die */
- CloseWindow(win);
- return (Envelope *)wp; /* cmd field already set up to MASTER_DIE */
- }
-
- /************************************************************************/
-
- char *mtitle = "Main menu"; /* title of the menu */
-
- char *items[] = { /* args to create_menu() */
- "Spawn new",
- "Quit "
- };
-
- main()
- {
- struct WindowPack *wp,*args; /* for comms. with windowmanagers */
- int running = 0; /* number of windowmanagers running */
- struct Menu *menu; /* menu for windows */
- char name[30][30]; /* holds names of refresher tasks */
-
- OdinBase = IntuitionBase = GfxBase = NULL;
- menu = NULL;
-
- /* open various libs */
- if(!(OdinBase = OpenLibrary("RAM:odin.library",0L))) goto do_exit;
- if(!(GfxBase = OpenLibrary("graphics.library",0L))) goto do_exit;
- if(!(IntuitionBase = OpenLibrary("intuition.library",0L))) goto do_exit;
-
- InitSemaphore(&ss); /* used in CR() macro */
- UniqueName(NULL); /* init first suffix */
-
- /* create shared menu */
- if(!(menu = create_menu(mtitle,items,2))) {
- printf("didn't create menu\n");
- goto do_exit;
- }
-
- /* create parameters to windowmanager */
- wp = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
- wp->nw.LeftEdge = 0; wp->nw.TopEdge = 0;
- wp->nw.Title = (UBYTE *)"Initial Window";
- wp->e.e_proc = windowhandler;
- wp->taskname = "initrefresh"; /* name of refreshertask */
- wp->menu = menu;
-
- /* start initial windowhandler as separate task */
- if(!Eval(wp,1L,8000L,EVAL_PROCESS)) {
- printf("couldn't create initial windowmanager-task\n");
- goto do_exit;
- }
- running++;
-
- /* messagehandling-loop */
- do {
- args = (struct WindowPack *)AwaitNamedEnvelope(MASTERNAME);
- switch(args->cmd) {
- case MASTER_SPAWN:
- /* create parameters to windowmanager */
- wp = (struct WindowPack *)CreateEnvelope(MASTERNAME,(long)sizeof(struct WindowPack));
- if(wp) {
- wp->nw.LeftEdge = args->window->LeftEdge+10;
- wp->nw.TopEdge = args->window->TopEdge+20;
- wp->nw.Title = (UBYTE *)"Secondary Window";
- wp->e.e_proc = windowhandler;
- wp->taskname = UniqueName(strcpy(&name[running][0],"refresh"));
- CR(printf("taskname: %s\n",wp->taskname);)
- wp->menu = menu;
- /* spawn new task if possible */
- if(Eval(wp,1L,8000L,EVAL_PROCESS)) running++;
- }
- break;
- case MASTER_DIE:
- running--;
- break;
- default:
- break;
- }
- DisposeEnvelope(args);
- } while(running);
-
- do_exit:
- {
- if(menu) destroy_menu(menu); /* free memory used by the menu */
- if(IntuitionBase) CloseLibrary(IntuitionBase);
- if(GfxBase) CloseLibrary(GfxBase);
- if(OdinBase) CloseLibrary(OdinBase);
- }
- }
-