📄 cslabel.c
字号:
#include "wwwsys.h"/*#include "HTUtils.h" */#include "HTList.h"#include "HTString.h"#include "CSParse.h"#include "CSLL.h"#include "CSLLSt.h"#define GetCSLabel(A) ((A)->target.pCSLabel)#define SETNEXTSTATE(target, subState) \ pCSParse->pTargetObject = target; \ pCSParse->currentSubState = subState;/* C H A R A C T E R S E T V A L I D A T I O N *//* The BNF for PICS labels describes the valid character ranges for each of * the label fields. Defining NO_CHAR_TEST will disable the tedious checking * of these ranges for a slight performance increase. */#ifdef NO_CHAR_TEST#define charSetOK(A, B, C)#define CHECK_CAR_SET(A)#define SET_CHAR_SET(A)#else /* !NO_CHAR_TEST */typedef enum {CharSet_ALPHAS = 1, CharSet_DIGITS = 2, CharSet_PLUSMINUS = 4, CharSet_FORSLASH = 8, CharSet_EXTENS = 0x10, CharSet_BASE64_EXTRAS = 0x20, CharSet_DATE_EXTRAS = 0x40, CharSet_URL_EXTRAS = 0x80, /* ------------------ BNF names are combinations of the above ------------------- */ CharSet_NUMBER = CharSet_DIGITS | CharSet_PLUSMINUS, CharSet_ALPHANUMPM = CharSet_ALPHAS | CharSet_DIGITS | CharSet_PLUSMINUS, CharSet_TRANSMIT_NAME = CharSet_ALPHANUMPM | CharSet_FORSLASH, CharSet_EXT_ALPHANUM = CharSet_ALPHANUMPM | CharSet_EXTENS, CharSet_BASE64 = CharSet_ALPHAS | CharSet_DIGITS | CharSet_BASE64_EXTRAS, CharSet_URL = CharSet_ALPHAS | CharSet_DIGITS | CharSet_URL_EXTRAS, CharSet_DATE = CharSet_DIGITS | CharSet_DATE_EXTRAS, CharSet_EXT_DATA = CharSet_DATE | CharSet_URL | CharSet_NUMBER | CharSet_EXT_ALPHANUM } CharSet_t; PRIVATE BOOL charSetOK(CSParse_t * pCSParse, char * checkMe, CharSet_t set);#define CHECK_CAR_SET(A) \ if (!charSetOK(pCSParse, token, A)) \ return StateRet_ERROR_BAD_CHAR;#define SET_CHAR_SET(A) pCSLabel->targetCharSet = A;#endif /* !NO_CHAR_TEST *//* C S L L S t a t e *//* This holds label list data and the methods to view it. All application * interface is intended to go through these methods. See User/Parsing.html */struct CSLabel_s { CSLLData_t * pCSLLData; LabelError_t * pCurrentLabelError; LabelOptions_t * pCurrentLabelOptions; Extension_t * pCurrentExtension; ExtensionData_t * pCurrentExtensionData; ServiceInfo_t * pCurrentServiceInfo; Label_t * pCurrentLabel; int currentLabelNumber; HTList * pCurrentLabelTree; SingleLabel_t * pCurrentSingleLabel; LabelRating_t * pCurrentLabelRating; Range_t * pCurrentRange;#ifndef NO_CHAR_TEST CharSet_t targetCharSet;#endif LabelTargetCallback_t * pLabelTargetCallback; LLErrorHandler_t * pLLErrorHandler;};/* forward references to parser functions */PRIVATE TargetObject_t LabelList_targetObject;PRIVATE TargetObject_t ServiceInfo_targetObject;PRIVATE TargetObject_t ServiceNoRat_targetObject;PRIVATE TargetObject_t ServiceError_targetObject;PRIVATE TargetObject_t Label_targetObject;PRIVATE TargetObject_t LabelError_targetObject;PRIVATE TargetObject_t LabelTree_targetObject;PRIVATE TargetObject_t SingleLabel_targetObject;PRIVATE TargetObject_t LabelRating_targetObject;PRIVATE TargetObject_t LabelRatingRange_targetObject;PRIVATE TargetObject_t Extension_targetObject;PRIVATE TargetObject_t ExtensionData_targetObject;PRIVATE TargetObject_t Awkward_targetObject;PRIVATE Check_t hasToken;PRIVATE Check_t LabelList_getVersion;PRIVATE Check_t ServiceInfo_getServiceId;PRIVATE Check_t error_getExpl;PRIVATE Check_t getOption;PRIVATE Check_t getOptionValue;PRIVATE Check_t LabelRating_getId;PRIVATE Check_t LabelRating_getValue;PRIVATE Check_t LabelRatingRange_get;PRIVATE Check_t isQuoted;PRIVATE Check_t Extension_getURL;PRIVATE Check_t ExtensionData_getData;PRIVATE Open_t LabelList_open;PRIVATE Open_t ServiceInfo_open;PRIVATE Open_t error_open;PRIVATE Open_t Label_open;PRIVATE Open_t LabelTree_open;PRIVATE Open_t SingleLabel_open;PRIVATE Open_t LabelRating_open;PRIVATE Open_t LabelRatingRange_open;PRIVATE Open_t Awkward_open;PRIVATE Open_t Extension_open;PRIVATE Open_t ExtensionData_open;PRIVATE Close_t LabelList_close;PRIVATE Close_t ServiceInfo_close;PRIVATE Close_t error_close;PRIVATE Close_t Label_close;PRIVATE Close_t LabelTree_close;PRIVATE Close_t SingleLabel_close;PRIVATE Close_t LabelRating_close;PRIVATE Close_t LabelRatingRange_close;PRIVATE Close_t Awkward_close;PRIVATE Close_t Extension_close;PRIVATE Close_t ExtensionData_close;PRIVATE Destroy_t LabelList_destroy;PRIVATE Destroy_t ServiceInfo_destroy;PRIVATE Destroy_t Label_destroy;PRIVATE Destroy_t LabelTree_destroy;PRIVATE Destroy_t SingleLabel_destroy;PRIVATE Destroy_t LabelRating_destroy;PRIVATE Destroy_t LabelRatingRange_destroy;PRIVATE Destroy_t Awkward_destroy;PRIVATE Destroy_t error_destroy;PRIVATE Destroy_t Extension_destroy;PRIVATE Destroy_t ExtensionData_destroy;PRIVATE Prep_t ServiceInfo_clearOpts;PRIVATE Prep_t LabelRating_next;PRIVATE Prep_t Extension_mandatory;PRIVATE Prep_t Extension_next;PRIVATE Prep_t ExtensionData_next;PRIVATE Prep_t SingleLabel_doClose;PRIVATE Prep_t Label_doClose;PRIVATE TargetChangeCallback_t targetChangeCallback;PRIVATE ParseErrorHandler_t parseErrorHandler;/* CSParse_doc states *//* L A B E L L I S T P A R S E R S T A T E S *//* This contains all the states in the BNF for PICS labels. * See User/Parsing.html for details. */PRIVATE StateToken_t LabelList_stateTokens[] = { /* A: fresh LabelList C: expect end */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelList_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, {"get version", SubState_A, Punct_WHITE, &LabelList_getVersion, 0, 0, 0, &ServiceInfo_targetObject, SubState_N, 0, 0}, {"end of list", SubState_C, Punct_RPAREN, 0, 0, 0, 0, &LabelList_targetObject, SubState_A, Command_MATCHANY|Command_CLOSE, 0} };PRIVATE TargetObject_t LabelList_targetObject = {"LabelList", &LabelList_open, &LabelList_close, &LabelList_destroy, LabelList_stateTokens, raysize(LabelList_stateTokens), CSLLTC_LIST};PRIVATE StateToken_t ServiceInfo_stateTokens[] = { /* A: fresh ServiceInfo B: has service id C: needs option value D: call from Awkward or NoRat to close E: call from Awkward to re-enter F: call from Awkward to handle no-ratings error */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "error w/o id", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &ServiceNoRat_targetObject, SubState_N, 0, 0}, { "service id", SubState_A, Punct_WHITE, &ServiceInfo_getServiceId, 0, 0, 0, &ServiceInfo_targetObject, SubState_B, 0, 0}, { "service error", SubState_B, Punct_LPAREN, 0, "error", 0, 0, &ServiceError_targetObject, SubState_N, 0, 0}, { "service option", SubState_B, Punct_WHITE, &getOption, 0, 0, 0, &ServiceInfo_targetObject, SubState_C, 0, 0}, {"service extension", SubState_B, Punct_LPAREN, 0, "extension", 0, 0, &Extension_targetObject, SubState_N, 0, 0}, { "label-mark close", SubState_B, Punct_RPAREN, 0, "l", "labels", 0, &LabelList_targetObject, SubState_C, Command_CLOSE|Command_CHAIN, 0}, { "label-mark", SubState_B, Punct_WHITE|Punct_LPAREN, 0, "l", "labels", 0, &Label_targetObject, SubState_N, Command_CHAIN, &ServiceInfo_clearOpts}, { "option value", SubState_C, Punct_WHITE, &getOptionValue, 0, 0, 0, &ServiceInfo_targetObject, SubState_B, 0, 0}, { "close", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelList_targetObject, SubState_C, Command_MATCHANY|Command_CLOSE|Command_CHAIN, 0}, { "re-enter", SubState_E, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_N, Command_MATCHANY|Command_CLOSE|Command_CHAIN, 0}, { "to no-rat", SubState_F, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_G, Command_MATCHANY|Command_CLOSE|Command_CHAIN, 0}, { "no-rat opener", SubState_G, Punct_ALL, 0, 0, 0, 0, &ServiceNoRat_targetObject, SubState_N, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0} };PRIVATE TargetObject_t ServiceInfo_targetObject = {"ServiceInfo", ServiceInfo_open, &ServiceInfo_close, &ServiceInfo_destroy, ServiceInfo_stateTokens, raysize(ServiceInfo_stateTokens), CSLLTC_SERVICE};PRIVATE StateToken_t Label_stateTokens[] = { /* A: fresh SingleLabel C: route to Awkward from LabelTree and LabelError D: from Awkward to LabelError */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Label_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "single label mark", SubState_A, Punct_WHITE, 0, "l", "labels", 0, &Label_targetObject, SubState_A, 0, 0}, /* stick around */ { "tree label mark", SubState_A, Punct_LPAREN, 0, "l", "labels", 0, &LabelTree_targetObject, SubState_N, 0, 0}, { "start tree", SubState_A, Punct_LPAREN, 0, 0, 0, 0, &LabelTree_targetObject, SubState_N, 0, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &LabelError_targetObject, SubState_N, 0, 0}, {"SingleLabel option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "ratings", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "to awkward", SubState_C, Punct_ALL, 0, 0, 0, 0, &Awkward_targetObject, SubState_A, Command_MATCHANY|Command_CLOSE, 0}, { "awkward to error", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelError_targetObject, SubState_N, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0} };PRIVATE TargetObject_t Label_targetObject = {"Label", &Label_open, &Label_close, &Label_destroy, Label_stateTokens, raysize(Label_stateTokens), CSLLTC_LABEL};PRIVATE StateToken_t LabelTree_stateTokens[] = { /* A: LabelTrees have no state */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelTree_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &LabelError_targetObject, SubState_N, 0, 0}, {"SingleLabel option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "ratingword", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "end of tree", SubState_A, Punct_RPAREN, 0, 0, 0, 0, &Label_targetObject, SubState_C, Command_CLOSE|Command_CHAIN, 0} };PRIVATE TargetObject_t LabelTree_targetObject = {"LabelTree", &LabelTree_open, &LabelTree_close, &LabelTree_destroy, LabelTree_stateTokens, raysize(LabelTree_stateTokens), CSLLTC_LABTREE};PRIVATE StateToken_t SingleLabel_stateTokens[] = { /* A: fresh SingleLabel B: needs option value */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &SingleLabel_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, {"label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &Extension_targetObject, SubState_N, 0, 0}, { "label option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_B, 0, 0}, { "ratingword", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &LabelRating_targetObject, SubState_N, 0, 0}, { "option value", SubState_B, Punct_WHITE, &getOptionValue, 0, 0, 0, &SingleLabel_targetObject, SubState_A, 0, 0} };PRIVATE TargetObject_t SingleLabel_targetObject = {"SingleLabel", &SingleLabel_open, &SingleLabel_close, &SingleLabel_destroy, SingleLabel_stateTokens, raysize(SingleLabel_stateTokens), CSLLTC_SINGLE};PRIVATE StateToken_t LabelRating_stateTokens[] = { /* A: looking for transmit name B: looking for value C: return from range (either creates a new rating or ends) D: close and re-open */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelRating_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "id before value", SubState_A, Punct_WHITE, &LabelRating_getId, 0, 0, 0, &LabelRating_targetObject, SubState_B, 0, 0}, { "id before range", SubState_A, Punct_LPAREN, &LabelRating_getId, 0, 0, 0, &LabelRatingRange_targetObject, SubState_N, 0, 0}, { "value next", SubState_B, Punct_WHITE, &LabelRating_getValue, 0, 0, 0, &LabelRating_targetObject, SubState_D, 0, 0}, /* opener must close last rating first */ { "value close", SubState_B, Punct_RPAREN, &LabelRating_getValue, 0, 0, 0, 0, SubState_X, Command_CLOSE, &LabelRating_next}, { "close", SubState_C, Punct_RPAREN, 0, 0, 0, 0, 0, SubState_X, Command_CLOSE, &LabelRating_next}, {"value after range", SubState_C, Punct_WHITE|Punct_LPAREN, &hasToken, 0, 0, 0, &LabelRating_targetObject, SubState_D, Command_CHAIN, 0}, /* opener must close last rating first */ { "re-enter", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelRating_targetObject, SubState_N, Command_MATCHANY|Command_CLOSE|Command_CHAIN, 0} };PRIVATE TargetObject_t LabelRating_targetObject = {"LabelRating", &LabelRating_open, &LabelRating_close, &LabelRating_destroy, LabelRating_stateTokens, raysize(LabelRating_stateTokens), CSLLTC_RATING};PRIVATE StateToken_t LabelRatingRange_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelRatingRange_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "range data", SubState_A, Punct_WHITE, &LabelRatingRange_get, 0, 0, 0, &LabelRatingRange_targetObject, SubState_A, 0, 0}, {"range close", SubState_A, Punct_RPAREN, &LabelRatingRange_get, 0, 0, 0, &LabelRating_targetObject, SubState_C, Command_CLOSE, 0} };PRIVATE TargetObject_t LabelRatingRange_targetObject = {"LabelRatingRange", &LabelRatingRange_open, &LabelRatingRange_close, &LabelRatingRange_destroy, LabelRatingRange_stateTokens, raysize(LabelRatingRange_stateTokens), CSLLTC_RANGE};/* Awkward assumes that the current Label has been closed. It decides whether to chain to LabelTree, Label, or ServiceInfo */PRIVATE StateToken_t Awkward_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Awkward_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "start tree", SubState_A, Punct_LPAREN, 0, 0, 0, 0, &LabelTree_targetObject, SubState_N, 0, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &Awkward_targetObject, SubState_B, 0, 0}, { "label option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, {"label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, { "rating", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, { "new service id", SubState_A, Punct_WHITE, &isQuoted, 0, 0, 0, &ServiceInfo_targetObject, SubState_E, Command_CHAIN, 0}, { "close", SubState_A, Punct_RPAREN, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CHAIN, 0}, /* close of LabelList */ { "req-denied", SubState_B, Punct_WHITE, 0, "request-denied", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "req-denied close", SubState_B, Punct_RPAREN, 0, "request-denied", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "not-labeled", SubState_B, Punct_WHITE, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, {"not-labeled close", SubState_B, Punct_RPAREN, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "no-ratings", SubState_B, Punct_WHITE, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_F, Command_CHAIN, 0}, { "no-ratings close", SubState_B, Punct_RPAREN, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_F, Command_CHAIN, 0} };PRIVATE TargetObject_t Awkward_targetObject = {"Awkward", &Awkward_open, &Awkward_close, &Awkward_destroy, Awkward_stateTokens, raysize(Awkward_stateTokens), 0};/* error parsing states */PRIVATE StateToken_t ServiceNoRat_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceNoRat_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "no-ratings", SubState_A, Punct_WHITE, 0, "no-ratings", 0, 0, &ServiceNoRat_targetObject, SubState_B, 0, 0}, { "no-ratings close", SubState_A, Punct_RPAREN, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE|Command_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &ServiceNoRat_targetObject, SubState_B, 0, 0}, {"explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE|Command_CHAIN, 0} };PRIVATE TargetObject_t ServiceNoRat_targetObject = {"ServiceNoRat", &error_open, &error_close, &error_destroy, ServiceNoRat_stateTokens, raysize(ServiceNoRat_stateTokens), CSLLTC_NORAT};PRIVATE StateToken_t ServiceError_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceError_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "req-denied", SubState_A, Punct_WHITE, 0, "request-denied", 0, 0, &ServiceError_targetObject, SubState_B, 0, 0}, { "req-denied close", SubState_A, Punct_RPAREN, 0, "request-denied", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE|Command_CHAIN, 0}, { "service-unavail", SubState_A, Punct_WHITE, 0,"service-unavailable", 0, 0, &ServiceError_targetObject, SubState_B, 0, 0}, {"service-unavail close", SubState_A, Punct_RPAREN, 0,"service-unavailable", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE|Command_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &ServiceError_targetObject, SubState_B, 0, 0}, { "explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE|Command_CHAIN, 0} };PRIVATE TargetObject_t ServiceError_targetObject = {"ServiceError", &error_open, &error_close, &error_destroy, ServiceError_stateTokens, raysize(ServiceError_stateTokens), CSLLTC_SRVERR};PRIVATE StateToken_t LabelError_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelError_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "req-denied", SubState_A, Punct_WHITE, 0, "request-denied", 0, 0, &LabelError_targetObject, SubState_B, 0, 0}, { "req-denied close", SubState_A, Punct_RPAREN, 0, "request-denied", 0, 0, &Label_targetObject, SubState_C, Command_CLOSE|Command_CHAIN, 0}, { "not-labeled", SubState_A, Punct_WHITE, 0, "not-labeled", 0, 0, &LabelError_targetObject, SubState_B, 0, 0}, {"not-labeled close", SubState_A, Punct_RPAREN, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_C, Command_CLOSE|Command_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &LabelError_targetObject, SubState_B, 0, 0}, {"explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &Label_targetObject, SubState_C, Command_CLOSE|Command_CHAIN, 0} };PRIVATE TargetObject_t LabelError_targetObject = {"LabelError", &error_open, &error_close, &error_destroy, LabelError_stateTokens, raysize(LabelError_stateTokens), CSLLTC_LABERR};PRIVATE StateToken_t Extension_stateTokens[] = { /* A: looking for mand/opt B: looking for URL C: back from ExtensionData */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Extension_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0}, { "mandatory", SubState_A, Punct_WHITE, 0, "mandatory", 0, 0, &Extension_targetObject, SubState_B, 0, &Extension_mandatory}, { "optional", SubState_A, Punct_WHITE, 0, "optional", 0, 0, &Extension_targetObject, SubState_B, 0, 0}, { "URL", SubState_B, Punct_WHITE, &Extension_getURL, 0, 0, 0, &ExtensionData_targetObject, SubState_N, 0, 0},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -