/* sequiny.c * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information (NCBI) * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government do not place any restriction on its use or reproduction. * We would, however, appreciate having the NCBI and the author cited in * any work or product based on this material * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * =========================================================================== * * File Name: sequiny.c * * Author: Jim Ostell * * Version Creation Date: 5/24/96 * * $Revision: 6.2 $ * * File Description: * This is a companion file to sequinx.c. In order to register additional proceedures * of your own design, to replace or supplement those intrinsic to sequin, * we have provided sequinx.c where you can register your functions with the * object manager. For demonstration purposes, we have included a REGISTER call * (commented out) to functions in this file. * * This file contains the demonstration functions themselves, as well as extensive * comments describing what they do. They are intended to serve as a model for what * you might do in a file of your own design. * * Basically, to register a proceedure with the object manager, you call a function * which specifies a name for the function, a string to show in a menu, an input * data type (OBJ_ in objmgr.h), possibly a subtype, and an output type, and possibly * a subtype, the type of function (filter, editor, etc), and a pointer to the function * to be called. The called function always * returns an Int2 (whose values are defined in objmgr.h as OM_MSG_RET_...) and takes * a single Pointer as an argument. This pointer always must be cast to an OMProcControlPtr * (objmgr.h) which contains the input arguments. It is only declared as a Pointer because * of C typedef order limitations. We will call this function the "work" function. * * The work function does the real job. It looks at the contents of the data pointer, * executes the appropriate actions and returns a completion or error code. Normally it * will return one of: * OM_MSG_RET_ERROR - an error occurred, presumably reported with ErrPostEx() * OM_MSG_RET_OK - everything was ok, but this function did not do anything. * OM_MSG_RET_DONE - everything was ok, and this function did the processing requested. * * When the object manager looks for a function to satisfy a request it enters a loop * which goes through appropriate functions until the action is done. First, it goes * through all registered functions of the requested class (editor, filter,..) in priority * order. First it looks for a match of type, and subtype. Failing that, it looks for a * match to type, with subtype = 0 (any). For each match, it calls the function with the * data. If the functions returns OM_MSG_RET_ERROR, or OM_MSG_RET_OK, the object manager * tries the next function. When a function returns OM_MSG_RET_DONE or there are no more * matching functions, the object manager returns. This means your functions can be called * before or after the default functions (priority), or by specifying a subtype not * supported by a default function. You can have your function called first, check the * data to decide if you want to handle it, return OM_MSG_RET_DONE if you do, or * OM_MSG_RET_OK if you want the object manager to find some other function to handle it. * * If you wish your function to receive messages from the object manager you must also * supply a message loop function and register it with the object manager when your * function is first called. You must remember to unregister it when your function exits. * If your function performs some quick computation and returns, you probably don't need * a message loop function. If it will persist awhile (like an editor or viewer) you * probably will. This is for cases such as 1) your function is a viewer showing Bioseq X * 2) some other function is an editor on Bioseq X. When Bioseq X is updated in the editor * it will send an update message to the object manager. Your function will want to receive * this message so it can update its display from the underlying (now edited) data * appropriately. Your message loop should return OM_MSG_RET_OK (not _DONE) so the object * manager will continue to relay the message to all functions that want to see it. * * * * Modifications: * -------------------------------------------------------------------------- * Date Name Description of modification * ------- ---------- ----------------------------------------------------- * * * ========================================================================== */ #include #include "sequin.h" #include "sequiny.h" /** prototype for message loop function **/ static Int2 LIBCALLBACK MyBioseqEditMsgFunc (OMMsgStructPtr ommsp); Int2 LIBCALLBACK MyBioseqEditFunc (Pointer data) { BioseqPtr bsp; OMProcControlPtr ompcp; Char buf[41]; OMUserDataPtr omudp; /* user data structure used for message loop */ Uint2 userkey; /* used to track omudp uniquely */ ompcp = (OMProcControlPtr) data; /* always do this cast */ /* check that all is cool */ if (ompcp == NULL) return OM_MSG_RET_ERROR; if (ompcp->input_itemtype != OBJ_BIOSEQ) return OM_MSG_RET_ERROR; if (ompcp->input_data == NULL) /* no BioseqPtr yet */ { if (! GatherDataForProc (ompcp, FALSE)) /* find it -- gather.h */ { ErrPostEx(SEV_ERROR,0,0,"MyBioseqEditFunc: couldn't gather BioseqPtr"); return OM_MSG_RET_ERROR; } } bsp = (BioseqPtr)(ompcp->input_data); /* get the pointer */ BioseqLabel(bsp, buf, 40, OM_LABEL_BOTH); /* make a text string to show */ Message(MSG_OK, "MyBioseqEditFunc called with [%s]", buf); /* show it */ /* assuming we need a message loop ************************************************/ userkey = OMGetNextUserKey (); /* get a unique key for this proc instance */ /* only necessary if the same proc could be invoked multiple times at once */ /* attach data to the entity for this procedure */ omudp = ObjMgrAddUserData(ompcp->input_entityID, ompcp->proc->procid, OMPROC_EDIT, userkey); omudp->userdata.ptrvalue = (Pointer)bsp; /* this could point to any data */ omudp->messagefunc = MyBioseqEditMsgFunc; /* add my message loop */ /* now we can send a message to ourselves */ /* just to prove it works. The message could just */ /* as well be from another proceedure though */ ObjMgrSendMsg (OM_MSG_SELECT, ompcp->input_entityID, 0, 0); /*** end of message loop setup ***************************************************/ /** here you would do whatever work you wanted on this entry **/ /** in this case we will just arbitrarily change the length to 10 */ bsp->length = 10; /* make the change */ /* inform any listening proceedures */ ObjMgrSendMsg (OM_MSG_UPDATE, ompcp->input_entityID, ompcp->input_itemID, ompcp->input_itemtype); /*** if we set up the message loop, we need to clean up before we leave *****/ ObjMgrFreeUserData(ompcp->input_entityID, ompcp->proc->procid, OMPROC_EDIT, userkey); /** Now we are done. Give a Done return code *******************************/ return OM_MSG_RET_DONE; } /****************************************************************************************** * * Here's the sample message loop function. It really does nothing but say hello * *******************************************************************************************/ static Int2 LIBCALLBACK MyBioseqEditMsgFunc (OMMsgStructPtr ommsp) { OMUserDataPtr omudp; BioseqPtr bsp; Char buf[41]; omudp = (OMUserDataPtr)(ommsp->omuserdata); bsp = (BioseqPtr)(omudp->userdata.ptrvalue); BioseqLabel(bsp, buf, 40, OM_LABEL_BOTH); /* make a text string to show */ switch (ommsp->message) { case OM_MSG_DEL: break; case OM_MSG_CREATE: break; case OM_MSG_UPDATE: Message(MSG_OK, "Got an update message on [%s]", buf); break; case OM_MSG_SELECT: /* add highlight code */ Message(MSG_OK, "Got a select message on [%s]", buf); break; case OM_MSG_DESELECT: /* add deselect code */ break; case OM_MSG_CACHED: break; case OM_MSG_UNCACHED: break; case OM_MSG_TO_CLIPBOARD: /* this is just because no clipboard now */ break; default: break; } return OM_MSG_RET_OK; }