\begindata{text,538373940} \textdsversion{12} \template{default} \define{global } \define{itemize } \define{programexample } \formatnote{\chapter{Example 5: Menus}} \indexi{Menus} Example 5 illustrates how to create an object that has menus. Toolkit provides two classes--\italic{Menulist} The Andrew \indexi{Menulist} \indexi{Class++Menulist} and \italic{Bind} \indexi{Bind} \indexi{Class++Bind} --that together allow objects to bind lists of menus to command procedures. The example program in this section will build upon the program in Example 4. Like Example 4, this program draws \italic{hello world} initially at the center of the window; if the user clicks on the left mouse button, the program draws \italic{hello world} centered at the location of the mouse cursor when the user lets up on the button, if the user clicks on the right mouse button, the string may be dragged around the screen. Like Example 4, the program also responds to two keys: Ctrl-c to center \italic{hello world}, and Ctrl-i to invert the screen. In addition, the program posts a new menu card entitled \bold{Hello World} with two menu items, \bold{Center} and \bold{Invert}. If the user pops-up the \bold{Hello World} menu card and chooses \bold{Center}, the program centers \italic{hello world} in the window; if the user chooses the menu item \bold{Invert}, the program inverts the screen, from white to black and black to white. The discussion that follows presents a step-by-step description of how to modify the \italic{helloworldview} class in Example 4 to produce Example 5. If you were to follow the steps, you would produce a program, called \italic{helloworldapp}, in five files: \itemize{ a hellov.ch file -- will contain the class definition for \italic{helloworldview}. It will be exactly the same as Example 4 with the addition of an extra data declaration for a menu list. a hellov.c file -- will contain statements that import Andrew Toolkit classes and define the object's methods and class procedures. We will add to Example 4's class procedure for initializing a menulist and for binding menu items to command procedures. a helloa.ch file -- will contain the class definition for the application program that will display an instance of the class in a window. This will be exactly the same as in Example 4. a helloa.c -- will contain declarations needed by the Andrew Toolkit linking and loading facilities as well the definition of the \italic{helloworldview} application method. This will be exactly the same as in Example 4. Makefile -- will contain the directions for compiling, linking and loading. This will be exactly the same as Example 4. } For a complete listing of these files, see \italic{Program listing for Example 5} at the end of this section on p. \begindata{textref,539236104} \textdsversion{12} # ExFiveListing\ \enddata{textref,539236104} \view{textrefv,539236104,910,0,0}. The source code is available in the directory /usr/andrew/examples/ex5. Although the discussion of the steps refers directly to this example, the information generally applies to the creation of any class that will create menus. \begindata{bp,538929032} \enddata{bp,538929032} \view{bpv,538929032,911,0,0} \section{Running the example program} \formatnote{\bold{Action 1.}\formatnote{ program, at the \bold{command }prompt type } \formatnote{To run the runapp /usr/andrew/examples/ex5/helloa and press the Enter key. } \bold{Response.}\formatnote{ \italic{hello world} }The program will produce a window with centered in the body of the window. \bold{Action 2.} \formatnote{ window, position the }To move \italic{hello world} in the mouse cursor within the program's window, click with the left mouse button, or click on the right mouse button, and drag the mouse. \bold{Response. }\formatnote{ wherever you release the mouse button. } \italic{hello world} will be drawn \bold{Action 3.}\formatnote{ }To use the menus to center \italic{hello world}, position the mouse cursor within the program's window, pop up the menus, and choose \bold{Center} from the \bold{Hello World} menu card. \bold{Response. }\formatnote{ the center of the window. } \italic{hello world} will be drawn in \bold{Action 4.}\formatnote{ up the menus and }To invert the drawing, using menus, pop choose \bold{Invert} from the \bold{Hello World} card. \bold{Response.}\formatnote{ case, it will change }The background will invert. In this from white to black. \bold{Action 5.}\formatnote{ choose \bold{Quit} }To quit the program, pop-up the menus and from the top card. \bold{Response.} \formatnote{ screen. }The program will disappear from the } \begindata{bp,538929288} \enddata{bp,538929288} \view{bpv,538929288,912,0,0} \section{Overview of menu lists} \indexi{Menus++Menu lists} Menu lists provide stacks of menu cards that a user can pop-up within the body of your program's windows. Each menu list corresponds to one stack of menu cards. Your program can have only one stack of menu cards per window, but can have any number of stacks that it posts at different times. There can be any number of cards in a stack. Each card in the stack can have a title and any number of menu items. If you use the methods that \italic{menulist} and \italic{bind} provide to bind a menu item to a command procedure, then when the user chooses that menu item, the \italic{Interaction Manager} will invoke the procedure. For example, if you bind the menu item \bold{Save} to the procedure \italic{Write_Buffer_to_File}, then when the user chooses the menu item \bold{Save}, the \italic{Interaction Manager} will invoke \italic{Write_Buffer_to_File}. The Andrew Toolkit class \italic{Menulist} provides methods for adding menu items to a card or deleting them, and for deleting all the cards from the stack of menu cards. \subsection{Menu chains} \indexi{Menus++Chains} \indexi{Menus++Priority} In the Andrew Toolkit, an object can contain other objects. Since an object may not know what other objects it will contain in advance, there must be a protocol that allows objects to coordinate the menu items that each object may add or delete from the stack of menus. For example, if a multi-media editor containing a drawing editor both add the menu item \bold{Quit}, there must be a way to decide which menu item takes priority. \italic{Menu chains} establish the priority of menu items. Menu chains work according to the following protocol: Each object posts the menus that it wants. If the object is contained in another object, the parent object determines the placement of the child's menu list in a menu chain. If a menu list \italic{ml}\italic{\subscript{j }}occurs after the menu list \italic{ml}\italic{\subscript{i}} in the menu chain, then \italic{ml}\italic{\subscript{j}}'s menus take precedence over \italic{ml}\subscript{\italic{j}}'s. Thus, a parent object can decide that its menus should have precedence over its child's menus, or that its child's menus should have precedence. The usual way to decide precedence is based on input focus: the menus of the object with the input focus should have precedence. \subsection{Flow of control for menus} \indexi{Menus++Flow of control} An object will normally define its menus when it is first loaded. this In case, the object's class procedure, \italic{InitializeClass}, will create a menu list and add its menu items to the menus. Normally, the object will create all the menu lists it will ever use. At this point, the menu items are defined, but they are not yet visible to the user. Whenever an instance of the class is created, its \italic{InitializeObject} method should normally not define the menus, but should \italic{duplicate} the menus of its class in order to save space. \indexi{Menus++Duplication} Most application programs start up by creating a set of views and asking the \italic{Interaction Manager} to make one of the views the input focus. A user can request a view to make itself the input focus by clicking in its visual rectangle. If a view wishes to respond to such user requests, it should request the \italic{Interaction Manager} to give it the input focus upon receiving the \italic{DownTransition} in its \italic{Hit} method. When an object receives the input focus, it should post the \italic{menulist} that it wants to have displayed to the user. If the object does not want menus, it should post a \smaller{NULL} menulist so that its parent menus are posted. When a child posts menus, its parent's \italic{post menu} method is called. If a parent object wants to control which menus appear, it should save all its children's menu lists when it creates the children. After the parent has created all its children, it should create its own menu list, and chain its children's menu lists into the menu chain according to the priority it desires. Then, in its own \italic{post menu} method, it should post the chained list. The menu list that the top-most object posts defines the complete set of menu items that can be displayed to the user. \section{Modifying the class definition} \subsection{Declaring the class} If you are creating a subclass of view that will have menus, you must add a pointer to a menulist structure to the class's data definition. For example, the following is the new class declaration for the example class \italic{helloworldview}: \programexample{ class helloworldview[hellov] : view \{ overrides: FullUpdate(enum view_UpdateType type, long left, long top, long width, long height); Update(); Hit (enum view_MouseAction action, long x, long y, long numberOfClicks) returns struct helloworldview *; ReceiveInputFocus(); LoseInputFocus(); classprocedures: InitializeClass() returns boolean; data: \bold{struct menulist *menulist;} struct keystate *keystate; long x,y; boolean blackOnWhite; boolean newBlackOnWhite; long distX,distY; long newX, newY; boolean HaveDownTransition; boolean haveInputFocus; \}; } Everything is the same as Example 4, except for the data declaration \italic{struct menulist *menulist}. \italic{helloworldview} will store its menu list in \italic{menulist}. Note that any class that uses menus must also override \italic{ReceiveInputFocus} and \italic{LoseInputFocus}. \subsection{Describing the menus} \indexi{Menus++Description} \indexi{Bind description} The description of the menus should be stored in a \smaller{NULL} terminated array of \italic{struct bind_Description}. The structure of a bind description array is described in detail in Example 4. Each entry in the array should be a description of a single menu item binding. For example, the two menu items for helloworldview are described by the following array, \italic{helloworldviewBindings}, in \italic{hellov.c}: \programexample{ static struct bind_Description helloworldviewBindings[]=\{ \{"helloworld-center", "\\003",0,\bold{ "Hello World,Center",}0,0, Center, "Center the helloworld string."\\\}, \{"helloworld-invert", "\\011",0, \bold{"Hello World,Invert",}0,0, Invert, "Invert the helloworld string."\}, NULL \}; } The first entry in the array describes the binding of the menu item \indexi{Menus++Cards} \bold{Center} on the menu card \bold{Hello World} to the procedure \italic{Center}. The item in the first entry, \italic{"helloworldcenter,"} is the user invocation name, discussed in Example 4. The next two items, "\\003",0, are the keyboard descriptions (again, see Example 4). These could be \smaller{NULL},0 if you did not want key bindings at all. The next item, \italic{"Hello World, Center"}, part is the menu string. The before the comma, \italic{Hello World,} specifies the menu card and the part after the comma, \italic{Center,} specifies the menu item. If no card name appears, menu items will appear on the front menu card. The menu items are listed on a card in the order they are added to the menu list and without blank lines between the menu items. Cards are stacked in the order in which they are posted. More complicated menu string formats allow you to control the order and spacing of menu items on the cards) and the stacking of cards. The next item, 0, represents the data to be passed to the procedure upon the user selecting the menu item \bold{Center}; in this example, none. The next item, 0, is the menu mask; again, in this example, none. The remaining items are the same as Example 4. Likewise, the second entry in the array binds the menu item \bold{Invert} on the card \bold{Hello World} to the procedure \italic{Invert}. The third entry in the array is \smaller{NULL} and indicates the end of the description of the bindings. When you run the program and pop-up the menus, you will find that the menu card "Hello World" is the second card in the stack of menus. The first card will be unnamed, and will have the menu item \bold{Quit} on it. The first card is posted by the \italic{Interaction Manger}, \italic{im}, \italic{helloworldview's} parent in the view tree. \indexi{Interaction manager++Menus} \indexi{Menus++Quit option} Parents in the view tree can choose to override menus that a child posts or add to those menus. Normally, parents give precedence to the menus of the view with the input focus. The actual command functions, \italic{Center} and \italic{Invert} were discussed previously in Example 4. They remain exactly the same. \subsection{Creating the menu list for the class} \indexi{Menu list++Creating} \indexi{ \italic{InitializeClass}} \indexi{Class++Initializing} A \italic{menulist} for the class represents the set of bindings from the menu items to the functions to be performed. The same \italic{menulist} can normally be shared among all instances of a view. Thus, like \italic{keymap}, a \italic{menulist} should be created in \italic{InitializeClass}, a class procedure that is called only once--the first time the class is loaded. Likewise, the structure declaration for the \italic{menulist} can be done in the module rather than in the class data. In general, to create menus, you should declare an \italic{InitializeClass} procedure that creates a new \italic{menulist} and associates the menu bindings for the class with the newly created \italic{menulist}. For example, the following creates a \italic{menulist} and associates the \italic{menulist} with the menu descriptions for the view \italic{helloworldview} in the file \italic{hellov.c}: \programexample{ \bold{static struct menulist *helloworldviewMenulist;} boolean helloworldview__InitializeClass(classID) struct classheader *classID; \{ \bold{helloworldviewMenulist=menulist_New();} helloworldviewKeymap=keymap_New(); bind_BindList(helloworldviewBindings, helloworldviewKeymap,\bold{helloworldviewMenulist,}&helloworldview_classi nfo); return TRUE; } \} The statement \italic{static struct menulist *helloworldviewMenulist} declares the menulist structure for this class. The statement \italic{helloworldviewMenulist=menulist_New()} creates a new menulist and stores it in \italic{helloworldviewMenulist}. The statement \italic{bind_BindList (helloworldviewBindings, helloworldviewKeymap, helloworldviewMenulist, &helloworldview_classinfo)} associates the menu descriptions in \italic{helloworldviewBindings} with the newly create menulist, \italic{helloworldviewMenulist}. The method \italic{bind_BindList} is described in Example 4. The second parameter, \italic{helloworldviewKeymap} could be \smaller{NULL} for a class with no key bindings. If you are creating a subclass of view and your application requires dynamic menu items, then you can create multiple menu lists for the class; alternatively, you can use menu masks. \subsection{Duplicating the menu list for the object} \indexi{Menus++Duplicating} Most objects in the same class can share menus. To share menus, when an instance of an object is created, its \italic{InitializeObject} \indexi{Objects++Initializing} \indexi{ \italic{InitializeObject}} method should not create the menus, but should duplicate the menus of its class. The duplicated menus should be stored as part of the view's data for later use in \italic{ReceiveInputFocus}. In addition, a view with menus should set a flag in its \italic{InitializeObject} method to indicate that it does not have the input focus. The following \italic{InitializeObject} method, in \italic{hellov.c}, creates a \italic{menulist} for the object by duplicating the one for the class and associates the \italic{menulist} for the class, \italic{helloworldviewMenulist}, with \italic{hwv}, an instance of the view \italic{helloworldview}: \programexample{ boolean helloworldview__InitializeObject(hwv) struct helloworldview *hwv; \{ hwv->x = POSUNDEF; hwv->y = POSUNDEF; hwv->blackOnWhite = TRUE; hwv->newBlackOnWhite = TRUE; hwv->HaveDownTransition = FALSE; hwv->keystate = keystate_Create(hwv, helloworldviewKeymap); \bold{hwv->menulist = menulist_DuplicateML(helloworldviewMenulist, hwv);} hwv->haveInputFocus = FALSE; return TRUE; \} } The statement \italic{hwv->menulist = menulist_DuplicateML(helloworldviewMenulist, hwv)} creates a duplicate of the class helloworldview's \italic{menulist}, \italic{helloworldviewMenulist}, associates the \italic{menulist} with the view, \italic{hwv}, and stores a pointer to the newly duplicated \italic{menulist} in \italic{hwv>menulist}. The remaining statements are as in Example 4. \subsection{User requests for the input focus} \indexi{Input focus++Requesting} \indexi{Menus++Input focus} By convention, a user can request a \italic{view} to make itself the input focus by clicking within its space on the screen. If a \italic{view} wishes to respond to such user requests, it should request the \italic{Interaction Manager} to give it the input focus upon receiving the \italic{DownTransition} in its \italic{Hit} method. Normally, if you are building a \italic{view} that will have menus, then in the \italic{view}'s \italic{Hit} method, you should request the input focus by calling \italic{WantInputFocus}. In Example 5, the \italic{helloworldview_Hit} method does not need to be modified from Example 4, since it requests the input focus in order to do keyboard input. \paragraph{Receiving the input focus} \indexi{Input focus++Receiving} When the \italic{Interaction Manager} gives a view the input focus, it notifies the view by calling a method, \italic{ReceiveInputFocus}. If you are writing a view that has menus, its \italic{ReceiveInputFocus} method must first set a flag that indicates it has the input focus. In general, you will need to write other methods (\italic{e.g.}, Hit, Update, etc.) so that they test this flag and act accordingly (see Example 4). Second, the view should post its \italic{menulist} to its parent. The \italic{menulist} provides the \italic{Interaction Manager} with the information it needs to post menus appropriately for the view. The following, in \italic{hellov.c}, is the \italic{ReceiveInputFocus} method for this example: \programexample{ void helloworldview__ReceiveInputFocus(hwv) struct helloworldview *hwv; \{ hwv->haveInputFocus = TRUE; hwv->keystate->next = NULL; helloworldview_PostKeyState(hwv, hwv->keystate); \bold{helloworldview_PostMenus(hwv, hwv->menulist);} \} } The statement \italic{hwv->haveInputFocus = \smaller{TRUE}} sets a flag to indicate that \italic{hwv} has the input focus. The statement \italic{helloworldview_PostMenus (hwv, hwv->menulist)} posts the \italic{menulist} \italic{hwv->menulist} for \italic{hwv} to the \italic{Interaction Manager}. If you are creating a view that is overriding view's \italic{ReceiveInputFocus} method, even if your view does not have a \italic{menulist }it should post a \italic{menulist} of \smaller{NULL.} \paragraph{Losing the input focus} \indexi{Input focus++Losing} When the \italic{Interaction Manager} takes the input focus view, it notifies the view by calling \italic{LoseInputFocus}. A \italic{LoseInputFocus} method should set a flag indicating longer has the input focus, then do whatever it needs to do before input focus. away from a view's that it no losing the The following \italic{LoseInputFocus} method for Example 5 is exactly the same as Example 4: \programexample{ void helloworldview__LoseInputFocus(hwv) struct helloworldview *hwv; hwv->haveInputFocus = FALSE; \{ \} } \subsection{Requesting the input focus upon start-up} If you are creating an application that has menus and you want the menus to appear immediately, then it should request the input focus after putting the object in the view tree and before entering the keyboard processor interaction loop. If the input focus is not requested, the menus will not appear until the first call to \italic{FullUpdate}, which occurs after a mouse action. To request the input focus immediately upon start-up, you must include the WantInputFocus statement as you did in the previous example in helloa.c, right after the im_SetView statement. \subsection{Importing Andrew Toolkit procedures} \indexi{Importing} \programexample{ #include <class.h> #include "hellov.eh" #include "graphic.ih" #include "rect.ih" #include "keymap.ih" #include "keystate.ih" #include "bind.ih" \bold{#include "menulist.ih"} } The import/export declarations are exactly the same as in the previous example, with the addition of \italic{menulist.ih} to import the menu list methods. \begindata{bp,538929224} \enddata{bp,538929224} \view{bpv,538929224,913,0,0} \begindata{texttag,539315976} \textdsversion{12} ExFiveListing\ \enddata{texttag,539315976} \view{texttagv,539315976,914,0,0} \section{Program listing for Example 5} \formatnote{ \bold{hellov.ch} class helloworldview[hellov]: view \{ overrides: FullUpdate(enum view_UpdateType type, long left, long top, long width, long height); Update(); Hit (enum view_MouseAction action, long x, long y, long numberOfClicks) returns struct view *; ReceiveInputFocus(); LoseInputFocus(); classprocedures: InitializeClass() returns boolean; data: struct menulist *menulist; struct keystate *keystate; boolean HaveDownTransition; boolean haveInputFocus; long x,y; long distX,distY; boolean blackOnWhite; long newX,newY; boolean newBlackOnWhite; \}; \bold{hellov.c} #include <class.h> #include "hellov.eh" #include "graphic.ih" #include "rect.h" #include "keymap.ih" #include "keystate.ih" #include "menulist.ih" #include "bind.ih" #define POSUNDEF -1 static struct keymap *helloworldviewKeymap; static struct menulist *helloworldviewMenulist; boolean helloworldview__InitializeObject(classID, hwv) struct classheader *classID; struct helloworldview *hwv; \{ hwv->x = POSUNDEF; hwv->y = POSUNDEF; hwv->HaveDownTransition = FALSE; hwv->haveInputFocus = FALSE; hwv->keystate = keystate_Create(hwv, helloworldviewKeymap); hwv->blackOnWhite = TRUE; hwv->newBlackOnWhite = TRUE; hwv->menulist = menulist_DuplicateML(helloworldviewMenulist, hwv); return TRUE; \} void helloworldview__FullUpdate(hwv, type, left, top, width, height) struct helloworldview *hwv; enum view_UpdateType type; long left; long top; long width; long height; \{ struct rectangle myVisualRect; helloworldview_GetVisualBounds(hwv,&myVisualRect); if (hwv->x == POSUNDEF) \{ hwv->x = rectangle_Left(&myVisualRect) + rectangle_Width(&myVisualRect) / 2; hwv->y = rectangle_Top(&myVisualRect) + rectangle_Height(&myVisualRect) / 2; hwv->newX = hwv->x; hwv->newY = hwv->y; \} else \{ hwv->x = hwv->newX; hwv->y = hwv->newY; \} helloworldview_SetTransferMode(hwv, graphic_COPY); if (hwv->blackOnWhite) helloworldview_FillRect(hwv, &myVisualRect, helloworldview_WhitePattern(hwv)); else helloworldview_FillRect(hwv, &myVisualRect, helloworldview_BlackPattern(hwv)); helloworldview_SetTransferMode(hwv, graphic_INVERT); helloworldview_MoveTo(hwv, hwv->x, hwv->y); helloworldview_DrawString(hwv,"hello world", graphic_BETWEENTOPANDBASELINE | graphic_BETWEENLEFTANDRIGHT); \} void helloworldview__Update(hwv) struct helloworldview *hwv; \{ /* TransferMode is graphic_INVERT from the last FullUpdate */ if (hwv->newBlackOnWhite != hwv->blackOnWhite) \{ struct rectangle vr; helloworldview_GetVisualBounds(hwv,&vr); helloworldview_FillRect(hwv, &vr, helloworldview_BlackPattern(hwv)); hwv->blackOnWhite = hwv->newBlackOnWhite; \} if (hwv->newX != hwv->x || hwv->newY != hwv->y) \{ helloworldview_MoveTo(hwv, hwv->x, hwv->y); helloworldview_DrawString(hwv, "hello world", graphic_BETWEENTOPANDBASELINE | graphic_BETWEENLEFTANDRIGHT); hwv->x = hwv->newX; hwv->y = hwv->newY; helloworldview_MoveTo(hwv, hwv->x, hwv->y); helloworldview_DrawString(hwv, "hello world", graphic_BETWEENTOPANDBASELINE | graphic_BETWEENLEFTANDRIGHT); \} \} struct view *helloworldview__Hit(hwv, action, x, y, numberOfClicks) struct helloworldview *hwv; enum view_MouseAction action; long x; long y; long numberOfClicks; \{ if(hwv->HaveDownTransition) switch(action)\{ case view_RightUp: hwv->HaveDownTransition=FALSE; /* fall through */ case view_RightMovement: hwv->newX=x-hwv->distX; hwv->newY=y-hwv->distY; break; case view_LeftUp: hwv->HaveDownTransition=FALSE; hwv->newX=x; hwv->newY=y; break; case view_LeftMovement: /* do nothing */ break; default: /* re-synchronize mouse */ hwv->HaveDownTransition=FALSE; \} if(!hwv->HaveDownTransition) switch(action)\{ case view_RightDown: hwv->distX=x-hwv->x; hwv->distY=y-hwv->y; /* fall through */ case view_LeftDown: hwv->HaveDownTransition=TRUE; helloworldview_WantInputFocus(hwv,hwv); break; \} helloworldview_WantUpdate(hwv,hwv); return (struct view *)hwv; \} void helloworldview__ReceiveInputFocus(hwv) struct helloworldview *hwv; \{ hwv->haveInputFocus = TRUE; hwv->keystate->next = NULL; helloworldview_PostKeyState(hwv, hwv->keystate); helloworldview_PostMenus(hwv, hwv->menulist); \} void helloworldview__LoseInputFocus(hwv) struct helloworldview *hwv; \{ hwv->haveInputFocus = FALSE; \} static void Center(hwv, rock) struct helloworldview *hwv; long rock; \{ struct rectangle myVisualRect; helloworldview_GetVisualBounds(hwv,&myVisualRect); hwv->newX = rectangle_Left(&myVisualRect) + rectangle_Width(&myVisualRect) / 2; hwv->newY = rectangle_Top(&myVisualRect) + rectangle_Height(&myVisualRect) / 2; helloworldview_WantUpdate(hwv, hwv); \} static void Invert(hwv, rock) struct helloworldview *hwv; long rock; \{ hwv->newBlackOnWhite = ! hwv->newBlackOnWhite; helloworldview_WantUpdate(hwv, hwv); \} static struct bind_Description helloworldviewBindings[]=\{ \{"helloworld-center", "\\003",0, "Hello World,Center",0,0, Center, "Center the helloworld string."\}, \{"helloworld-invert", "\\011",0, "Hello World,Invert",0,0, Invert, "Invert the helloworld string."\}, NULL \}; boolean helloworldview__InitializeClass(classID) struct classheader *classID; \{ helloworldviewMenulist=menulist_New(); helloworldviewKeymap=keymap_New(); bind_BindList(helloworldviewBindings, helloworldviewKeymap,helloworldviewMenulist, &helloworldview_classinfo); return TRUE; \} \bold{helloa.ch} class helloworldapp[helloa] : application[app]\{ overrides: Start() returns boolean; \}; \bold{helloa.c} #include <class.h> #include "helloa.eh" #include "im.ih" #include "hellov.ih" boolean helloworldapp__Start(hwapp) struct helloworldapp *hwapp; \{ struct helloworldview *hwv; struct im *im; if(!super_Start(hwapp)) return FALSE; hwv=helloworldview_New(); if(hwv==NULL) return FALSE; im=im_Create(NULL); if(im==NULL)\{ helloworldview_Destroy(hwv); return FALSE; \} im_SetView(im,hwv); helloworldview_WantInputFocus(hwv,hwv); return TRUE; \} \bold{Makefile} SRCDIR=/usr/andrew/ INCLUDES= -I. -I$\{SRCDIR\}include/atk -I$\{SRCDIR\}include INCLUDESRC = $\{SRCDIR\}include/atk CC=cc DEBUG = -g TOOLS = $\{SRCDIR\}bin/ CFLAGS= $\{DEBUG\} $\{INCLUDES\} CLASSFLAGS=$\{INCLUDES\} MAKEDO = $\{TOOLS\}makedo $\{DEBUG\} -b $\{TOOLS\} -d $\{SRCDIR\}lib CLASS = $\{TOOLS\}class .SUFFIXES: .ih .eh .ch .do .ch.ih: $\{CLASS\} $\{CLASSFLAGS\} $*.ch .ch.eh: $\{CLASS\} $\{CLASSFLAGS\} $*.ch .o.do: $\{MAKEDO\} $< all: helloa.do hellov.do helloa.do: helloa.o helloa.eh hellov.do: hellov.o hellov.eh helloa.o: helloa.c helloa.o: $\{INCLUDESRC\}/app.ih helloa.o: $\{INCLUDESRC\}/graphic.ih helloa.o: $\{INCLUDESRC\}/im.ih helloa.o: $\{INCLUDESRC\}/observe.ih helloa.o: $\{INCLUDESRC\}/point.h helloa.o: $\{INCLUDESRC\}/rect.h helloa.o: $\{INCLUDESRC\}/view.ih helloa.o: $\{SRCDIR\}include/class.h helloa.o: hellov.ih helloa.o: helloa.eh helloa.eh helloa.ih: helloa.ch helloa.eh helloa.ih: $\{INCLUDESRC\}/app.ih hellov.o: hellov.c hellov.o: $\{INCLUDESRC\}/graphic.ih hellov.o: $\{INCLUDESRC\}/observe.ih hellov.o: $\{INCLUDESRC\}/point.h hellov.o: $\{INCLUDESRC\}/rect.h hellov.o: $\{INCLUDESRC\}/view.ih hellov.o: $\{SRCDIR\}include/class.h hellov.o: hellov.eh hellov.eh hellov.ih: hellov.ch hellov.eh hellov.ih: $\{INCLUDESRC\}/graphic.ih hellov.eh hellov.ih: $\{INCLUDESRC\}/observe.ih hellov.eh hellov.ih: $\{INCLUDESRC\}/point.h hellov.eh hellov.ih: $\{INCLUDESRC\}/rect.h hellov.eh hellov.ih: $\{INCLUDESRC\}/view.ih hellov.eh hellov.ih: $\{SRCDIR\}include/class.h } \begindata{bp,537558784} \enddata{bp,537558784} \view{bpv,537558784,916,0,0} Copyright 1992 Carnegie Mellon University and IBM. All rights reserved. \smaller{\smaller{$Disclaimer: Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice, this permission notice, and the following disclaimer appear in supporting documentation, and that the names of IBM, Carnegie Mellon University, and other copyright holders, not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. $ }}\enddata{text,538373940}