/** pubscr.c * * These are the screen management routines * **/ #include #include #include #include "pubscr.h" /* * The following two strings must exist. */ char SSHname[] = "screenshare.library"; char SSHid[] = "screenshare 1.2 (Sep 89)\r\n"; UWORD SSHrevision = 2; /* * ScreenList is the only static variable */ static struct List *ScreenList = NULL; static struct ScreenNode *ScrListAlloc(), *ScrListFree(), *ScrListFind(); static struct Library *ScrSharBase; /** * * NAME * * GetPubScrList * ============= * * SYNOPSIS * * struct List *ScreenList = GetPubScrList() * D0 * * FUNCTION * * This function returns a pointer to the Exec-style * list of shared screen nodes. * * INPUTS * * None * * RESULT * * Pointer to the first node. * * ADDITIONAL CONSIDERATIONS * * This routine is not normally used in applications. * The ScreenNode structure is described in pubscr.h. * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ struct List *GetPubScrList() { return(ScreenList); } /** * * NAME * * PublicScreen * ============ * * SYNOPSIS * * int result = PublicScreen(Name, ScreenAddress) * D0 A0 A1 * * FUNCTION * * This function adds a named screen to the public screen list. * * INPUTS * * Name Name to be assigned to the public screen. * ScreenAddress Pointer to the Screen structure. * * RESULT * * 0 on failure, 1 on success. * Note: the return code is a 16 bit int (a short). * * ADDITIONAL CONSIDERATIONS * * This routine should be called by an application ("host") if it wants * to make its custom screen accessible to the outside world ("symbionts"). * When an application calls this function, it promises in particular to * NOT CLOSE this screen until it has ascertained that the screen is no * longer occupied by symbionts through calling PubScrLocked(), and until * it has reverted the status of the screen to private by calling * PrivateScreen(). * * If a screen with the same name already exists, the screen pointer is * compared with that of the existing public screen. The function only * returns successfully in that case if the two pointers are identical. * In such a case, the symbiont open count is not affected. * Otherwise, the function returns 0 and performs no action. * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ int PublicScreen(name, address) char *name; struct Screen *address; { struct ScreenNode *olditem = NULL; int res; /* * Can't interrupt this */ Forbid(); res = 0; /* * First try to find this one. If found, and the addess is the same, return okay */ if (olditem = ScrListFind(name)) { if (olditem->sn_Address == address) res = 1; } /* * Else allocate a new node and open ourselves so we don't go away */ else { if (ScrListAlloc(name, address)) { ScrSharBase = OpenLibrary("screenshar.library", 0L); res = 1; } } Permit(); return(res); } /** * * NAME * * PrivateScreen * ============= * * SYNOPSIS * * int result = PrivateScreen(Name) * D0 A0 * * FUNCTION * * This function removes a named screen from the public screen list. * * INPUTS * * Name Name of the public screen * * RESULT * * 0 on failure, 1 on success. * Note: the return code is a 16 bit int (a short). * * ADDITIONAL CONSIDERATIONS * * This routine should be called by an application that has made itself * the "host" to a named public screen through a call to PublicScreen(). * Before calling PrivateScreen(), the application should verify that no * "symbionts" are currently present on the screen through a call to * PubScrLocked(). * * If the Name is not found in the public screen list, the function * performs no operation and returns 0. * If the Name is found, the current symbiont open count is checked. * If the open count is non-zero, the function performs no operation * and returns 0. * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ int PrivateScreen(name) char *name; { struct ScreenNode *olditem = NULL; int res; /* * Can't interrupt this */ Forbid(); res = 0; /* * Try to find this name, if found, free node and close ourselves. */ if (olditem = ScrListFind(name)) { if (olditem->sn_OpenCount == 0) { ScrListFree(olditem); if (ScrSharBase) CloseLibrary(ScrSharBase); res = 1; } } Permit(); return(res); } /** * * NAME * * PubScrLocked * ============ * * SYNOPSIS * * int result = PubScrLocked(Name) * D0 A0 * * FUNCTION * * This function returns the number of symbionts still open on this * named screen. * * INPUTS * * Name Name of the public screen * * RESULT * * Number of symbionts with windows still open on this screen. * Note: the return code is a 16 bit int (a short). * * ADDITIONAL CONSIDERATIONS * * This function should be used by an application that has made itself * the "host" to a named public screen through a call to PublicScreen() * in order to determine whether it is safe to call PrivateScreen(). * * If a screen with the given Name is not found, the function returns 0. * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ int PubScrLocked(name) char *name; { struct ScreenNode *olditem = NULL; int res; /* * Can't interrupt this */ Forbid(); res = 0; if (olditem = ScrListFind(name)) res = olditem->sn_OpenCount; Permit(); return(res); } /** * * NAME * * LockPubScreen * ============= * * SYNOPSIS * * struct Screen *ScreenPtr = LockPubScreen(Name) * D0 A0 * * FUNCTION * * This function returns the address of a named public screen, and * increments the screenshare.library's symbiont counter for this * screen. * * INPUTS * * Name Name of the public screen * * RESULT * * Pointer to the public screen, if found. NULL otherwise. * * ADDITIONAL CONSIDERATIONS * * This function should be used by the symbiont in order to find * the address of the Screen structure of the application that has declared * its screen public. The symbiont should use UnlockPubScreen() whenever * it has closed its window(s) on that screen, and not open any windows * on that screen until after a call to LockPubScreen(). * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ struct Screen *LockPubScreen(name) char *name; { struct Screen *res; struct ScreenNode *olditem; /* * Can't interrupt this */ Forbid(); res = 0L; /* * Find the screen. If found, increment its counter. Return the address. */ if (olditem = ScrListFind(name)) { olditem->sn_OpenCount++; res = olditem->sn_Address; } Permit(); return(res); } /** * * NAME * * UnlockPubScreen * =============== * * SYNOPSIS * * struct Screen *ScreenPtr = UnlockPubScreen(Name) * D0 A0 * * FUNCTION * * This function decrements the symbiont counter of the named screen. * * INPUTS * * Name Name of the public screen * * RESULT * * Guaranteed NULL. * * ADDITIONAL CONSIDERATIONS * * This function should be used by the symbiont in order to decrement the * the symbiont counter of the named screen to signal it has closed its * window(s) on that screen. The symbiont should use LockPubScreen() * before opening any windows on that screen, and not call UnlockPubScreen() * until it has closed its window(s) on that screen. * * BUGS * * None known. * * AUTHOR * * W.G.J. Langeveld (WGL) * **/ struct Screen *UnlockPubScreen(name) char *name; { struct Screen *res; struct ScreenNode *olditem; /* * Can't interrupt this */ Forbid(); res = 0L; /* * First find the screen. If found, decrement its counter. */ if (olditem = ScrListFind(name)) { if (olditem->sn_OpenCount != 0) olditem->sn_OpenCount--; res = 0L; } Permit(); return(res); } /** * * The following are local routines, not accessible from the outside world * ======================================================================= * * Routine to add another node to the Screen list. * **/ #define SNSIZE ((long) sizeof(struct ScreenNode)) #define SLSIZE ((long) sizeof(struct List)) static struct ScreenNode *ScrListAlloc(s, scr) char *s; struct Screen *scr; { struct ScreenNode *sn; /* * If no list exists, create one */ if (ScreenList == NULL) { ScreenList = (struct List *) AllocMem(SLSIZE, MEMF_PUBLIC | MEMF_CLEAR); if (!ScreenList) return(NULL); NewList(ScreenList); } /* * Create a node */ sn = (struct ScreenNode *) AllocMem(SNSIZE, MEMF_PUBLIC | MEMF_CLEAR); if (sn) { /* * Allocate room for the name */ sn->sn_Node.ln_Name = (char *) AllocMem((long) (strlen(s) + 1), MEMF_PUBLIC | MEMF_CLEAR); if (sn->sn_Node.ln_Name) { /* * ...and copy the name */ strcpy(sn->sn_Node.ln_Name, s); /* * Copy the address and zero the open count. */ sn->sn_Address = scr; sn->sn_OpenCount = 0; /* * Add this one to the list */ AddTail(ScreenList, sn); } } return(sn); } /** * * Free a ScreenNode node * **/ static struct ScreenNode *ScrListFree(item) struct ScreenNode *item; { if (item == 0L) return(0L); if (ScreenList == 0L) return(0L); /* * Isolate this item from the list. */ Remove(item); /* * Free the string */ if (item->sn_Node.ln_Name) FreeMem(item->sn_Node.ln_Name, (long) (strlen(item->sn_Node.ln_Name) + 1)); /* * Free the item */ FreeMem(item, SNSIZE); /* * If this is the last item, free the list. */ if (ScreenList->lh_TailPred == ScreenList) { FreeMem(ScreenList, SLSIZE); ScreenList = NULL; } return(0L); } /** * * Find a screen with a certain name * **/ static struct ScreenNode *ScrListFind(name) char *name; { /* * If the name is null or there is no header, return */ if (name == 0L) return(0L); if (ScreenList == 0L) return(0L); /* * Find it */ return((struct ScreenNode *) FindName(ScreenList, name)); }