📄 reader.c
字号:
if (pushedClass >= 0) { rtfClass = pushedClass; rtfMajor = pushedMajor; rtfMinor = pushedMinor; rtfParam = pushedParam; (void) strcpy (rtfTextBuf, pushedTextBuf); rtfTextLen = strlen (rtfTextBuf); pushedClass = -1; return; } /* * Beyond this point, no token is ever seen twice, which is * important, e.g., for making sure no "}" pops the font stack twice. */ _RTFGetToken2 (); if (rtfClass == rtfText) /* map RTF char to standard code */ rtfMinor = RTFMapChar (rtfMajor); /* * If auto-charset stuff is activated, see if anything needs doing, * like reading the charset maps or switching between them. */ if (autoCharSetFlags == 0) return; if ((autoCharSetFlags & rtfReadCharSet) && RTFCheckCM (rtfControl, rtfCharSet)) { ReadCharSetMaps (); } else if ((autoCharSetFlags & rtfSwitchCharSet) && RTFCheckCMM (rtfControl, rtfCharAttr, rtfFontNum)) { if ((fp = RTFGetFont (rtfParam)) != (RTFFont *) NULL) { if (fp->rtfFName!=NULL&&strncmp (fp->rtfFName, "Symbol", 6) == 0) curCharSet = rtfCSSymbol; else curCharSet = rtfCSGeneral; RTFSetCharSet (curCharSet); } } else if ((autoCharSetFlags & rtfSwitchCharSet) && rtfClass == rtfGroup) { switch (rtfMajor) { case rtfBeginGroup: if (csTop >= maxCSStack) RTFPanic ("_RTFGetToken: stack overflow"); csStack[csTop++] = curCharSet; break; case rtfEndGroup: if (csTop <= 0) RTFPanic ("_RTFGetToken: stack underflow"); curCharSet = csStack[--csTop]; RTFSetCharSet (curCharSet); break; } }}/* this shouldn't be called anywhere but from _RTFGetToken() */void_RTFGetToken2 (){int sign;int c; /* initialize token vars */ rtfClass = rtfUnknown; rtfParam = rtfNoParam; rtfTextBuf[rtfTextLen = 0] = '\0'; /* get first character, which may be a pushback from previous token */ if (pushedChar != EOF) { c = pushedChar; rtfTextBuf[rtfTextLen++] = c; rtfTextBuf[rtfTextLen] = '\0'; pushedChar = EOF; } else if ((c = GetChar ()) == EOF) { rtfClass = rtfEOF; return; } if (c == '{') { rtfClass = rtfGroup; rtfMajor = rtfBeginGroup; return; } if (c == '}') { rtfClass = rtfGroup; rtfMajor = rtfEndGroup; return; } if (c != '\\') { /* * Two possibilities here: * 1) ASCII 9, effectively like \tab control symbol * 2) literal text char */ if (c == '\t') /* ASCII 9 */ { rtfClass = rtfControl; rtfMajor = rtfSpecialChar; rtfMinor = rtfTab; } else { rtfClass = rtfText; rtfMajor = c; } return; } if ((c = GetChar ()) == EOF) { /* early eof, whoops (class is rtfUnknown) */ return; } if (!isalpha (c)) { /* * Three possibilities here: * 1) hex encoded text char, e.g., \'d5, \'d3 * 2) special escaped text char, e.g., \{, \} * 3) control symbol, e.g., \_, \-, \|, \<10> */ if (c == '\'') /* hex char */ { int c2; if ((c = GetChar ()) != EOF && (c2 = GetChar ()) != EOF) { /* should do isxdigit check! */ rtfClass = rtfText; rtfMajor = RTFCharToHex (c) * 16 + RTFCharToHex (c2); return; } /* early eof, whoops (class is rtfUnknown) */ return; } /* escaped char */ /*if (index (":{}\\", c) != (char *) NULL) /* escaped char */ if (c == ':' || c == '{' || c == '}' || c == '\\') { rtfClass = rtfText; rtfMajor = c; return; } /* control symbol */ Lookup (rtfTextBuf); /* sets class, major, minor */ return; } /* control word */ while (isalpha (c)) { if ((c = GetChar ()) == EOF) break; } /* * At this point, the control word is all collected, so the * major/minor numbers are determined before the parameter * (if any) is scanned. There will be one too many characters * in the buffer, though, so fix up before and restore after * looking up. */ if (c != EOF) rtfTextBuf[rtfTextLen-1] = '\0'; Lookup (rtfTextBuf); /* sets class, major, minor */ if (c != EOF) rtfTextBuf[rtfTextLen-1] = c; /* * Should be looking at first digit of parameter if there * is one, unless it's negative. In that case, next char * is '-', so need to gobble next char, and remember sign. */ sign = 1; if (c == '-') { sign = -1; c = GetChar (); } if (c != EOF && isdigit (c)) { rtfParam = 0; while (isdigit (c)) /* gobble parameter */ { rtfParam = rtfParam * 10 + c - '0'; if ((c = GetChar ()) == EOF) break; } rtfParam *= sign; } /* * If control symbol delimiter was a blank, gobble it. * Otherwise the character is first char of next token, so * push it back for next call. In either case, delete the * delimiter from the token buffer. */ if (c != EOF) { if (c != ' ') pushedChar = c; rtfTextBuf[--rtfTextLen] = '\0'; }}/* * Read the next character from the input. This handles setting the * current line and position-within-line variables. Those variable are * set correctly whether lines end with CR, LF, or CRLF (the last being * the tricky case). * * bumpLine indicates whether the line number should be incremented on * the *next* input character. */static intGetChar (){int c;int oldBumpLine; if ((c = getc (rtffp)) != EOF) { rtfTextBuf[rtfTextLen++] = c; rtfTextBuf[rtfTextLen] = '\0'; } if (prevChar == EOF) bumpLine = 1; oldBumpLine = bumpLine; /* non-zero if prev char was line ending */ bumpLine = 0; if (c == '\r') bumpLine = 1; else if (c == '\n') { bumpLine = 1; if (prevChar == '\r') /* oops, previous \r wasn't */ oldBumpLine = 0; /* really a line ending */ } ++rtfLinePos; if (oldBumpLine) /* were we supposed to increment the */ { /* line count on this char? */ ++rtfLineNum; rtfLinePos = 1; } prevChar = c; return (c);}/* * Synthesize a token by setting the global variables to the * values supplied. Typically this is followed with a call * to RTFRouteToken(). * * If a param value other than rtfNoParam is passed, it becomes * part of the token text. */voidRTFSetToken (class, major, minor, param, text)int class, major, minor, param;char *text;{ rtfClass = class; rtfMajor = major; rtfMinor = minor; rtfParam = param; if (param == rtfNoParam) (void) strcpy (rtfTextBuf, text); else sprintf (rtfTextBuf, "%s%d", text, param); rtfTextLen = strlen (rtfTextBuf);}/* ---------------------------------------------------------------------- *//* * Routines to handle mapping of RTF character sets * onto standard characters. * * RTFStdCharCode(name) given char name, produce numeric code * RTFStdCharName(code) given char code, return name * RTFMapChar(c) map input (RTF) char code to std code * RTFSetCharSet(id) select given charset map * RTFGetCharSet() get current charset map * * See ../h/README for more information about charset names and codes. *//* * Initialize charset stuff. */static voidCharSetInit (){ autoCharSetFlags = (rtfReadCharSet | rtfSwitchCharSet); RTFFree (genCharSetFile); genCharSetFile = (char *) NULL; haveGenCharSet = 0; RTFFree (symCharSetFile); symCharSetFile = (char *) NULL; haveSymCharSet = 0; curCharSet = rtfCSGeneral; curCharCode = genCharCode;}/* * Specify the name of a file to be read when auto-charset-file reading is * done. */voidRTFSetCharSetMap (name, csId)char *name;int csId;{ if ((name = RTFStrSave (name)) == (char *) NULL) /* make copy */ RTFPanic ("RTFSetCharSetMap: out of memory"); switch (csId) { case rtfCSGeneral: RTFFree (genCharSetFile); /* free any previous value */ genCharSetFile = name; break; case rtfCSSymbol: RTFFree (symCharSetFile); /* free any previous value */ symCharSetFile = name; break; }}/* * Do auto-charset-file reading. */static voidReadCharSetMaps (){char buf[rtfBufSiz]; if (genCharSetFile != (char *) NULL) (void) strcpy (buf, genCharSetFile); else sprintf (buf, "%s-gen", &rtfTextBuf[1]); if (RTFReadCharSetMap (buf, rtfCSGeneral) == 0) RTFPanic ("ReadCharSetMaps: Cannot read charset map %s", buf); if (symCharSetFile != (char *) NULL) (void) strcpy (buf, symCharSetFile); else sprintf (buf, "%s-sym", &rtfTextBuf[1]); if (RTFReadCharSetMap (buf, rtfCSSymbol) == 0) RTFPanic ("ReadCharSetMaps: Cannot read charset map %s", buf);}/* * Read in a file describing an RTF character set map. Lines consist of pairs * associating character names with character values. * * If the filename is an absolute pathname, look in the specified location * only. Otherwise try to find the file in the current directory or library. */intRTFReadCharSetMap (file, csId)char *file;int csId;{FILE *f;char buf[rtfBufSiz];char *name, *p;int *stdCodeArray;int stdCode;int radix;int value;int i;TSScanner scanner;char *scanEscape;char *fn = "RTFReadCharSetMap"; switch (csId) { default: return (0); /* illegal charset id */ case rtfCSGeneral: stdCodeArray = genCharCode; break; case rtfCSSymbol: stdCodeArray = symCharCode; break; } if ((f = RTFOpenLibFile (file, "r")) == (FILE *) NULL) return (0); /* clobber current mapping */ for (i = 0; i < charSetSize; i++) { stdCodeArray[i] = rtfSC_nothing; } /* * Turn off scanner's backslash escape mechanism while reading * charset file. Restore it later. */ TSGetScanner (&scanner); scanEscape = scanner.scanEscape; scanner.scanEscape = ""; TSSetScanner (&scanner); /* read file */ while (fgets (buf, (int) sizeof (buf), f) != (char *) NULL) { if(buf[0] == '#') /* skip comment lines */ continue; TSScanInit (buf); if ((name = TSScan ()) == (char *) NULL) continue; /* skip blank lines */ if ((stdCode = RTFStdCharCode (name)) < 0) { RTFPanic ("%s: unknown character name: %s", fn, name); continue; } if ((p = TSScan ()) == (char *) NULL) { RTFPanic ("%s: malformed charset map line for character %s", fn, name); continue; } if (p[1] == '\0') /* single char - use ascii value */ value = p[0]; else { radix = 10; if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { radix = 16; p += 2; } value = 0; while (*p != '\0') value = value * radix + RTFCharToHex(*p++); } if (value >= charSetSize) { RTFMsg ("%s: character value %d for %s too high\n", fn, value, name); RTFPanic ("maximum value is %d", charSetSize - 1); } stdCodeArray[value] = stdCode; } scanner.scanEscape = scanEscape; TSSetScanner (&scanner); fclose(f); switch (csId) { case rtfCSGeneral: haveGenCharSet = 1; break; case rtfCSSymbol: haveSymCharSet = 1; break; } return (1);}/* * Given a standard character name (a string), find its code (a number). * Return -1 if name is unknown. */intRTFStdCharCode (name)char *name;{int i; for (i = 0; i < rtfSC_MaxChar; i++) { if (strcmp (name, stdCharName[i]) == 0) return (i); } return (-1);}/* * Given a standard character code (a number), find its name (a string). * Return NULL if code is unknown. */char *RTFStdCharName (code)int code;{ if (code < 0 || code >= rtfSC_MaxChar) return ((char *) NULL); return (stdCharName[code]);}/* * Given an RTF input character code, find standard character code. * The translator should read the appropriate charset maps when it finds a * charset control. However, the file might not contain one. In this * case, no map will be available. When the first attempt is made to * map a character under these circumstances, RTFMapChar() assumes ANSI * and reads the map as necessary. */intRTFMapChar (c)int c;{ switch (curCharSet) { case rtfCSGeneral: if (!haveGenCharSet) { if (RTFReadCharSetMap ("ansi-gen", rtfCSGeneral) == 0) RTFPanic ("RTFMapChar: cannot read ansi-gen"); } break; case rtfCSSymbol: if (!haveSymCharSet) { if (RTFReadCharSetMap ("ansi-sym", rtfCSSymbol) == 0) RTFPanic ("RTFMapChar: cannot read ansi-sym"); } break; } if (c < 0 || c >= charSetSize) return (rtfSC_nothing); return (curCharCode[c]);}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -