// Registers one plugin. "pPluginFilespec" is a string containing the file // name of a DLL. // This function can be called more than once so a plugin which has copied // into the plugins subdir AFTER the Nav has started can be registered // and loaded. // The DLL is a plugin candidate, and is qualified during // this function, by checking the DLL VERSIONINFO data structure for a // MIME type string. If this string is found successfully, the handle // of the management block is used to register the plugin for its MIME type. // The extents which are to be associated with this MIME type are also grokked // from the VERSIONINFO data structure, once the candidate is accepted. // This function also takes the opportunity to overrided any helper app, by // setting a helper app data structure member to allow the plugin to handle // the MIME type instead of the helper, (pApp->how_handle = HANDLE_VIA_PLUGIN). // Returns an error if "pPluginFilespec" was not registered. NPError fe_RegisterPlugin(char* pPluginFilespec) { CString strName, strDescription; // initialize a new plugin list mgt block NPPMgtBlk* pNPMgtBlk = new NPPMgtBlk; if(pNPMgtBlk == NULL) // fatal, can't continue return NPERR_OUT_OF_MEMORY_ERROR; pNPMgtBlk->pPluginFuncs = NULL; pNPMgtBlk->pLibrary = NULL; pNPMgtBlk->uRefCount = 0; pNPMgtBlk->next = NULL; // determine the MIME type and version of this plugin if(wfe_GetPluginProperties(pPluginFilespec, pNPMgtBlk, strName, strDescription) != NPERR_NO_ERROR) { delete pNPMgtBlk; return NPERR_GENERIC_ERROR; } // if a plugin is already registered for this MIME type, return. this // allows downloading and registering new plugins without exiting the nav for(NPPMgtBlk* pListBlk = g_pRegisteredPluginList; pListBlk != NULL; pListBlk = pListBlk->next) { BOOL bSameFile = (strcmp(pListBlk->pPluginFilename, pPluginFilespec) == 0); BOOL bSameMIMEtype = (strstr(pNPMgtBlk->szMIMEType, pListBlk->szMIMEType) != NULL); if(bSameFile && bSameMIMEtype) { // the plugin DLL's filename and the MIME type it's registering for // are the same, don't reregister delete pNPMgtBlk; return NPERR_GENERIC_ERROR; } } pNPMgtBlk->pPluginFilename = XP_STRDUP(pPluginFilespec); if(pNPMgtBlk->pPluginFilename == NULL) // fatal, can't continue { delete pNPMgtBlk; return NPERR_OUT_OF_MEMORY_ERROR; } // Register the plugin file with the XP plugin code NPL_RegisterPluginFile(strName, pNPMgtBlk->pPluginFilename, strDescription, pNPMgtBlk); // Iterate through the filename extensions. These are a list which are // delimited via the '|' character. The list of MIME Types,File Extents, // and Open Names must all coordinate char *pStartMIME, *pEndMIME, *pStartExt, *pEndExt, *pStartName, *pEndName; pStartMIME = pNPMgtBlk->szMIMEType; pStartExt = pNPMgtBlk->szFileExtents; pStartName = pNPMgtBlk->szFileOpenName; pEndMIME = strchr(pStartMIME ,'|'); while (pEndMIME) { pEndExt = strchr(pStartExt,'|'); pEndName = strchr(pStartName,'|'); if (pEndMIME) *pEndMIME = 0; else return NPERR_GENERIC_ERROR; if (pEndExt) *pEndExt = 0; else return NPERR_GENERIC_ERROR; if (pEndName) *pEndName = 0; else return NPERR_GENERIC_ERROR; // Register the MIME type with the XP plugin code. We need to pass in // a description. If there's a file open template specified, then use the // description from there. Otherwise use the MIME type LPSTR lpszDescription = NULL; if (pStartName) lpszDescription = ExtractDescription(pStartName); NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); if (lpszDescription) XP_FREE(lpszDescription); CHelperApp *pApp; if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { // We've a match. // Make sure the app is marked to handle the load // via a plugin pApp->how_handle = HANDLE_VIA_PLUGIN; } if ((pEndMIME+1) && (pEndExt+1) && (pEndName+1)) { pStartMIME = pEndMIME+1; pStartExt = pEndExt+1; pStartName = pEndName+1; } pEndMIME = strchr(pStartMIME ,'|'); } // Register the MIME type with the XP plugin code. We need to pass in // a description. If there's a file open template specified, then use the // description from there. Otherwise use the MIME type LPSTR lpszDescription = NULL; if (pStartName) lpszDescription = ExtractDescription(pStartName); NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); if (lpszDescription) XP_FREE(lpszDescription); CHelperApp *pApp; if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { // We've a match. // Make sure the app is marked to handle the load // via a plugin pApp->how_handle = HANDLE_VIA_PLUGIN; } // insert the plugin mgt blk at the head of the list of registered plugins. // this means they are listed in the reverse order from which they were // created, which doesn't matter. pNPMgtBlk->next = g_pRegisteredPluginList; g_pRegisteredPluginList = pNPMgtBlk; return NPERR_NO_ERROR; }
/** Parses a buffer and creates appropriate instances. It works on a very low level. Ugly, but fast :-) */ void CStyleFile::ParseBuffer(const TCHAR *buf) { for (int i = 0; i < TOKEN_COUNT; i++) { const TCHAR *t, *token; TCHAR nameBuf[255]; std::size_t lTok = _tcslen(TOKENS[i]); token = _tcsstr(buf, TOKENS[i]); while (token != NULL) { t = token; token += lTok; bool hasStar = false; bool isPrivate = false; int nOptions = 0; const TCHAR *first = _tcsstr(token, _T("\\")); const TCHAR *second = _tcsstr(token, _T("{")); const TCHAR *close = _tcsstr(token, _T("}")); const TCHAR *openBr = _tcsstr(token, _T("[")); const TCHAR *closeBr = _tcsstr(token, _T("]")); const TCHAR *p; if (first == NULL && second != NULL) { p = second; } else if (first != NULL && second == NULL) { p = first; } else if (first != NULL && second != NULL) { p = (first < second ? first : second); } else { token = _tcsstr(token + 1, TOKENS[i]); continue; } if (*token == _T('*')) { hasStar = true; } if (i == LATEX_COMMAND) /* Commands have a leading _T('\') */ { ++token; } /* Get number of options */ nOptions = ExtractOptionCount(close, openBr, closeBr); while (!(_istalpha(*p) || _istdigit(*p) || *p == _T('@'))) ++p; /* skip comments, white spaces, etc... */ const TCHAR *pStart = p; while (_istalpha(*p) || _istdigit(*p) || *p == _T('@')) { if (*p == _T('@')) { isPrivate = true; /* mark as internal command */ } ++p; } int l = p - pStart; if (l < 255 && l > 1 && !isPrivate) /* Command valid? */ { _tcsncpy((TCHAR*) & nameBuf, pStart, l); nameBuf[l] = 0; /* Create appropriate instance */ std::tr1::shared_ptr<CAbstractLaTeXCommand> lc(CreateItem(i, nameBuf, hasStar, nOptions)); if (lc != NULL) /* Instance valid -> Notify container and add to list */ { switch (i) { case LATEX_COMMAND: case LATEX_ENVIRONMENT: case LATEX_DEF: case LATEX_LET: case LATEX_TXT_SYMBOL: case LATEX_MATH_SYMBOL: case LATEX_TXT_COMMAND: { SharedLaTeXCommandPtr cmd = std::tr1::dynamic_pointer_cast<CLaTeXCommand>(lc); /* Some commands may be duplicate due to conditional definitions in the style file. */ if (!AddCommand(cmd)) { } } break; case LATEX_OPTION: if (!CStyleFileContainer::ContainsString(&m_Options, lc->GetName())) { m_Options.Add(lc->GetName()); } break; case LATEX_REQPACKAGE: m_ReqPackages.Add(lc->GetName()); break; case LATEX_CLS_DESC: case LATEX_STY_DESC: ExtractDescription(close, openBr, closeBr, m_Desc); TRACE(_T("Desc: %s: <%s>\n"), m_Name, m_Desc); break; } } } else /* For debug purposes only */ { if (l > 1 && !isPrivate) { TRACE(_T("!! Buffer to small: Needs %d bytes\n"), l); } else if (!isPrivate) { _tcsncpy(nameBuf, t, 50); _tcsncpy(((TCHAR*)(&nameBuf) + 50), _T("..."), 3); nameBuf[53] = 0; TRACE(_T("** Invalid name: %s\n"), nameBuf); _tcsncpy(nameBuf, pStart, 10); _tcsncpy(((TCHAR*)(&nameBuf) + 10), _T("..."), 3); nameBuf[13] = 0; TRACE(_T("** pStart = %s\n"), nameBuf); _tcsncpy(nameBuf, p, 10); _tcsncpy(((TCHAR*)(&nameBuf) + 10), _T("..."), 3); nameBuf[13] = 0; TRACE(_T("** p = %s\n"), nameBuf); } } /* Get next token: */ token = _tcsstr(token + 1, TOKENS[i]); } } }