/* tidylib.c -- internal library definitions (c) 1998-2008 (W3C) MIT, ERCIM, Keio University See tidy.h for the copyright notice. CVS Info : $Author: arnaud02 $ $Date: 2008/06/18 20:18:54 $ $Revision: 1.75 $ Defines HTML Tidy API implemented by tidy library. Very rough initial cut for discussion purposes. Public interface is const-correct and doesn't explicitly depend on any globals. Thus, thread-safety may be introduced w/out changing the interface. Looking ahead to a C++ wrapper, C functions always pass this-equivalent as 1st arg. Created 2001-05-20 by Charles Reitzel */ #include #include "tidy-int.h" #include "parser.h" #include "clean.h" #include "config.h" #include "message.h" #include "pprint.h" #include "entities.h" #include "tmbstr.h" #include "utf8.h" #include "mappedio.h" #ifdef TIDY_WIN32_MLANG_SUPPORT #include "win32tc.h" #endif /* Create/Destroy a Tidy "document" object */ static TidyDocImpl* tidyDocCreate( TidyAllocator *allocator ); static void tidyDocRelease( TidyDocImpl* impl ); static int tidyDocStatus( TidyDocImpl* impl ); /* Parse Markup */ static int tidyDocParseFile( TidyDocImpl* impl, ctmbstr htmlfil ); static int tidyDocParseStdin( TidyDocImpl* impl ); static int tidyDocParseString( TidyDocImpl* impl, ctmbstr content ); static int tidyDocParseBuffer( TidyDocImpl* impl, TidyBuffer* inbuf ); static int tidyDocParseSource( TidyDocImpl* impl, TidyInputSource* docIn ); /* Execute post-parse diagnostics and cleanup. ** Note, the order is important. You will get different ** results from the diagnostics depending on if they are run ** pre-or-post repair. */ static int tidyDocRunDiagnostics( TidyDocImpl* doc ); static int tidyDocCleanAndRepair( TidyDocImpl* doc ); /* Save cleaned up file to file/buffer/sink */ static int tidyDocSaveFile( TidyDocImpl* impl, ctmbstr htmlfil ); static int tidyDocSaveStdout( TidyDocImpl* impl ); static int tidyDocSaveString( TidyDocImpl* impl, tmbstr buffer, uint* buflen ); static int tidyDocSaveBuffer( TidyDocImpl* impl, TidyBuffer* outbuf ); static int tidyDocSaveSink( TidyDocImpl* impl, TidyOutputSink* docOut ); static int tidyDocSaveStream( TidyDocImpl* impl, StreamOut* out ); #ifdef NEVER TidyDocImpl* tidyDocToImpl( TidyDoc tdoc ) { return (TidyDocImpl*) tdoc; } TidyDoc tidyImplToDoc( TidyDocImpl* impl ) { return (TidyDoc) impl; } Node* tidyNodeToImpl( TidyNode tnod ) { return (Node*) tnod; } TidyNode tidyImplToNode( Node* node ) { return (TidyNode) node; } AttVal* tidyAttrToImpl( TidyAttr tattr ) { return (AttVal*) tattr; } TidyAttr tidyImplToAttr( AttVal* attval ) { return (TidyAttr) attval; } const TidyOptionImpl* tidyOptionToImpl( TidyOption topt ) { return (const TidyOptionImpl*) topt; } TidyOption tidyImplToOption( const TidyOptionImpl* option ) { return (TidyOption) option; } #endif /* Tidy public interface ** ** Most functions return an integer: ** ** 0 -> SUCCESS ** >0 -> WARNING ** <0 -> ERROR ** */ TidyDoc TIDY_CALL tidyCreate(void) { TidyDocImpl* impl = tidyDocCreate( &TY_(g_default_allocator) ); return tidyImplToDoc( impl ); } TidyDoc TIDY_CALL tidyCreateWithAllocator( TidyAllocator *allocator ) { TidyDocImpl* impl = tidyDocCreate( allocator ); return tidyImplToDoc( impl ); } void TIDY_CALL tidyRelease( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); tidyDocRelease( impl ); } TidyDocImpl* tidyDocCreate( TidyAllocator *allocator ) { TidyDocImpl* doc = (TidyDocImpl*)TidyAlloc( allocator, sizeof(TidyDocImpl) ); TidyClearMemory( doc, sizeof(*doc) ); doc->allocator = allocator; TY_(InitMap)(); TY_(InitTags)( doc ); TY_(InitAttrs)( doc ); TY_(InitConfig)( doc ); TY_(InitPrintBuf)( doc ); /* By default, wire tidy messages to standard error. ** Document input will be set by parsing routines. ** Document output will be set by pretty print routines. ** Config input will be set by config parsing routines. ** But we need to start off with a way to report errors. */ doc->errout = TY_(StdErrOutput)(); return doc; } void tidyDocRelease( TidyDocImpl* doc ) { /* doc in/out opened and closed by parse/print routines */ if ( doc ) { assert( doc->docIn == NULL ); assert( doc->docOut == NULL ); TY_(ReleaseStreamOut)( doc, doc->errout ); doc->errout = NULL; TY_(FreePrintBuf)( doc ); TY_(FreeLexer)( doc ); TY_(FreeNode)(doc, &doc->root); TidyClearMemory(&doc->root, sizeof(Node)); if (doc->givenDoctype) TidyDocFree(doc, doc->givenDoctype); TY_(FreeConfig)( doc ); TY_(FreeAttrTable)( doc ); TY_(FreeTags)( doc ); TidyDocFree( doc, doc ); } } /* Let application store a chunk of data w/ each Tidy tdocance. ** Useful for callbacks. */ void TIDY_CALL tidySetAppData( TidyDoc tdoc, void* appData ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) impl->appData = appData; } void* TIDY_CALL tidyGetAppData( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return impl->appData; return NULL; } ctmbstr TIDY_CALL tidyReleaseDate(void) { return TY_(ReleaseDate)(); } /* Get/set configuration options */ Bool TIDY_CALL tidySetOptionCallback( TidyDoc tdoc, TidyOptCallback pOptCallback ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { impl->pOptCallback = pOptCallback; return yes; } return no; } int TIDY_CALL tidyLoadConfig( TidyDoc tdoc, ctmbstr cfgfil ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ParseConfigFile)( impl, cfgfil ); return -EINVAL; } int TIDY_CALL tidyLoadConfigEnc( TidyDoc tdoc, ctmbstr cfgfil, ctmbstr charenc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ParseConfigFileEnc)( impl, cfgfil, charenc ); return -EINVAL; } int TIDY_CALL tidySetCharEncoding( TidyDoc tdoc, ctmbstr encnam ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { int enc = TY_(CharEncodingId)( impl, encnam ); if ( enc >= 0 && TY_(AdjustCharEncoding)(impl, enc) ) return 0; TY_(ReportBadArgument)( impl, "char-encoding" ); } return -EINVAL; } int TIDY_CALL tidySetInCharEncoding( TidyDoc tdoc, ctmbstr encnam ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { int enc = TY_(CharEncodingId)( impl, encnam ); if ( enc >= 0 && TY_(SetOptionInt)( impl, TidyInCharEncoding, enc ) ) return 0; TY_(ReportBadArgument)( impl, "in-char-encoding" ); } return -EINVAL; } int TIDY_CALL tidySetOutCharEncoding( TidyDoc tdoc, ctmbstr encnam ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { int enc = TY_(CharEncodingId)( impl, encnam ); if ( enc >= 0 && TY_(SetOptionInt)( impl, TidyOutCharEncoding, enc ) ) return 0; TY_(ReportBadArgument)( impl, "out-char-encoding" ); } return -EINVAL; } TidyOptionId TIDY_CALL tidyOptGetIdForName( ctmbstr optnam ) { const TidyOptionImpl* option = TY_(lookupOption)( optnam ); if ( option ) return option->id; return N_TIDY_OPTIONS; /* Error */ } TidyIterator TIDY_CALL tidyGetOptionList( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(getOptionList)( impl ); return (TidyIterator) -1; } TidyOption TIDY_CALL tidyGetNextOption( TidyDoc tdoc, TidyIterator* pos ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); const TidyOptionImpl* option = NULL; if ( impl ) option = TY_(getNextOption)( impl, pos ); else if ( pos ) *pos = 0; return tidyImplToOption( option ); } TidyOption TIDY_CALL tidyGetOption( TidyDoc ARG_UNUSED(tdoc), TidyOptionId optId ) { const TidyOptionImpl* option = TY_(getOption)( optId ); return tidyImplToOption( option ); } TidyOption TIDY_CALL tidyGetOptionByName( TidyDoc ARG_UNUSED(doc), ctmbstr optnam ) { const TidyOptionImpl* option = TY_(lookupOption)( optnam ); return tidyImplToOption( option ); } TidyOptionId TIDY_CALL tidyOptGetId( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return option->id; return N_TIDY_OPTIONS; } ctmbstr TIDY_CALL tidyOptGetName( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return option->name; return NULL; } TidyOptionType TIDY_CALL tidyOptGetType( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return option->type; return (TidyOptionType) -1; } TidyConfigCategory TIDY_CALL tidyOptGetCategory( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return option->category; return (TidyConfigCategory) -1; } ctmbstr TIDY_CALL tidyOptGetDefault( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option && option->type == TidyString ) return (ctmbstr) option->dflt; return NULL; } ulong TIDY_CALL tidyOptGetDefaultInt( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option && option->type != TidyString ) return option->dflt; return ~0U; } Bool TIDY_CALL tidyOptGetDefaultBool( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option && option->type != TidyString ) return ( option->dflt ? yes : no ); return no; } Bool TIDY_CALL tidyOptIsReadOnly( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return ( option->parser == NULL ); return yes; } TidyIterator TIDY_CALL tidyOptGetPickList( TidyOption topt ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return TY_(getOptionPickList)( option ); return (TidyIterator) -1; } ctmbstr TIDY_CALL tidyOptGetNextPick( TidyOption topt, TidyIterator* pos ) { const TidyOptionImpl* option = tidyOptionToImpl( topt ); if ( option ) return TY_(getNextOptionPick)( option, pos ); return NULL; } ctmbstr TIDY_CALL tidyOptGetValue( TidyDoc tdoc, TidyOptionId optId ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); ctmbstr optval = NULL; if ( impl ) optval = cfgStr( impl, optId ); return optval; } Bool TIDY_CALL tidyOptSetValue( TidyDoc tdoc, TidyOptionId optId, ctmbstr val ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ParseConfigValue)( impl, optId, val ); return no; } Bool TIDY_CALL tidyOptParseValue( TidyDoc tdoc, ctmbstr optnam, ctmbstr val ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ParseConfigOption)( impl, optnam, val ); return no; } ulong TIDY_CALL tidyOptGetInt( TidyDoc tdoc, TidyOptionId optId ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); ulong opti = 0; if ( impl ) opti = cfg( impl, optId ); return opti; } Bool TIDY_CALL tidyOptSetInt( TidyDoc tdoc, TidyOptionId optId, ulong val ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(SetOptionInt)( impl, optId, val ); return no; } Bool TIDY_CALL tidyOptGetBool( TidyDoc tdoc, TidyOptionId optId ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); Bool optb = no; if ( impl ) { const TidyOptionImpl* option = TY_(getOption)( optId ); if ( option ) { optb = cfgBool( impl, optId ); } } return optb; } Bool TIDY_CALL tidyOptSetBool( TidyDoc tdoc, TidyOptionId optId, Bool val ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(SetOptionBool)( impl, optId, val ); return no; } ctmbstr TIDY_CALL tidyOptGetEncName( TidyDoc tdoc, TidyOptionId optId ) { uint enc = tidyOptGetInt( tdoc, optId ); return TY_(CharEncodingOptName)( enc ); } ctmbstr TIDY_CALL tidyOptGetCurrPick( TidyDoc tdoc, TidyOptionId optId ) { const TidyOptionImpl* option = TY_(getOption)( optId ); if ( option && option->pickList ) { uint ix, pick = tidyOptGetInt( tdoc, optId ); const ctmbstr* pL = option->pickList; for ( ix=0; *pL && ix < pick; ++ix ) ++pL; if ( *pL ) return *pL; } return NULL; } TidyIterator TIDY_CALL tidyOptGetDeclTagList( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); TidyIterator declIter = 0; if ( impl ) declIter = TY_(GetDeclaredTagList)( impl ); return declIter; } ctmbstr TIDY_CALL tidyOptGetNextDeclTag( TidyDoc tdoc, TidyOptionId optId, TidyIterator* iter ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); ctmbstr tagnam = NULL; if ( impl ) { UserTagType tagtyp = tagtype_null; if ( optId == TidyInlineTags ) tagtyp = tagtype_inline; else if ( optId == TidyBlockTags ) tagtyp = tagtype_block; else if ( optId == TidyEmptyTags ) tagtyp = tagtype_empty; else if ( optId == TidyPreTags ) tagtyp = tagtype_pre; if ( tagtyp != tagtype_null ) tagnam = TY_(GetNextDeclaredTag)( impl, tagtyp, iter ); } return tagnam; } ctmbstr TIDY_CALL tidyOptGetDoc( TidyDoc ARG_UNUSED(tdoc), TidyOption opt ) { const TidyOptionId optId = tidyOptGetId( opt ); const TidyOptionDoc* docDesc = TY_(OptGetDocDesc)( optId ); return docDesc ? docDesc->doc : NULL; } TidyIterator TIDY_CALL tidyOptGetDocLinksList( TidyDoc ARG_UNUSED(tdoc), TidyOption opt ) { const TidyOptionId optId = tidyOptGetId( opt ); const TidyOptionDoc* docDesc = TY_(OptGetDocDesc)( optId ); if (docDesc && docDesc->links) return (TidyIterator)docDesc->links; return (TidyIterator)NULL; } TidyOption TIDY_CALL tidyOptGetNextDocLinks( TidyDoc tdoc, TidyIterator* pos ) { const TidyOptionId* curr = (const TidyOptionId *)*pos; TidyOption opt; if (*curr == TidyUnknownOption) { *pos = (TidyIterator)NULL; return (TidyOption)0; } opt = tidyGetOption(tdoc, *curr); curr++; *pos = (*curr == TidyUnknownOption ) ? (TidyIterator)NULL:(TidyIterator)curr; return opt; } int TIDY_CALL tidyOptSaveFile( TidyDoc tdoc, ctmbstr cfgfil ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(SaveConfigFile)( impl, cfgfil ); return -EINVAL; } int TIDY_CALL tidyOptSaveSink( TidyDoc tdoc, TidyOutputSink* sink ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(SaveConfigSink)( impl, sink ); return -EINVAL; } Bool TIDY_CALL tidyOptSnapshot( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { TY_(TakeConfigSnapshot)( impl ); return yes; } return no; } Bool TIDY_CALL tidyOptResetToSnapshot( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { TY_(ResetConfigToSnapshot)( impl ); return yes; } return no; } Bool TIDY_CALL tidyOptResetAllToDefault( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { TY_(ResetConfigToDefault)( impl ); return yes; } return no; } Bool TIDY_CALL tidyOptResetToDefault( TidyDoc tdoc, TidyOptionId optId ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ResetOptionToDefault)( impl, optId ); return no; } Bool TIDY_CALL tidyOptDiffThanDefault( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ConfigDiffThanDefault)( impl ); return no; } Bool TIDY_CALL tidyOptDiffThanSnapshot( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return TY_(ConfigDiffThanSnapshot)( impl ); return no; } Bool TIDY_CALL tidyOptCopyConfig( TidyDoc to, TidyDoc from ) { TidyDocImpl* docTo = tidyDocToImpl( to ); TidyDocImpl* docFrom = tidyDocToImpl( from ); if ( docTo && docFrom ) { TY_(CopyConfig)( docTo, docFrom ); return yes; } return no; } /* I/O and Message handling interface ** ** By default, Tidy will define, create and use ** tdocances of input and output handlers for ** standard C buffered I/O (i.e. FILE* stdin, ** FILE* stdout and FILE* stderr for content ** input, content output and diagnostic output, ** respectively. A FILE* cfgFile input handler ** will be used for config files. Command line ** options will just be set directly. */ /* Use TidyReportFilter to filter messages by diagnostic level: ** info, warning, etc. Just set diagnostic output ** handler to redirect all diagnostics output. Return true ** to proceed with output, false to cancel. */ Bool TIDY_CALL tidySetReportFilter( TidyDoc tdoc, TidyReportFilter filt ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { impl->mssgFilt = filt; return yes; } return no; } #if 0 /* Not yet */ int tidySetContentOutputSink( TidyDoc tdoc, TidyOutputSink* outp ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { impl->docOut = outp; return 0; } return -EINVAL; } int tidySetDiagnosticOutputSink( TidyDoc tdoc, TidyOutputSink* outp ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { impl->msgOut = outp; return 0; } return -EINVAL; } /* Library helpers */ cmbstr tidyLookupMessage( TidyDoc tdoc, int errorNo ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); cmbstr mssg = NULL; if ( impl ) mssg = tidyMessage_Lookup( impl->messages, errorNo ); return mssg; } #endif FILE* TIDY_CALL tidySetErrorFile( TidyDoc tdoc, ctmbstr errfilnam ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { FILE* errout = fopen( errfilnam, "wb" ); if ( errout ) { uint outenc = cfg( impl, TidyOutCharEncoding ); uint nl = cfg( impl, TidyNewline ); TY_(ReleaseStreamOut)( impl, impl->errout ); impl->errout = TY_(FileOutput)( impl, errout, outenc, nl ); return errout; } else /* Emit message to current error sink */ TY_(FileError)( impl, errfilnam, TidyError ); } return NULL; } int TIDY_CALL tidySetErrorBuffer( TidyDoc tdoc, TidyBuffer* errbuf ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { uint outenc = cfg( impl, TidyOutCharEncoding ); uint nl = cfg( impl, TidyNewline ); TY_(ReleaseStreamOut)( impl, impl->errout ); impl->errout = TY_(BufferOutput)( impl, errbuf, outenc, nl ); return ( impl->errout ? 0 : -ENOMEM ); } return -EINVAL; } int TIDY_CALL tidySetErrorSink( TidyDoc tdoc, TidyOutputSink* sink ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) { uint outenc = cfg( impl, TidyOutCharEncoding ); uint nl = cfg( impl, TidyNewline ); TY_(ReleaseStreamOut)( impl, impl->errout ); impl->errout = TY_(UserOutput)( impl, sink, outenc, nl ); return ( impl->errout ? 0 : -ENOMEM ); } return -EINVAL; } /* Document info */ int TIDY_CALL tidyStatus( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); int tidyStat = -EINVAL; if ( impl ) tidyStat = tidyDocStatus( impl ); return tidyStat; } int TIDY_CALL tidyDetectedHtmlVersion( TidyDoc ARG_UNUSED(tdoc) ) { /* TidyDocImpl* impl = tidyDocToImpl( tdoc ); */ return 0; } Bool TIDY_CALL tidyDetectedXhtml( TidyDoc ARG_UNUSED(tdoc) ) { /* TidyDocImpl* impl = tidyDocToImpl( tdoc ); */ return no; } Bool TIDY_CALL tidyDetectedGenericXml( TidyDoc ARG_UNUSED(tdoc) ) { /* TidyDocImpl* impl = tidyDocToImpl( tdoc ); */ return no; } uint TIDY_CALL tidyErrorCount( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); uint count = 0xFFFFFFFF; if ( impl ) count = impl->errors; return count; } uint TIDY_CALL tidyWarningCount( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); uint count = 0xFFFFFFFF; if ( impl ) count = impl->warnings; return count; } uint TIDY_CALL tidyAccessWarningCount( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); uint count = 0xFFFFFFFF; if ( impl ) count = impl->accessErrors; return count; } uint TIDY_CALL tidyConfigErrorCount( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); uint count = 0xFFFFFFFF; if ( impl ) count = impl->optionErrors; return count; } /* Error reporting functions */ void TIDY_CALL tidyErrorSummary( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) TY_(ErrorSummary)( impl ); } void TIDY_CALL tidyGeneralInfo( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) TY_(GeneralInfo)( impl ); } /* I/O Functions ** ** Initial version supports only whole-file operations. ** Do not expose Tidy StreamIn or Out data structures - yet. */ /* Parse/load Functions ** ** HTML/XHTML version determined from input. */ int TIDY_CALL tidyParseFile( TidyDoc tdoc, ctmbstr filnam ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocParseFile( doc, filnam ); } int TIDY_CALL tidyParseStdin( TidyDoc tdoc ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocParseStdin( doc ); } int TIDY_CALL tidyParseString( TidyDoc tdoc, ctmbstr content ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocParseString( doc, content ); } int TIDY_CALL tidyParseBuffer( TidyDoc tdoc, TidyBuffer* inbuf ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocParseBuffer( doc, inbuf ); } int TIDY_CALL tidyParseSource( TidyDoc tdoc, TidyInputSource* source ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocParseSource( doc, source ); } int tidyDocParseFile( TidyDocImpl* doc, ctmbstr filnam ) { #ifdef _WIN32 return TY_(DocParseFileWithMappedFile)( doc, filnam ); #else int status = -ENOENT; FILE* fin = fopen( filnam, "rb" ); #if PRESERVE_FILE_TIMES struct stat sbuf = {0}; /* get last modified time */ TidyClearMemory( &doc->filetimes, sizeof(doc->filetimes) ); if ( fin && cfgBool(doc,TidyKeepFileTimes) && fstat(fileno(fin), &sbuf) != -1 ) { doc->filetimes.actime = sbuf.st_atime; doc->filetimes.modtime = sbuf.st_mtime; } #endif if ( fin ) { StreamIn* in = TY_(FileInput)( doc, fin, cfg( doc, TidyInCharEncoding )); if ( !in ) { fclose( fin ); return status; } status = TY_(DocParseStream)( doc, in ); TY_(freeFileSource)(&in->source, yes); TY_(freeStreamIn)(in); } else /* Error message! */ TY_(FileError)( doc, filnam, TidyError ); return status; #endif } int tidyDocParseStdin( TidyDocImpl* doc ) { StreamIn* in = TY_(FileInput)( doc, stdin, cfg( doc, TidyInCharEncoding )); int status = TY_(DocParseStream)( doc, in ); TY_(freeStreamIn)(in); return status; } int tidyDocParseBuffer( TidyDocImpl* doc, TidyBuffer* inbuf ) { int status = -EINVAL; if ( inbuf ) { StreamIn* in = TY_(BufferInput)( doc, inbuf, cfg( doc, TidyInCharEncoding )); status = TY_(DocParseStream)( doc, in ); TY_(freeStreamIn)(in); } return status; } int tidyDocParseString( TidyDocImpl* doc, ctmbstr content ) { int status = -EINVAL; TidyBuffer inbuf; StreamIn* in = NULL; if ( content ) { tidyBufInitWithAllocator( &inbuf, doc->allocator ); tidyBufAttach( &inbuf, (byte*)content, TY_(tmbstrlen)(content)+1 ); in = TY_(BufferInput)( doc, &inbuf, cfg( doc, TidyInCharEncoding )); status = TY_(DocParseStream)( doc, in ); tidyBufDetach( &inbuf ); TY_(freeStreamIn)(in); } return status; } int tidyDocParseSource( TidyDocImpl* doc, TidyInputSource* source ) { StreamIn* in = TY_(UserInput)( doc, source, cfg( doc, TidyInCharEncoding )); int status = TY_(DocParseStream)( doc, in ); TY_(freeStreamIn)(in); return status; } /* Print/save Functions ** */ int TIDY_CALL tidySaveFile( TidyDoc tdoc, ctmbstr filnam ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocSaveFile( doc, filnam ); } int TIDY_CALL tidySaveStdout( TidyDoc tdoc ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocSaveStdout( doc ); } int TIDY_CALL tidySaveString( TidyDoc tdoc, tmbstr buffer, uint* buflen ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocSaveString( doc, buffer, buflen ); } int TIDY_CALL tidySaveBuffer( TidyDoc tdoc, TidyBuffer* outbuf ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocSaveBuffer( doc, outbuf ); } int TIDY_CALL tidySaveSink( TidyDoc tdoc, TidyOutputSink* sink ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); return tidyDocSaveSink( doc, sink ); } int tidyDocSaveFile( TidyDocImpl* doc, ctmbstr filnam ) { int status = -ENOENT; FILE* fout = NULL; /* Don't zap input file if no output */ if ( doc->errors > 0 && cfgBool(doc, TidyWriteBack) && !cfgBool(doc, TidyForceOutput) ) status = tidyDocStatus( doc ); else fout = fopen( filnam, "wb" ); if ( fout ) { uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); StreamOut* out = TY_(FileOutput)( doc, fout, outenc, nl ); status = tidyDocSaveStream( doc, out ); fclose( fout ); TidyDocFree( doc, out ); #if PRESERVE_FILE_TIMES if ( doc->filetimes.actime ) { /* set file last accessed/modified times to original values */ utime( filnam, &doc->filetimes ); TidyClearMemory( &doc->filetimes, sizeof(doc->filetimes) ); } #endif /* PRESERVFILETIMES */ } if ( status < 0 ) /* Error message! */ TY_(FileError)( doc, filnam, TidyError ); return status; } /* Note, _setmode() does NOT work on Win2K Pro w/ VC++ 6.0 SP3. ** The code has been left in in case it works w/ other compilers ** or operating systems. If stdout is in Text mode, be aware that ** it will garble UTF16 documents. In text mode, when it encounters ** a single byte of value 10 (0xA), it will insert a single byte ** value 13 (0xD) just before it. This has the effect of garbling ** the entire document. */ #if !defined(NO_SETMODE_SUPPORT) #if defined(_WIN32) || defined(OS2_OS) #include #include #endif #endif int tidyDocSaveStdout( TidyDocImpl* doc ) { #if !defined(NO_SETMODE_SUPPORT) #if defined(_WIN32) || defined(OS2_OS) int oldstdoutmode = -1, oldstderrmode = -1; #endif #endif int status = 0; uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); StreamOut* out = TY_(FileOutput)( doc, stdout, outenc, nl ); #if !defined(NO_SETMODE_SUPPORT) #if defined(_WIN32) || defined(OS2_OS) oldstdoutmode = setmode( fileno(stdout), _O_BINARY ); oldstderrmode = setmode( fileno(stderr), _O_BINARY ); #endif #endif if ( 0 == status ) status = tidyDocSaveStream( doc, out ); fflush(stdout); fflush(stderr); #if !defined(NO_SETMODE_SUPPORT) #if defined(_WIN32) || defined(OS2_OS) if ( oldstdoutmode != -1 ) oldstdoutmode = setmode( fileno(stdout), oldstdoutmode ); if ( oldstderrmode != -1 ) oldstderrmode = setmode( fileno(stderr), oldstderrmode ); #endif #endif TidyDocFree( doc, out ); return status; } int tidyDocSaveString( TidyDocImpl* doc, tmbstr buffer, uint* buflen ) { uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); TidyBuffer outbuf; StreamOut* out; int status; tidyBufInitWithAllocator( &outbuf, doc->allocator ); out = TY_(BufferOutput)( doc, &outbuf, outenc, nl ); status = tidyDocSaveStream( doc, out ); if ( outbuf.size > *buflen ) status = -ENOMEM; else memcpy( buffer, outbuf.bp, outbuf.size ); *buflen = outbuf.size; tidyBufFree( &outbuf ); TidyDocFree( doc, out ); return status; } int tidyDocSaveBuffer( TidyDocImpl* doc, TidyBuffer* outbuf ) { int status = -EINVAL; if ( outbuf ) { uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); StreamOut* out = TY_(BufferOutput)( doc, outbuf, outenc, nl ); status = tidyDocSaveStream( doc, out ); TidyDocFree( doc, out ); } return status; } int tidyDocSaveSink( TidyDocImpl* doc, TidyOutputSink* sink ) { uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); StreamOut* out = TY_(UserOutput)( doc, sink, outenc, nl ); int status = tidyDocSaveStream( doc, out ); TidyDocFree( doc, out ); return status; } int tidyDocStatus( TidyDocImpl* doc ) { if ( doc->errors > 0 ) return 2; if ( doc->warnings > 0 || doc->accessErrors > 0 ) return 1; return 0; } int TIDY_CALL tidyCleanAndRepair( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return tidyDocCleanAndRepair( impl ); return -EINVAL; } int TIDY_CALL tidyRunDiagnostics( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); if ( impl ) return tidyDocRunDiagnostics( impl ); return -EINVAL; } /* Workhorse functions. ** ** Parse requires input source, all input config items ** and diagnostic sink to have all been set before calling. ** ** Emit likewise requires that document sink and all ** pretty printing options have been set. */ static ctmbstr integrity = "\nPanic - tree has lost its integrity\n"; int TY_(DocParseStream)( TidyDocImpl* doc, StreamIn* in ) { Bool xmlIn = cfgBool( doc, TidyXmlTags ); int bomEnc; assert( doc != NULL && in != NULL ); assert( doc->docIn == NULL ); doc->docIn = in; TY_(TakeConfigSnapshot)( doc ); /* Save config state */ TY_(FreeLexer)( doc ); TY_(FreeAnchors)( doc ); TY_(FreeNode)(doc, &doc->root); TidyClearMemory(&doc->root, sizeof(Node)); if (doc->givenDoctype) TidyDocFree(doc, doc->givenDoctype); doc->givenDoctype = NULL; doc->lexer = TY_(NewLexer)( doc ); /* doc->lexer->root = &doc->root; */ doc->root.line = doc->lexer->lines; doc->root.column = doc->lexer->columns; doc->inputHadBOM = no; bomEnc = TY_(ReadBOMEncoding)(in); if (bomEnc != -1) { in->encoding = bomEnc; TY_(SetOptionInt)(doc, TidyInCharEncoding, bomEnc); } #ifdef TIDY_WIN32_MLANG_SUPPORT if (in->encoding > WIN32MLANG) TY_(Win32MLangInitInputTranscoder)(in, in->encoding); #endif /* TIDY_WIN32_MLANG_SUPPORT */ /* Tidy doesn't alter the doctype for generic XML docs */ if ( xmlIn ) { TY_(ParseXMLDocument)( doc ); if ( !TY_(CheckNodeIntegrity)( &doc->root ) ) TidyPanic( doc->allocator, integrity ); } else { doc->warnings = 0; TY_(ParseDocument)( doc ); if ( !TY_(CheckNodeIntegrity)( &doc->root ) ) TidyPanic( doc->allocator, integrity ); } #ifdef TIDY_WIN32_MLANG_SUPPORT TY_(Win32MLangUninitInputTranscoder)(in); #endif /* TIDY_WIN32_MLANG_SUPPORT */ doc->docIn = NULL; return tidyDocStatus( doc ); } int tidyDocRunDiagnostics( TidyDocImpl* doc ) { Bool quiet = cfgBool( doc, TidyQuiet ); Bool force = cfgBool( doc, TidyForceOutput ); if ( !quiet ) { TY_(ReportMarkupVersion)( doc ); TY_(ReportNumWarnings)( doc ); } if ( doc->errors > 0 && !force ) TY_(NeedsAuthorIntervention)( doc ); return tidyDocStatus( doc ); } int tidyDocCleanAndRepair( TidyDocImpl* doc ) { Bool word2K = cfgBool( doc, TidyWord2000 ); Bool logical = cfgBool( doc, TidyLogicalEmphasis ); Bool clean = cfgBool( doc, TidyMakeClean ); Bool dropFont = cfgBool( doc, TidyDropFontTags ); Bool htmlOut = cfgBool( doc, TidyHtmlOut ); Bool xmlOut = cfgBool( doc, TidyXmlOut ); Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut ); Bool xmlDecl = cfgBool( doc, TidyXmlDecl ); Bool tidyMark = cfgBool( doc, TidyMark ); Bool tidyXmlTags = cfgBool( doc, TidyXmlTags ); Bool wantNameAttr = cfgBool( doc, TidyAnchorAsName ); Node* node; if (tidyXmlTags) return tidyDocStatus( doc ); /* simplifies ... ... etc. */ TY_(NestedEmphasis)( doc, &doc->root ); /* cleans up indented text etc. */ TY_(List2BQ)( doc, &doc->root ); TY_(BQ2Div)( doc, &doc->root ); /* replaces i by em and b by strong */ if ( logical ) TY_(EmFromI)( doc, &doc->root ); if ( word2K && TY_(IsWord2000)(doc) ) { /* prune Word2000's ... */ TY_(DropSections)( doc, &doc->root ); /* drop style & class attributes and empty p, span elements */ TY_(CleanWord2000)( doc, &doc->root ); TY_(DropEmptyElements)(doc, &doc->root); } /* replaces presentational markup by style rules */ if ( clean || dropFont ) TY_(CleanDocument)( doc ); /* Move terminating
tags from out of paragraphs */ /*! Do we want to do this for all block-level elements? */ /* This is disabled due to http://tidy.sf.net/bug/681116 */ #if 0 FixBrakes( doc, TY_(FindBody)( doc )); #endif /* Reconcile http-equiv meta element with output encoding */ if (cfg( doc, TidyOutCharEncoding) != RAW #ifndef NO_NATIVE_ISO2022_SUPPORT && cfg( doc, TidyOutCharEncoding) != ISO2022 #endif ) TY_(VerifyHTTPEquiv)( doc, TY_(FindHEAD)( doc )); if ( !TY_(CheckNodeIntegrity)( &doc->root ) ) TidyPanic( doc->allocator, integrity ); /* remember given doctype for reporting */ node = TY_(FindDocType)(doc); if (node) { AttVal* fpi = TY_(GetAttrByName)(node, "PUBLIC"); if (AttrHasValue(fpi)) { if (doc->givenDoctype) TidyDocFree(doc, doc->givenDoctype); doc->givenDoctype = TY_(tmbstrdup)(doc->allocator,fpi->value); } } if ( doc->root.content ) { /* If we had XHTML input but want HTML output */ if ( htmlOut && doc->lexer->isvoyager ) { Node* node = TY_(FindDocType)(doc); /* Remove reference, but do not free */ if (node) TY_(RemoveNode)(node); } if (xhtmlOut && !htmlOut) { TY_(SetXHTMLDocType)(doc); TY_(FixAnchors)(doc, &doc->root, wantNameAttr, yes); TY_(FixXhtmlNamespace)(doc, yes); TY_(FixLanguageInformation)(doc, &doc->root, yes, yes); } else { TY_(FixDocType)(doc); TY_(FixAnchors)(doc, &doc->root, wantNameAttr, yes); TY_(FixXhtmlNamespace)(doc, no); TY_(FixLanguageInformation)(doc, &doc->root, no, yes); } if (tidyMark ) TY_(AddGenerator)(doc); } /* ensure presence of initial */ if ( xmlOut && xmlDecl ) TY_(FixXmlDecl)( doc ); return tidyDocStatus( doc ); } static Bool showBodyOnly( TidyDocImpl* doc, TidyTriState bodyOnly ) { Node* node; switch( bodyOnly ) { case TidyNoState: return no; case TidyYesState: return yes; default: node = TY_(FindBody)( doc ); if (node && node->implicit ) return yes; } return no; } int tidyDocSaveStream( TidyDocImpl* doc, StreamOut* out ) { Bool showMarkup = cfgBool( doc, TidyShowMarkup ); Bool forceOutput = cfgBool( doc, TidyForceOutput ); #if SUPPORT_UTF16_ENCODINGS Bool outputBOM = ( cfgAutoBool(doc, TidyOutputBOM) == TidyYesState ); Bool smartBOM = ( cfgAutoBool(doc, TidyOutputBOM) == TidyAutoState ); #endif Bool xmlOut = cfgBool( doc, TidyXmlOut ); Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut ); TidyTriState bodyOnly = cfgAutoBool( doc, TidyBodyOnly ); Bool dropComments = cfgBool(doc, TidyHideComments); Bool makeClean = cfgBool(doc, TidyMakeClean); Bool asciiChars = cfgBool(doc, TidyAsciiChars); Bool makeBare = cfgBool(doc, TidyMakeBare); Bool escapeCDATA = cfgBool(doc, TidyEscapeCdata); TidyAttrSortStrategy sortAttrStrat = cfg(doc, TidySortAttributes); if (escapeCDATA) TY_(ConvertCDATANodes)(doc, &doc->root); if (dropComments) TY_(DropComments)(doc, &doc->root); if (makeClean) { /* noop */ TY_(DropFontElements)(doc, &doc->root, NULL); TY_(WbrToSpace)(doc, &doc->root); } if ((makeClean && asciiChars) || makeBare) TY_(DowngradeTypography)(doc, &doc->root); if (makeBare) /* Note: no longer replaces   in */ /* attribute values / non-text tokens */ TY_(NormalizeSpaces)(doc->lexer, &doc->root); else TY_(ReplacePreformattedSpaces)(doc, &doc->root); if ( sortAttrStrat != TidySortAttrNone ) TY_(SortAttributes)(&doc->root, sortAttrStrat); if ( showMarkup && (doc->errors == 0 || forceOutput) ) { #if SUPPORT_UTF16_ENCODINGS /* Output a Byte Order Mark if required */ if ( outputBOM || (doc->inputHadBOM && smartBOM) ) TY_(outBOM)( out ); #endif /* No longer necessary. No DOCTYPE == HTML 3.2, ** which gives you only the basic character entities, ** which are safe in any browser. ** if ( !TY_(FindDocType)(doc) ) ** TY_(SetOptionBool)( doc, TidyNumEntities, yes ); */ doc->docOut = out; if ( xmlOut && !xhtmlOut ) TY_(PPrintXMLTree)( doc, NORMAL, 0, &doc->root ); else if ( showBodyOnly( doc, bodyOnly ) ) TY_(PrintBody)( doc ); else TY_(PPrintTree)( doc, NORMAL, 0, &doc->root ); TY_(PFlushLine)( doc, 0 ); doc->docOut = NULL; } TY_(ResetConfigToSnapshot)( doc ); return tidyDocStatus( doc ); } /* Tree traversal functions ** ** The big issue here is the degree to which we should mimic ** a DOM and/or SAX nodes. ** ** Is it 100% possible (and, if so, how difficult is it) to ** emit SAX events from this API? If SAX events are possible, ** is that 100% of data needed to build a DOM? */ TidyNode TIDY_CALL tidyGetRoot( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); Node* node = NULL; if ( impl ) node = &impl->root; return tidyImplToNode( node ); } TidyNode TIDY_CALL tidyGetHtml( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); Node* node = NULL; if ( impl ) node = TY_(FindHTML)( impl ); return tidyImplToNode( node ); } TidyNode TIDY_CALL tidyGetHead( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); Node* node = NULL; if ( impl ) node = TY_(FindHEAD)( impl ); return tidyImplToNode( node ); } TidyNode TIDY_CALL tidyGetBody( TidyDoc tdoc ) { TidyDocImpl* impl = tidyDocToImpl( tdoc ); Node* node = NULL; if ( impl ) node = TY_(FindBody)( impl ); return tidyImplToNode( node ); } /* parent / child */ TidyNode TIDY_CALL tidyGetParent( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); return tidyImplToNode( nimp->parent ); } TidyNode TIDY_CALL tidyGetChild( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); return tidyImplToNode( nimp->content ); } /* siblings */ TidyNode TIDY_CALL tidyGetNext( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); return tidyImplToNode( nimp->next ); } TidyNode TIDY_CALL tidyGetPrev( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); return tidyImplToNode( nimp->prev ); } /* Node info */ TidyNodeType TIDY_CALL tidyNodeGetType( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); TidyNodeType ntyp = TidyNode_Root; if ( nimp ) ntyp = (TidyNodeType) nimp->type; return ntyp; } uint TIDY_CALL tidyNodeLine( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); uint line = 0; if ( nimp ) line = nimp->line; return line; } uint TIDY_CALL tidyNodeColumn( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); uint col = 0; if ( nimp ) col = nimp->column; return col; } ctmbstr TIDY_CALL tidyNodeGetName( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); ctmbstr nnam = NULL; if ( nimp ) nnam = nimp->element; return nnam; } Bool TIDY_CALL tidyNodeHasText( TidyDoc tdoc, TidyNode tnod ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); if ( doc ) return TY_(nodeHasText)( doc, tidyNodeToImpl(tnod) ); return no; } Bool TIDY_CALL tidyNodeGetText( TidyDoc tdoc, TidyNode tnod, TidyBuffer* outbuf ) { TidyDocImpl* doc = tidyDocToImpl( tdoc ); Node* nimp = tidyNodeToImpl( tnod ); if ( doc && nimp && outbuf ) { uint outenc = cfg( doc, TidyOutCharEncoding ); uint nl = cfg( doc, TidyNewline ); StreamOut* out = TY_(BufferOutput)( doc, outbuf, outenc, nl ); Bool xmlOut = cfgBool( doc, TidyXmlOut ); Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut ); doc->docOut = out; if ( xmlOut && !xhtmlOut ) TY_(PPrintXMLTree)( doc, NORMAL, 0, nimp ); else TY_(PPrintTree)( doc, NORMAL, 0, nimp ); TY_(PFlushLine)( doc, 0 ); doc->docOut = NULL; TidyDocFree( doc, out ); return yes; } return no; } Bool TIDY_CALL tidyNodeGetValue( TidyDoc tdoc, TidyNode tnod, TidyBuffer* buf ) { TidyDocImpl *doc = tidyDocToImpl( tdoc ); Node *node = tidyNodeToImpl( tnod ); if ( doc == NULL || node == NULL || buf == NULL ) return no; switch( node->type ) { case TextNode: case CDATATag: case CommentTag: case ProcInsTag: case SectionTag: case AspTag: case JsteTag: case PhpTag: { tidyBufClear( buf ); tidyBufAppend( buf, doc->lexer->lexbuf + node->start, node->end - node->start ); break; } default: /* The node doesn't have a value */ return no; } return yes; } Bool TIDY_CALL tidyNodeIsProp( TidyDoc ARG_UNUSED(tdoc), TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); Bool isProprietary = yes; if ( nimp ) { switch ( nimp->type ) { case RootNode: case DocTypeTag: case CommentTag: case XmlDecl: case ProcInsTag: case TextNode: case CDATATag: isProprietary = no; break; case SectionTag: case AspTag: case JsteTag: case PhpTag: isProprietary = yes; break; case StartTag: case EndTag: case StartEndTag: isProprietary = ( nimp->tag ? (nimp->tag->versions&VERS_PROPRIETARY)!=0 : yes ); break; } } return isProprietary; } TidyTagId TIDY_CALL tidyNodeGetId(TidyNode tnod) { Node* nimp = tidyNodeToImpl(tnod); TidyTagId tagId = TidyTag_UNKNOWN; if (nimp && nimp->tag) tagId = nimp->tag->id; return tagId; } /* Null for non-element nodes and all pure HTML cmbstr tidyNodeNsLocal( TidyNode tnod ) { } cmbstr tidyNodeNsPrefix( TidyNode tnod ) { } cmbstr tidyNodeNsUri( TidyNode tnod ) { } */ /* Iterate over attribute values */ TidyAttr TIDY_CALL tidyAttrFirst( TidyNode tnod ) { Node* nimp = tidyNodeToImpl( tnod ); AttVal* attval = NULL; if ( nimp ) attval = nimp->attributes; return tidyImplToAttr( attval ); } TidyAttr TIDY_CALL tidyAttrNext( TidyAttr tattr ) { AttVal* attval = tidyAttrToImpl( tattr ); AttVal* nxtval = NULL; if ( attval ) nxtval = attval->next; return tidyImplToAttr( nxtval ); } ctmbstr TIDY_CALL tidyAttrName( TidyAttr tattr ) { AttVal* attval = tidyAttrToImpl( tattr ); ctmbstr anam = NULL; if ( attval ) anam = attval->attribute; return anam; } ctmbstr TIDY_CALL tidyAttrValue( TidyAttr tattr ) { AttVal* attval = tidyAttrToImpl( tattr ); ctmbstr aval = NULL; if ( attval ) aval = attval->value; return aval; } /* Null for pure HTML ctmbstr tidyAttrNsLocal( TidyAttr tattr ) { } ctmbstr tidyAttrNsPrefix( TidyAttr tattr ) { } ctmbstr tidyAttrNsUri( TidyAttr tattr ) { } */ TidyAttrId TIDY_CALL tidyAttrGetId( TidyAttr tattr ) { AttVal* attval = tidyAttrToImpl( tattr ); TidyAttrId attrId = TidyAttr_UNKNOWN; if ( attval && attval->dict ) attrId = attval->dict->id; return attrId; } Bool TIDY_CALL tidyAttrIsProp( TidyAttr tattr ) { /* You cannot tell whether an attribute is proprietary without knowing on which element it occurs in the general case, but this function cannot know the element. As a result, it does not work anymore. Do not use. */ return no; } /* * local variables: * mode: c * indent-tabs-mode: nil * c-basic-offset: 4 * eval: (c-set-offset 'substatement-open 0) * end: */