/***************************************************************************** * * * FMT.C * * * * Copyright (C) Microsoft Corporation 1990. * * All Rights reserved. * * * ****************************************************************************** * * * Module Intent * * FM caching module. Used in history and back lists. * * * * Currently, I don't keep a ref count of the FMs in the cache. This * * means I can't shrink the cache until all users finish using it. * * * *****************************************************************************/ #include "help.h" #pragma hdrstop _subsystem( FMT ); /***************************************************************************** * * * Defines * * * *****************************************************************************/ /***************************************************************************** * * * Typedefs * * * *****************************************************************************/ /***************************************************************************** * * * Static Variables * * * *****************************************************************************/ /****************************************************************************\ * * The following static variables define the cache. There is only one * cache because the whole idea is to share it. * \****************************************************************************/ static INT16 cfm = 0; // count of FDs static GH hrgfm = NULL; // handle to array of FDs static FM * rgfm = NULL; // locked hrgfd (sometimes valid) static INT16 cRefFmt = 0; // FDT ref count /***************************************************************************** * * * Prototypes * * * *****************************************************************************/ /***************************************************************************\ * - Function: RcInitFmt() - * Purpose: Enlist as a user of the FMT. * * ASSUMES * * globals IN: cRefFmt * * PROMISES * * returns: rcSuccess always * * globals OUT: ref count cRefFmt is incremented * * Note: If you RcInitFmt(), you must RcFiniFmt() when you're done. * * +++ * * Method: Increment the ref count. * \***************************************************************************/ void STDCALL RcInitFmt() { ++cRefFmt; } /***************************************************************************\ * - Function: RcFiniFmt() - * Purpose: Tell the FMT you're done using it. When the last user * finishes, memory is deallocated. * * ASSUMES * * PROMISES * * returns: rcSuccess rcFailure * \***************************************************************************/ void STDCALL RcFiniFmt(void) { INT16 ifm; FM * qfmT; ASSERT( 0 < cRefFmt ); if (0 == --cRefFmt) { if (!hrgfm) { if (rgfm == NULL) rgfm = PtrFromGh(hrgfm); for (ifm = 0, qfmT = rgfm; ifm < cfm; ++ifm, ++qfmT) DisposeFm(*qfmT); rgfm = NULL; FreeGh(hrgfm); hrgfm = NULL; } cfm = 0; } } /***************************************************************************\ * - Function: UnlockFmt() - * Purpose: Ensure that the FMT is unlocked. * * ASSUMES * * globals IN: * * PROMISES * * globals OUT: * * Notes: You should do this after performing the mapping functions * before yielding. * * +++ * * Method: * * Notes: * \***************************************************************************/ _public void STDCALL UnlockFmt() { if (rgfm) { ASSERT(NULL != hrgfm); rgfm = NULL; } } /***************************************************************************\ - - Function: IfmFromFm( fm ) - * Purpose: Map an ifm into an fm * * ASSUMES * * args IN: fm - map it to an ifm * * globals IN: rgfm * hrgfm * * PROMISES * * returns: success - valid ifm * failure - ifmNil * * globals OUT: hrgfm - array of saved FMs can grow * rgfm - guaranteed to be hrgfm, locked * cfm - can be incremented * * state OUT: FMT is locked * \***************************************************************************/ _public INT16 STDCALL IfmFromFm( fm ) FM fm; { INT16 ifm; FM fmT; FM * qfmT; GH ghT; if (!rgfm) { if (!hrgfm) { if (!(hrgfm = GhAlloc(GPTR, sizeof(FM)))) return ifmNil; cfm = 1; rgfm = PtrFromGh( hrgfm ); ASSERT(NULL != rgfm); ifm = 0; fmT = FmCopyFm(fm); rgfm[ ifm ] = fmT; return ifm; } rgfm = PtrFromGh(hrgfm); ASSERT(NULL != rgfm); } for (ifm = 0, qfmT = rgfm; ifm < cfm; ++ifm, ++qfmT) { if (FSameFmFm(fm, *qfmT)) { return ifm; } } ghT = GhResize(hrgfm, 0, sizeof(FM) * ++cfm); if ( NULL == ghT ) { --cfm; return ifmNil; } hrgfm = ghT; rgfm = PtrFromGh( hrgfm ); fmT = FmCopyFm(fm); rgfm[ ifm ] = fmT; return ifm; } /***************************************************************************\ - - Function: FmFromIfm( ifm ) - * Purpose: Map an ifm into an fm. * * ASSUMES * * args IN: ifm - in range: 0 <= ifm < cfm * * globals IN: * * PROMISES * * returns: success: fm - a copy of the fm in the table (so it can be * disposed without causing problems. * failure: NULL * * state OUT: FMT is locked * \***************************************************************************/ FM STDCALL FmFromIfm(INT16 ifm) { if ( 0 > ifm || ifm >= cfm ) return NULL; if (NULL == rgfm) { ASSERT(NULL != hrgfm); rgfm = PtrFromGh(hrgfm); ASSERT(NULL != rgfm); } return rgfm[ ifm ]; } /* EOF */