\begindata{text,538268692} \textdsversion{12} \template{default} \define{global } \define{footnote attr:[Flags OverBar Int Set] attr:[FontSize PreviousFontSize Point -2]} \define{hidden menu:[Region~4,Hidden] attr:[FontFamily AndySans Int 0] attr:[FontSize PreviousFontSize Point -4]} \define{reallyhidden menu:[Region~4,ReallyHidden] attr:[Flags Hidden Int Set]} \define{min1 menu:[Font~1,Min1] attr:[FontSize PreviousFontSize Point -1]} \define{plus6 menu:[Font~1,Plus6] attr:[FontSize PreviousFontSize Point 6]} \define{plus18 menu:[Font~1,Plus18] attr:[FontSize PreviousFontSize Point 18]} \define{sans menu:[Font~1,Sans] attr:[FontFamily AndySans Int 0]} \define{symbol menu:[Font~1,Symbol] attr:[FontFamily Symbol Int 0]} \define{symbola menu:[Font~1,SymbolA] attr:[FontFamily SymbolA Int 0]} \define{andy menu:[Font~1,Andy] attr:[FontFamily Andy Int 0]} \define{up2 menu:[Justify~2,Up2] attr:[Script PreviousScriptMovement Point -2]} \define{down2 menu:[Justify~2,Down2] attr:[Script PreviousScriptMovement Point 2]} \define{para6 menu:[Justify~2,Para6] attr:[Spacing ConstantSpacing Point 0] attr:[Spread ConstantSpacing Point 6]} \define{para12 menu:[Justify~2,Para12] attr:[Spread ConstantSpacing Point 14]} \define{para24 menu:[Justify~2,Para24] attr:[Spread ConstantSpacing Point 24]} \define{line6 menu:[Justify~2,Line6] attr:[Spacing ConstantSpacing Point 6]} \define{line12 menu:[Justify~2,Line12] attr:[Spacing ConstantSpacing Point 12]} \define{line24 menu:[Justify~2,Line24] attr:[Spacing ConstantSpacing Point 24]} \define{leftinmin36 menu:[Indent~5,LeftInMin36] attr:[LeftMargin LeftMargin Cm -83231]} \define{leftinmin12 menu:[Indent~5,LeftInMin12] attr:[LeftMargin LeftMargin Cm -27744]} \define{leftindent12 menu:[Indent~5,LeftIndent12] attr:[LeftMargin LeftMargin Cm 27744]} \define{leftindent36 menu:[Indent~5,LeftIndent36] attr:[LeftMargin LeftMargin Cm 83231]} \define{leftindent72 menu:[Indent~5,LeftIndent72] attr:[LeftMargin LeftMargin Cm 166461]} \define{rightinmin36 menu:[Indent~5,RightInMin36] attr:[RightMargin RightMargin Cm -83231]} \define{rightinmin12 menu:[Indent~5,RightInMin12] attr:[RightMargin RightMargin Cm -27744]} \define{rightindent12 menu:[Indent~5,RightIndent12] attr:[RightMargin RightMargin Cm 27744]} \define{rightindent36 menu:[Indent~5,RightIndent36] attr:[RightMargin RightMargin Cm 83231]} \define{rightindent72 menu:[Indent~5,RightIndent72] attr:[RightMargin RightMargin Cm 166461]} \define{firstinmin72 menu:[Indent~5,FirstInMin72] attr:[Indent PreviousIndentation Cm -166461]} \define{firstinmin36 menu:[Indent~5,FirstInMin36] attr:[Indent PreviousIndentation Cm -83231]} \define{firstinmin12 menu:[Indent~5,FirstInMin12] attr:[Indent PreviousIndentation Cm -27744]} \define{firstindent12 menu:[Indent~5,FirstIndent12] attr:[Indent PreviousIndentation Cm 27744]} \define{firstindent36 menu:[Indent~5,FirstIndent36] attr:[Indent PreviousIndentation Cm 83231]} -- fromrtf.n -- Convert a file (or selected section) from RTF format to ATK format. -- -- Author: WJHansen marker Version := "1.3" -- Version 1.3 - 19 February 1991 -- bug fixes, especially to indentation and \\* -- now deals with an old fonttbl format -- Version 1.2 - 13 Feb 1991 -- Added features: -- annotations, fields, index entries, table of contents (partial) -- all page numbering options -- paragraph indentation has been corrected -------------------------------------------- -- HERE'S HOW -- To convert an entire file give the command -- nessrun /usr/andrew/lib/ness/fromrtf.n -- The output will be in a file having the same prefix and the extension '.d' -- An existing file with the name generated for the output will be moved to -- the same name with the extension '.old' -- To convert a piece of a document: -- Select the piece, type ESC-ESC, and at the 'Ness:' prompt type -- fileconvert_convert() -- To have the conversion as a menu option, add to your ~/.atkinit (or other .XYZinit): -- call ness-load FILENAME -- where FILENAME is the full pathname of this file -- To invoke conversion from another Ness program, call the function -- fromrtf_to_atk(text) -- The return value will be the converted text. -- For the second, third, and fourth options your ~/.atkinit (or other .XYZinit file) -- should contain the lines -- load ness -- addkey ness-dostmt \\e\\e view ----------------------------------------- -- Known Problems -- Styles are fragmented, a long indented section will have separate pieces -- at each place where the style of an internal piece changes. -- -- Table of contents entries in ATK are generated based on styles. These -- styles are not currently generated by this program; instead the individual -- components of the styles are generated. -- Hidden text in ATK cannot be viewed readily. Users can get around this -- by using lookz to give some other attributes to the style "Hidden". ----------------------------------------- -- Algorithm -- The main loop searches for the next \\ \{ \} or newline, -- processing each appropriately. -- CurrText is the unprocessed tail of the original input. -- The accumulated output is in OutText. -- Newlines and carriage returns are ignored, everywhere. -- The format of a control is -- backslash, letters, optional-number-optionally-signed, optional-space -- or -- backslash, non-letter -- PeelControl() knows this syntax and strips one control off the input. -- Our strategy for dealing with styles is to accumulate a style -- string from style information. When the style changes or a group -- ends, the current style string is applied to the text that has just -- been finished. -- The style string to be applied to any given piece of text may have a sequence -- of styles, each of which is represented as a byte with that style. -- The entire sequence is stored as a sequence of such bytes, each followed -- by a single unstyled blank. A style defined in the rtf \\stylesheet is stored -- in variable StyleSheet as the sequence: -- \\sdd (where dd is an integer), followed by a dash, -- the style sequence, and finally a comma. -- On encountering a style, the plain text collected since the last style -- is marked with the former style. Then the new style is applied -- (added or deleted) to the style string. -- At the end of a group, the outer style string is reinstated, popping -- its string off StyleStack in ParseGroup. -- The following rtf controls are processed by this program. -- A # means the style has a numeric operand -- A * means the control may have the operand 0 to turn off the style. -- Major groups that are specially processed -- \\rtf# \\fonttbl \\stylesheet \\footnote -- \\footer \\footerl \\footerr \\header \\headerl \\headerr -- \\*\\annotation \\*\\atnid stored as hidden text -- \\field - minimal processing. -- convert page to \\chpgn or use \\fldrslt (if not \\fldpriv) -- ignore \\flddirty \\fldedit \\fldlock \\*\\fldinst -- \\xe text goes into document (possibly hidden ala \\v) \\: -> : -- ignore \\bxe \\ixe \\rxe \\txe -- \\tc ignore \\tcf# and \\tcl# -- \\info saved in document with "Hidden" style -- \\info includes the following: -- \\title \\subject \\author \\keywords \\comment \\version -- \\doccomm \\vern# \\creatim \\yr# \\mo# \\dy# \\hr# \\min# \\id# -- \\revtim \\printim \\buptim \\edmins# \\nopages# \\nofwords# \\nofchars# -- Character set is assumed to be ASCII, so the mappings -- \\ansi \\mac \\pc \\pca \\nextcset -- are minimal and utilized only for \\' -- These maps can be extended by adding appropriate entries. -- Page numbering and section controls -- \\page \\pgnstart# \\pgnstarts# \\pgnrestart \\pgncont -- \\pgndec \\pgnucrm \\pgnlcrm \\pgnucltr \\pgnlcltr -- \\sect \\sectd \\sbknone \\sbkcol \\sbkpage \\sbkeven \\sbkodd -- Controls that result in modifications to the style string -- \\pard \\s# -- \\v uses "Hidden" style -- \\ql \\qr \\qj \\qc -- \\plain \\b* \\i* \\f \\fs \\ulnone -- \\ul* \\ulw* \\uld* \\uldb* all treated as \\ul -- \\fi# \\li# \\ri# rounded to nearest 12 points -- \\up# \\dn# \\sb# \\sa# \\sl# rounded to nearest 2 points -- as installed, the Region,Hidden style is sanserif and four points smaller. -- To make this text invisible, edit the style to have the Hidden -- attribute in the "enable" section. This attribute can be made visible -- by clicking the Region,ReallyHidden style name in lookz. -- Unfortunately, ReallyHidden text still prints as of February, 1991 -- Controls that are replaced with text -- \\par newline -- backslash-newline newline -- backslash-return newline -- \\row newline -- \\cell tab -- \\line carriage return ("soft" newline) -- \\tab -- \\~ unpaddable space -- \\'n uses the n'th ASCII character (may be mapped) -- \\- soft hyphen -- \\_ non-breaking hyphen -- \\\\ \\ -- \\\{ \{ -- \\\} \} -- \\: : -- \\chpgn page number -- \\chdate mo/day/yr, as 1/30/91 -- \\bullet \\emdash \\endash \\lquote \\rquote \\ldblquote \\rdblquote ---------------------------------------- -- Ignored controls -- -- Groups beginning with these words -- \\headerf \\footerf \\pict \\colortbl -- \\*\\bkmkstart \\*\\bkmkend -- Associated with the ignored groups are these controls -- which appear only in these groups and are thus never encountered -- \\red# \\green# \\blue# \\ftnsep \\ftnspec \\ftncn -- \\pich# \\picw# \\picscaled \\wmetafile# \\macpict \\bin# -- \\wbitmap# \\picwGoal# \\pichGoal# \\picscalex# \\picscaley# -- \\piccropt# \\piccropb# \\piccropl# \\piccropr# -- \\wbmbitspixel# \\wbmplanes# \\wbmwidthbytes# -- Document formatting controls -- \\paperw# \\paperh# \\margl# \\margr# \\margt# \\margb# \\facingp -- \\gutter# \\ogutter# \\deftab# \\widowctrl \\deff# \\revbar# -- \\hyphotz# \\ftncn \\enddoc \\defformat \\revisions \\revprop# -- \\ftnbj \\ftnsep \\ftnsepc \\endnotes \\ftntj \\ftnstart# -- \\ftnrestart \\linestart# \\landscape \\margmirror -- \\fracwidth \\*\\nextfile \\*\\template \\makeback -- Section properties: -- \\pgnx# \\pgny# \\headery# \\footery# -- \\linemod# \\linex# \\linestarts# \\linerestart \\lineppage -- \\linecont \\vertalt \\vertalc \\vertalj \\vertal -- \\cols# \\colsx# \\linebetcol \\endnhere \\titlepg -- Paragraph styles -- \\keep \\keepn \\sbys \\noline \\tx# \\tqr \\tb \\tqc \\tqdec -- \\brdrt \\brdrb \\brdrl \\brdrr \\box \\brdrs -- \\brdrth \\brdrsh \\brdrdb \\brdrdot \\brdrhair \\brsp# -- \\tldot \\tlhyph \\tlul \\tlth \\pagebb -- Absolute positioned objects -- \\posx# \\posxc \\posxi \\posxl \\posxo \\posxr -- \\posy# \\posyil \\posyt \\posyc \\posyb -- \\absw# \\dxfrtext# \\pvmrg \\pvpg \\phmrg \\phpg \\phcol -- Tables -- \\intbl \\clbrdrb \\clbrdrt \\clbrdrr \\clbrdrl -- \\trowd \\trql \\trqc \\trqr \\trgaph# \\trrh# \\trleft# -- \\cellx# \\clmgf \\clmgr -- Character styles -- \\strike \\outl \\shad \\scaps \\caps \\expnd# \\cb# \\cf# \\revised -- Special characters -- \\chftn \\chftnsep \\chftnsepc \\chtime \\| \\chatn \\column ------- Lookz to edit the special styles used in this program -- Do not use lookz to edit styles FirstIndent\italic{xx} and FirstInMin\italic{xx}. -- \begindata{lookz, 538247816} hidden \enddata{lookz, 538247816} \view{lookzview,538247816,14,0,0} --------------------------------------------- -- constants integer DEFAULTFONTSIZE := 12 -- whatever size is usual marker Letters := "qwertyuiopasdfghjklzxcvbnm" ~ "QWERTYUIOPASDFGHJKLZXCVBNM" marker Hidden := "\hidden{h}idden" -- first letter has "hidden" style -- (this value is temporarily replaced in processing \\xe) marker PageBreak := // \begindata{bp,538247880} \enddata{bp,538247880} \view{bpv,538247880,15,0,0} \\\\ --------------------------------------------- -- global state marker CurrText -- what remains to be parsed -- results of parseControl() marker CurrCtl -- the result of parsing the latest control marker CurrRand -- the operand string integer CurrRandValue -- the numeric operand marker StyleSheet -- constructed from \\stylesheet marker FontTbl -- constructed from \\fonttbl group marker CurrMap -- set from macmap, ansimap, pcmap, or pcamap boolean DefinedHeader -- have we seen \\header... boolean sectBreakPage := True -- set False by \\sbknone boolean restartpgnumpersect := False -- set true by \\pgnrestart integer sectFirstPageNum := 1 -- set by \\pgnstarts boolean pageNumberSupplied := False -- kludge marker currPageNFmt := "1" -- set by \\pgnxcxx --------------------------------------------- -- Control Interpretation Table -- The ControlInterpretationTable gives a translation for every control -- interpreted by this program. -- The proper entry for "control" is found by searching for "\\control-" -- and utilizing subsequent characters up to the comma. -- The first character after the dash is the major function indicator -- and determines, for example, whether preceding text should have the -- current style applied. marker ControlInterpretationTable := -- these entries all introduce new styles. The major function code is "s". -- the action for those without $ is to append the style to the current style -- for those with subcode $, individual actions are taken -- The style code letters are not duplicated so when a style is to be deleted -- from the current style, its code letter is deleted from the style string. "\\\\ql-s\flushleft{A},\\\\qr-s\flushright{B},\\\\qj-sC,\\\\qc-s\center{D},\ \\\\b-s\bold{E},\\\\i-s\italic{F}," ~ "\\\\v-s\hidden{G}," -- between the s and comma is a "G" in style Hidden ~ "\\\\ul-s\underline{I},\\\\ulw-s\underline{J},\\\\uld-s\underline{K},\\\\uldb-s\ \underline{L},\\\\up-s$R\up2{M}\down2{M},\\\\dn-s$R\down2{N}\up2{N}," ~ "\\\\li-s$P\leftinmin36{h}\leftindent72{h}\leftinmin12{h}\leftindent36{h}\leftindent12{h\ },\\\\ri-s$P\rightinmin36{i}\rightindent72{i}\rightinmin12{i}\rightindent36{i}\ \rightindent12{i},\\\\fi-s$Q\firstinmin72{j}\firstindent36{j}\firstinmin36{j}\ \firstindent12{j}\firstinmin12{j},\\\\sb-s$U\para6{k}\para12{k}\para24{k},\\\\s\ a-s$U\para6{k}\para12{k}\para24{k},\\\\sl-s$U\line6{l}\line12{l}\line24{l}," ~ "\\\\s-s$S,\\\\fs-s$T,\\\\f-s$f,\\\\ulnone-s$V," ~ "\\\\plain-s$W,\\\\pard-s$X,\\\\snext-s$n,\\\\sbasedon-s$b," -- the following are simply replaced with the text following the -- major function code, which is "r" ~ "\\\\par-r\\n,\\\\tab-r\\t,\\\\~-r\formatnote{\\\\ },\\\\_-r\formatnote{\\\\-},\\\\--r\formatnote{\\\\%},\\\\:-r:," ~ "\\\\\\r-r\\n,\\\\line-r\\r,\\\\\{-r\{,\\\\\}-r\},\\\\\\\\-r\\\\,\\\\\\n-r\\n,"\ ~ "\\\\chpgn-r\formatnote{\\\\\\\\n(PN},\\\\chdate-r\formatnote{\\\\\\\\n(mo/\\\\\ \\\\n(dy/\\\\\\\\n(yr}," ~ "\\\\cell-r\\t,\\\\row-r\\n,\\\\bullet-r\symbola{7},\\\\emdash-r\symbola{>},\\\\\ endash-r-," ~ "\\\\lquote-r`,\\\\rquote-r',\\\\ldblquote-r\\",\\\\rdblquote-r\symbola{2}," -- footnotes (code "p") return text to be inserted unstyled -- picts are ignored. annotations are stored as hidden text ~ "\\\\footnote-pA,\\\\pict-pB," ~ "\\\\annotation-pC,\\\\atnid-pD,\\\\annotation-pC,\\\\atnid-pD," ~ "\\\\field-pE,\\\\xe-pF,\\\\tc-pG," -- hex chars are mapped. major function code "m" ~ "\\\\'-m," -- map font codes to ATK fonts. major function code "f" -- (These should only be seen by parseFonttbl) ~ "\\\\fnil-f,\\\\froman-\andy{f},\\\\fswiss-\sans{f},\\\\fmodern-\typewriter{f},\ " ~ "\\\\fscript-\italic{\underline{f}},\\\\fdecor-\bold{\underline{f}},\\\\ftech-\ \symbol{f}," -- page numbering and section controls, func code "qP" ~ "\\\\pgnstart-qPa,\\\\pgnstarts-qPb,\\\\pgnrestart-qPc,\\\\pgncont-qPd," ~ "\\\\pgnucrm-qPe,\\\\pgnlcrm-qPf,\\\\pgnucltr-qPg,\\\\pgnlcltr-qPh,\\\\pgndec-q\ Pi," ~ "\\\\sect-qPj,\\\\sectd-qPk,\\\\sbknone-qPl,\\\\sbkcol-qPm," ~ "\\\\sbkpage-qPm,\\\\sbkeven-qPm,\\\\sbkodd-qPm,\\\\page-qPp," -- these introduce major blocks. Function code "q" ~ "\\\\footer-qEfs,\\\\footerl-qEfd,\\\\footerr-qEfd," ~ "\\\\header-qEhs,\\\\headerl-qEhd,\\\\headerr-qEhd," ~ "\\\\mac-qCA,\\\\pc-qCB,\\\\ansi-qCC,\\\\nextcset-qCC,\\\\pca-qCD," ~ "\\\\rtf-qR,\\\\fonttbl-qF,\\\\stylesheet-qS,\\\\info-qI," ~ "\\\\*-q*," -- unknown destinations are ignored ~ "\\\\colortbl-q#,\\\\bkmkstart-q#,\\\\bkmkend-q#," -- ignored ~ "\\\\txe-q#,\\\\rxe-q#," --------------------------------------------- -- font controls \symbola{ }-- Font choices: -- \\fnil -> default font -- \\roman -> andy -- \\fswiss -> andysans -- \\fmodern-> andytype -- \\fscript -> default-italic-underline -- \\fdecor -> default-bold-underline -- \\ftech -> symbol (could be symbola, XXX need mapping) -- The fonts Symbol and SymbolA under ATK are in the PostScript ordering. -- font Symbol: (PostScript symbol codes 0x20 ... 0x7F) --\symbol{ !"#$%&'()*+,-./} 2x punctuation -- \symbol{0123456789:;<=>?} 3x digits -- \symbol{@ABCDEFGHIJKLMNO} 4x upper case -- \symbol{PQRSTUVWXYZ[\\]^_} 5x upper case\symbol{ }-- \symbol{`abcdefghijklmno} 6x lower case\symbol{ }-- \symbol{pqrstuvwxyz\{|\}~?} 7x lower case -- font SymbolA: (PostScript symbol codes 0xA0 ... 0xFF, mapped to 0x20 ... 0x7F) -- \symbola{ !"#$%&'()*+,-./} 2x\symbola{ }--\symbola{ 0123456789:;<=>?} 3x --\symbola{ @ABCDEFGHIJKLMNO} 4x --\symbola{ PQRSTUVWXYZ[\\]^_} 5x --\symbola{ `abcdefghijklmno} 6x --\symbola{ pqrstuvwxyz\{|\}~?} 7x marker macmap := "a1-\symbola{0}a5-\symbola{7}a8-\symbola{b}a9-\symbola{c}aa-\symbola{T}ad-\ \symbola{9}c9-\symbola{<}d" ~ "1-\symbola{m}d2-\\"d3-\symbola{2}d4-`d5-'" marker ansimap := "aa-\\"ba-\symbola{2}b7-\symbola{7}e3-\symbola{c}" marker pcmap := "" marker pcamap := "" --------------------------------------------- -- table for \\'#, the hexadecimal character convention (we just use ASCII) marker hextran := "\\000\\001\\002\\003\\004\\005\\006\\007\\010\\011\\012\\013\\014\\015\\0\ 16\\017" ~ "\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\0\ 37" ~ "\\040\\041\\042\\043\\044\\045\\046\\047\\050\\051\\052\\053\\054\\055\\056\\0\ 57" ~ "\\060\\061\\062\\063\\064\\065\\066\\067\\070\\071\\072\\073\\074\\075\\076\\0\ 77" ~ "\\100\\101\\102\\103\\104\\105\\106\\107\\110\\111\\112\\113\\114\\115\\116\\1\ 17" ~ "\\120\\121\\122\\123\\124\\125\\126\\127\\130\\131\\132\\133\\134\\135\\136\\1\ 37" ~ "\\140\\141\\142\\143\\144\\145\\146\\147\\150\\151\\152\\153\\154\\155\\156\\1\ 57" ~ "\\160\\161\\162\\163\\164\\165\\166\\167\\170\\171\\172\\173\\174\\175\\176\\1\ 77" ~ "\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\2\ 17" ~ "\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\2\ 37" ~ "\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\2\ 57" ~ "\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\2\ 77" ~ "\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\3\ 17" ~ "\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\3\ 37" ~ "\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\3\ 57" ~ "\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\3\ 77" function printdump(msg, text) writefile ("/tmp/a", text) printline(msg) printline(system("cat /tmp/a")) end function --------------------------------------------- -- text manipulation -- SkipNewlines() -- advance CurrText beyond any initial newline or carriage return -- returns resulting first character of CurrText function SkipNewlines() while first(CurrText) = "\\n" or first(CurrText) = "\\r" do CurrText := rest(CurrText) end while return first(CurrText) end function -- SkipToUnmatchedRightBrace(after) -- skip text to next unmatched right brace -- if 'after' is True CurrText will begin after the brace, -- otherwise before -- deal with \\\{ and \\\} by skipping char after \\ function SkipToUnmatchedRightBrace(boolean after) marker brace integer cnt := 1 while cnt > 0 do brace := anyof(CurrText, "\{\}\\\\") CurrText := extent(finish(brace), CurrText) if CurrText = "" then exit function elif brace = "\\\\" then CurrText := rest(CurrText) elif brace = "\{" then cnt := cnt + 1 else cnt := cnt -1 end if end while if not after then CurrText := extent(previous(CurrText), CurrText) end if end function -- PeelControl(bs) -- bs refers to a \\ at the beginning of a control -- This function parses a control off CurrText -- and sets CurrText, CurrCtl, CurrRand, CurrRandValue -- returns major function code in ControlInterpretationTable function PeelControl(bs) integer neg := 1 marker t CurrCtl := extent(bs, span(finish(bs), Letters)) if CurrCtl = "\\\\" then -- must be a control symbol CurrCtl := extent(CurrCtl, next(CurrCtl)) CurrRand := "" CurrText := extent(finish(CurrCtl), CurrText) if CurrCtl = "\\\\*" then t := PeelControl(first(CurrText)) if t /= "" then return t end if -- ignore \\* CurrCtl := "\\\\*" -- replace unintelligible control group end if else CurrRand := span(finish(CurrCtl), "+-0123456789") if CurrRand /= "" then if first(CurrRand) = "-" then neg := -neg end if CurrRandValue := neg * parseint(token(CurrRand, "0123456789")) else CurrRandValue := 0 end if CurrText := extent(finish(CurrRand), CurrText) if front(CurrText) = " " then CurrText := rest(CurrText) end if end if return next(search(ControlInterpretationTable, CurrCtl ~ "-")) end function --------------------------------------------- -- font routines -- ParseOldFonttbl() -- some \\rtf0 files have a non-group format for fonttbls. -- Each font entry is text like: -- \\f1\\froman Times; -- the semicolon on the last entry is followed by a \} to match the one before \\fonttbl function ParseOldFonttbl() marker c := first(CurrText) marker tkey, font while c = "\\\\" do PeelControl(c) -- get font code: \\fnn if CurrCtl /= "\\\\f" then -- error: no \\f exit function end if tkey := CurrRand -- save nn c := SkipNewlines() if c /= "\\\\" then exit function end if -- error: no control for font family font := PeelControl(c) -- get font family: \\fnil, etc. if font /= "f" then exit function end if -- error, no font family FontTbl ~:= tkey ~ " ," replace (previous(last(FontTbl)), font) c := anyof(CurrText, ";\}\\\\") if c /= ";" then exit function end if -- error no font name CurrText := extent(finish(c), CurrText) c := SkipNewlines() end while end function -- ParseFontTbl() -- parses the \\fonttbl, building table in FontTbl -- assumes CurrText begins just after \\fonttbl -- Output is string containing sequence of "nnf," where nn is font number -- and f has the appropriate style -- We utilize the font family code and ignore the font name. function ParseFontTbl() marker c marker tkey, font c := SkipNewlines() if c /= "\{" then return ParseOldFonttbl() end if while c = "\{" do CurrText := rest(CurrText) c := SkipNewlines() if c /= "\\\\" then exit function end if -- error: no \\ for \\f tkey := PeelControl(c) -- get font code: \\fnn if CurrCtl /= "\\\\f" then -- error: no \\f exit function end if tkey := CurrRand -- save nn c := SkipNewlines() if c /= "\\\\" then exit function end if -- error: no control for font family font := PeelControl(c) -- get font family: \\fnil, etc. if font /= "f" then exit function end if -- error, no font family FontTbl ~:= tkey ~ " ," replace (previous(last(FontTbl)), font) SkipToUnmatchedRightBrace(True) -- skip fontname & \} c := SkipNewlines() end while end function -- GenerateFontSize(integer fs) -- fs is size in half points -- generate a character having a font size style setting of fs -- Algorithm: start with size 1 or 2 and advance with Bigger, Plus6, and Plus18 function GenerateFontSize(integer fs) marker s := copy("T") -- byte to be styled integer currsize := DEFAULTFONTSIZE -- convert to points by dividing by two. -- round extra half point to nearest even number. if fs % 4 = 3 then fs := fs + 1 elif fs % 4 = 1 then fs := fs -1 end if fs := fs / 2 if fs %2 = 1 then addstyles(s, "\min1{$}"); currsize := currsize - 1 end if while currsize > fs do addstyles(s, "\smaller{$}"); currsize := currsize - 2 end while while currsize+18 <= fs do addstyles(s, "\plus18{$}"); currsize := currsize + 18 end while while currsize+6 <= fs do addstyles(s, "\plus6{$}"); currsize := currsize + 6 end while while currsize+2 <= fs do addstyles(s, "\bigger{$}"); currsize := currsize + 2 end while return s end function --------------------------------------------- -- style routines -- RemoveStyles(style sts) -- remove from style the styles coded by sts function RemoveStyles(style, sts) marker m while sts /= "" do if first(sts) /= " " then m := search(style, first(sts)) if m /= "" then replace(extent(m, next(m)), "") end if end if sts := rest(sts) end while end function -- adjustindent() -- addstyles(target, code) enough times to come closer to the desired value integer function adjustindent(target, integer desired, code, integer val) integer times := desired / val if times < 0 then return desired end if -- opposite signs desired := desired - val * times while times > 0 do addstyles(target, code); times := times - 1 end while return desired end function function IndentUnits(style, code, integer first, integer second, integer third, integer fourth, integer fifth) -- convert twips to points and round to nearest 12 points integer desired := (CurrRandValue + 120) / 20 marker target RemoveStyles(style, code) style ~:= code ~ " " target := previous(last(style)) clearstyles(target) desired := adjustindent(target, desired, code, first) code := next(code) desired := adjustindent(target, desired, code, second) code := next(code) desired := adjustindent(target, desired, code, third) code := next(code) desired := adjustindent(target, desired, code, fourth) code := next(code) desired := adjustindent(target, desired, code, fifth) code := next(code) return style end function function RoundUnits(style, code, integer base) integer twips := base * 20; -- measurements are in points/20 if CurrRandValue < 0 then code := next(code) CurrRandValue := - CurrRandValue end if RemoveStyles(style, code) style ~:= code ~ " " CurrRandValue := CurrRandValue - twips*3/2 -- count first one and round while CurrRandValue > 0 do addstyles(previous(last(style)), code) CurrRandValue := CurrRandValue - twips end while return style end function -- ModifyStyle(code, style) -- Modify 'style' to have or remove the style of 'code' -- A CurrRand of 0 turns off the option if already in 'style'. -- Other numeric rands are ignored. -- If code is "$", the style is specially handled as coded by next(code): -- Q round to 12 points -- R round to 2 points -- U round to 2 points -- S \\s# search StyleSheet -- T \\fs# set font size -- f \\f# set font -- V \\ulnone undoes any underline -- W \\plain undoes \\b \\i \\f \\fs \\ul \\ulw \\uld \\uldb \\up \\dn " -- X \\pard sets style string to empty -- assumption, the styles are represented each with a unique byte function ModifyStyle(code, style) marker m code := next(code) if CurrRand /= "" and CurrRandValue = 0 then -- turn off the style if code = "$" then code := next(code) end if RemoveStyles(style, code) elif code /= "$" then RemoveStyles(style, code) style ~:= " " -- two blanks replace(previous(last(style)), code) else code := next(code) --printline("s$" ~ code) if code = "T" then -- \\fs RemoveStyles(style, "T") style ~:= " " -- two blanks replace(previous(last(style)), GenerateFontSize(CurrRandValue)) elif code = "f" then -- \\f RemoveStyles(style, "f") m := search(FontTbl, CurrRand) if m /= "" then style ~:= " " -- two blanks replace(previous(last(style)), next(m)) end if elif code = "S" then -- \\s -- change style to that found in StyleSheet m := search(StyleSheet, "\\\\" ~ CurrRand ~ "-") if m /= "" then m := finish(m) style := copy(extent(m, start(search(m, ",")))) --printdump("change to style \\\\s" ~ CurrRand, style) end if elif code = "P" then -- \\li \\ri round to 12 points style := IndentUnits(style, next(code), -36, 72, -12, 36, 12) elif code = "Q" then -- \\fi round to 12 points style := IndentUnits(style, next(code), -72, 36, -36, 12, -12) elif code = "R" then -- \\up \\dn round to 2 points style := RoundUnits(style, next(code), 2) elif code = "U" then -- \\sa \\sb \\sl 6, 12, or 24 points, but cancel for 0 code := next(code) RemoveStyles(style, code) if CurrRandValue /= 0 then if CurrRandValue >= 360 then -- 18 points or more, use 24 code := next(next(code)) elif CurrRandValue >= 180 then -- 9 points or more, use 12 code := next(code) else -- less than 9 points, use 6 end if style ~:= " " -- two blanks replace(previous(last(style)), code) end if elif code = "X" then -- \\pard style := newbase() elif code = "W" then -- \\plain RemoveStyles(style, "GHIJKLMNfT") elif code = "V" then -- \\ulnone RemoveStyles(style, "IJKL") end if end if return style end function -- ParseStyle() -- parse controls off the front of CurrText -- call ModifyStyle to append style definitions to style -- leave CurrText at the beginning of the style name -- Returns "\\snn," where nn is stylenum and is a style string -- for \\sbasedon, call ModifyStyle for each elt of the basis style -- (order of definition matters) function ParseStyle() marker stynum := "999" marker m, code, xcode marker style := newbase() while first(CurrText) = "\\\\" do code := PeelControl(first(CurrText)) xcode := extent(code, next(next(code))) if CurrCtl = "\\\\s" then stynum := CurrRand elif CurrCtl = "\\\\snext" and stynum = "999" then -- \\snext -- this is BOGUS, based on rule that \\snext gives -- own number if is the "last" XXX stynum := CurrRand elif CurrCtl = "\\\\sbasedon" then -- \\sbasedon m := search(StyleSheet, "\\\\" ~ CurrRand ~ "-") if m /= "" then m := copy(extent(next(m), start(search(finish(m), ",")))) RemoveStyles(m, style) -- remove styles already -- specified in 'style' style ~:= m -- printdump("basedon " ~ CurrRand, style) end if elif code = "s" then style := ModifyStyle(code, style) end if SkipNewlines() end while return "\\\\" ~ stynum ~ "-" ~ style ~ "," end function -- ParseStyleSheet() -- parse stylesheet, build StyleSheet value -- CurrText begins just after \\stylesheet function ParseStyleSheet() marker t t := SkipNewlines() while t = "\{" do CurrText := rest(CurrText) SkipNewlines() StyleSheet ~:= ParseStyle() SkipToUnmatchedRightBrace(True) -- skip style name & \} t := SkipNewlines() end while -- printdump("stylesheet", StyleSheet) end function -- ApplyStyle(tstart, tend, style) -- Apply style to extent(tstart, base(tend)) -- Return ref to tend -- function ApplyStyle(tstart, tend, style) marker subject subject := extent(tstart, base(tend)) if subject = "" then -- no text to be styled return finish(subject) end if while style /= "" do addstyles(subject, style) style := rest(rest(style)) end while return finish(subject) end function --------------------------------------------- -- Headers and Footers -- Every header and footer is included, but only the most recent of each -- will apply. Simplex printing is specified for header or footer. -- Duplex printing is specified for headerl, headerr, footerl, footerr. -- Each tab in the text separates one of the three parts of the title. -- (Maximum of two tabs). Styles are ignored. --Example input: -- \{\\footerl \\pard\\plain \\s243\\tqc\\tx4320\\tqr\\tx8640 -- \{\\f14\\fs20 Sun OS 4.0 Installation Procedures\\tab \\chdate -- \\tab Page \\chpgn \\par \}\} -- Example output (all wrapped in FormatNote) -- .duplex -- .\\" Footer -- .ds LB Sun OS 4.0 Installation Procedures -- .ds CB \\\\n(dy/\\\\n(mo/\\\\n(yr -- .ds RB \\\\n(PN -- -- ComputeExtremiter(text, footer) -- create lines for left, right, and center -- break text at tabs or newlines, using the non-blank segments -- 3 or more non-blank segs: use first three as L, C, and R -- 2 segs: L and R -- 1 seg: C function ComputeExtremiter(text, boolean footer) marker tab, segL, segC, segR, where integer nsegs := 0 while text /= ""and nsegs < 3 do tab := anyof(text, "\\t\\n") segR := extent(text, start(tab)) if segR /= "" then -- grab a seg nsegs := nsegs + 1 if nsegs = 1 then segL := segR elif nsegs = 2 then segC := segR end if end if -- skip tab text := extent(finish(tab), text) end while if nsegs = 1 then segC := segL; segL := ""; segR := "" elif nsegs = 2 then segC := "" elif nsegs = 0 then segC := ""; segL := ""; segR := "" end if if footer then where := "B " else where := "T " end if return (".ds L" ~ where ~ segL ~ "\\n") ~ (".ds C" ~ where ~ segC ~ "\\n") ~ (".ds R" ~ where ~ segR ~ "\\n") end function -- ~ "\\\\footer-qEfs,\\\\footerl-qEfd,\\\\footerr-qEfd," -- ~ "\\\\header-qEhs,\\\\headerl-qEhd,\\\\headerr-qEhd," function ParseExtremiter(code) boolean footer marker text := newbase() ~ "\\n" -- initial newline code := next(code) -- f or h footer := code = "f" code := next(code) -- to s or d if code = "d" then text ~:= ".duplex\\n" else text ~:= ".simplex\\n" end if if footer then text ~:= ".\\\\\\" Footer\\n" else text ~:= ".\\\\\\" Header\\n" end if text ~:= ComputeExtremiter(clearstyles(parseGroup("")), footer) if not footer then DefinedHeader := True elif footer and not DefinedHeader then -- undefine the standard header with page number at top text ~:= ".ds CT\\n" end if return addstyles(text, "\formatnote{%}") -- formatnote end function --------------------------------------------- -- Footnotes marker annotator := "" function parseEmbeddedObject(code) marker m, t, SaveState if next(code) = "A" then -- \\footnote -- m := copy("\footnote{\ \begindata{fnote,537826312} \textdsversion{12} \enddata{fnote,537826312} \view{fnotev,537826312,16,0,0} }") -- footnote object and two footnote blanks -- the above fails because all footnotes get the same object m := copy(" ") replacewithobject(first(m), new(class("fnote")), "fnotev") addstyles(m, "\footnote{\ \begindata{fnote,537826568} \textdsversion{12} \enddata{fnote,537826568} \view{fnotev,537826568,17,0,0}}") m := replace (previous(last(m)), clearstyles(parseGroup(""))) if first(m) = "\\n" then replace(first(m), "") end if replace(next(m), "") return base(m) elif next(code) = "C" then -- \\annotation. append (annotator) m := parseGroup("") if annotator /= "" then m := m ~ " (" ~ annotator ~ ")" end if annotator := "" addstyles(m, Hidden) return m elif next(code) = "D" then -- \\atnid. save author annotator := parseGroup("") return "" elif next(code) = "E" then -- \\field - minimal processing. -- convert page to \\chpgn or use \\fldrslt (if not \\fldpriv) -- ignore \\flddirty \\fldedit \\fldlock \\*\\fldinst m := CurrText SkipToUnmatchedRightBrace(False) m := extent(m, start(CurrText)) -- the contents of the \\field group if search(m, "page") /= "" then -- assume it is page number return "\formatnote{\\\\\\\\n(PN}" end if t := search(m, "\\\\fldrslt") if t /= "" then -- return contents of \\fldrslt SaveState := CurrText PeelControl(first(t)) -- sets CurrText m := parseGroup("") CurrText := SaveState return m end if return "" elif next(code) = "F" then -- xe text goes into document --(possibly hidden ala \\v) \\: -> : -- ignore \\bxe \\ixe \\rxe \\txe SaveState := Hidden Hidden := "\indexi{InvisibleIndex}" m := parseGroup("") if not hasstyles(m, Hidden) then addstyles(m, "\index{Index}") end if Hidden := SaveState return m elif next(code) = "G" then -- \\tc -- ATK entries for T/C are based on which style is chosen -- to implement this, we would have to choose which style -- sequences map to each ATK title style. -- For now we just include the text. return parseGroup("") else -- must be a pict, field, index entry, or tc entry SkipToUnmatchedRightBrace(False) return "" end if end function --------------------------------------------- -- Control and Block Processing -- MapHex() -- Do mapping for \\'xx -- First check CurrMap, then just generate the hex byte -- function MapHex() marker t marker m := next(CurrCtl) m := extent(m, next(m)) -- the two hex bytes CurrText := extent(finish(m), CurrText) t := search(CurrMap, m ~ "-") if t /= "" then return next(t) else return nextn(first(hextran), parseint("0x" ~ m)) end if end function function pageNFmt(fmt, fmtname) if currPageNFmt = fmt then return "" end if currPageNFmt := fmt return ".\\\\\\" format page number as " ~ fmtname ~ "\\n'af PN " ~ fmt end function function Pagination(code) marker t marker troff := newbase() -- printline("Pagination code " ~ code) if code = "a" then -- a-\\pgnstart# CurrRandValue := CurrRandValue + 1 -- kludge t := textimage(CurrRandValue) troff ~:= "\\n.\\\\\\" set page number to " ~ t ~ "\\n'pn " ~ t pageNumberSupplied := True elif code = "b" then -- b-\\pgnstarts# CurrRandValue := CurrRandValue + 1 -- kludge sectFirstPageNum := CurrRandValue return "" elif code = "c" then -- c-\\pgnrestart -- it is incorrect to output the new page number here, -- but it works since pgnrestart is only given -- at the beginning of a section restartpgnumpersect := True t := textimage(sectFirstPageNum) troff := pageNFmt("1", "decimal") ~ ".\\\\\\" reset page number for new section to " ~ t ~ "\\n'pn " ~ t pageNumberSupplied := True elif code = "d" then -- \\pgncont restartpgnumpersect := False return "" elif code = "e" then -- \\pgnucrm troff := pageNFmt("I", "upper case roman") elif code = "f" then -- \\pgnlcrm troff := pageNFmt("i", "lower case roman") elif code = "g" then -- \\pgnucltr troff := pageNFmt("A", "upper case letter") elif code = "h" then -- \\pgnlcltr troff := pageNFmt("a", "lower case letter") elif code = "i" then -- \\pgndec troff := pageNFmt("1", "decimal") elif code = "j" then -- \\sect: add newline or page break -- and perhaps restart page numbers if not restartpgnumpersect then if sectBreakPage then return copy("\\f") else return "" end if end if t := textimage(sectFirstPageNum) troff := "\\n.\\\\\\" set page number for new section to " ~ t ~ "\\n'pn " ~ t pageNumberSupplied := True if sectBreakPage then troff := "\\f" ~ troff end if elif code = "k" then -- \\sectd -- reset all section styles (we only have those for pagination) sectBreakPage := True restartpgnumpersect := False sectFirstPageNum := 1 -- assume we just had a \\sect, so we reformat page numbers troff := pageNFmt("1", "decimal") elif code = "l" then -- \\sbknone sectBreakPage := False return "" elif code = "m" then -- \\sbkcol \\sbkpage \\sbkeven \\sbkodd -- all set page break before section sectBreakPage := True return "" elif code = "p" then -- \\page return copy("\\f") -- signal to do page break before next text end if if troff = "" or troff = "\\n" then return "" end if return addstyles(troff ~ "\\n", "\formatnote{FormatNote}") end function -- parseDocumentControl(code) -- major function code "q" -- process a group with a block code -- each function called to handle a group -- leaves its trailing \} on the front of CurrText function parseDocumentControl(code) marker m --printline("parseDocumentControl " ~ CurrCtl ~ CurrRand) code := next(code) if code = "*" then -- \\* ignorable destination SkipToUnmatchedRightBrace(False) elif code = "P" then -- page numbering options return Pagination(next(code)) elif code = "R" then --\\rtf -- fine, accept rtf XXX probably should check CurrRand elif code = "F" then -- \\fonttbl ParseFontTbl() elif code = "S" then -- \\stylesheet ParseStyleSheet() elif code = "E" then -- \\header or \\footer return ParseExtremiter(code) elif code = "I" then -- \\info (make it hidden) m := CurrText SkipToUnmatchedRightBrace(False) m := copy(extent(m, start(CurrText))) return addstyles(m, Hidden) elif code = "C" then -- \\mac \\pc \\ansi \\pca -- map characters code := next(code) if code = "A" then CurrMap := macmap elif code = "B" then CurrMap := pcmap elif code = "C" then CurrMap := ansimap elif code = "D" then CurrMap := pcamap end if else -- skip all others SkipToUnmatchedRightBrace(False) end if return "" end function boolean NewPage := False -- kludge return value from AppendTo -- AppendTo(target, src, pagewanted, hadtext) -- specialized version of ~:= to avoid a bug in styles -- if pagewanted is true and the src is non-empty, -- set NewPage and generate a page break if hadtext is True function AppendTo(target, src, boolean pagewanted, boolean hadtext) -- printline("Append: " ~ src ~ " " ~ textimage(pagewanted) ~ " " ~ textimage(hadtext)) if pagewanted and src /= "" then NewPage := True -- tell parsegroup to turn off pagewanted target ~:= " " if hadtext then replace(last(target), PageBreak) elif pageNumberSupplied then replace(last(target), ".\\\\\\" increment page number for inital page break\\n" ~ "\formatnote{'pn \\\\n%+1\\n}") end if pageNumberSupplied := False end if target ~:= " " replace (last(target), src) return base(target) end function -- parseGroup(CurrStyle) -- parses the text in CurrText, using the argument as the base style -- returns the translated text -- -- the input is a sequence of operators and blocks -- where an operator begins with \\ and a block begins with \{ -- spaces and newlines are ignored -- some blocks are control blocks, others are text blocks, -- depending on the first operator in the block -- The AppendTo function is used instead of ~:= to avoid -- a bug in ATK styles code. -- The "\}" which terminates the group is left on the front of CurrText. -- function parseGroup(CurrStyle) marker c, t, func, OutText, TStart, StyleStack boolean pagePending := False boolean hadText := False integer depth := 0 OutText := newbase() TStart := OutText StyleStack := "" CurrStyle := copy(CurrStyle) while CurrText /= "" do c := anyof(CurrText, "\{\}\\n\\r\\\\") t := extent(CurrText, start(c)) if t /= "" then OutText := AppendTo(OutText, t, pagePending, hadText) hadText := True end if CurrText := extent(finish(c), CurrText) if NewPage then PagePending := False NewPage := False end if if c = "\{" then -- OutText := AppendTo(OutText, parseGroup(CurrStyle)) -- CurrText := rest(CurrText) -- discard "\}" -- instead of explicitly recurring, we push -- (this avoids copying OutText) TStart := ApplyStyle(TStart, OutText, CurrStyle) depth := depth + 1 StyleStack := CurrStyle ~ ";" ~ StyleStack elif c = "\}" then -- we are finished, at least at this level of nesting if depth <= 0 then CurrText := extent(c, CurrText) -- keep the "\}" exit while else TStart := ApplyStyle(TStart, OutText, CurrStyle) -- pop depth := depth - 1 c := search(StyleStack, ";") CurrStyle := copy(extent(StyleStack, start(c))) StyleStack := extent(finish(c), StyleStack) end if elif c = "\\\\" then func := PeelControl(c) -- printline(CurrCtl ~ ": " ~ func) if func = "s" then -- style change TStart := ApplyStyle(TStart, OutText, CurrStyle) CurrStyle := ModifyStyle(func, CurrStyle) -- printline("New style : " ~ CurrStyle) elif func = "r" then -- replace control with text OutText := AppendTo(OutText, extent(next(func), start(search(finish(func), ","))), pagePending, hadText) elif func = "p" then -- footnote (or pict) TStart := ApplyStyle(TStart, OutText, CurrStyle) OutText := AppendTo(OutText, parseEmbeddedObject(func), pagePending, hadText) TStart := finish(OutText) elif func = "m" then -- \\'xx hex code to map. must unset font if search(CurrStyle, "f") /= "" then t := copy(CurrStyle) RemoveStyles(t, "f") TStart := ApplyStyle(TStart, OutText, CurrStyle) OutText := AppendTo(OutText, MapHex(), pagePending, hadText) TStart := ApplyStyle(TStart, OutText, t) else OutText := AppendTo(OutText, MapHex(), pagePending, hadText) end if elif func = "q" then -- major block or document format TStart := ApplyStyle(TStart, OutText, CurrStyle) t := parseDocumentControl(func) if first(t) = "\\f" then PagePending := True -- t := rest(t) -- fails due to bug in styles replace(first(t), "") end if if first(t) = "\\n" and (last(OutText) = "\\n" or OutText ="") then -- t := rest(t) -- fails due to bug in styles replace(first(t), "") end if OutText := AppendTo(OutText, t, False, hadText) TStart := finish(OutText) else -- ignore other controls end if else -- c = "\\n" or c = "\\r" then -- skip newline or carriage return end if if NewPage then PagePending := False NewPage := False end if end while ApplyStyle(TStart, OutText, CurrStyle) return base(OutText) end function --------------------------------------------- -- central conversion routine -- convert(s) -- Initialize global variables and parse the input by calling parsegroup. -- ParseGroup ends leaving CurrText starting with the trailing "\}" -- Convert continues processing if there is more CurrText and the -- "\}" is not followed by a zero byte. -- function convert(s) marker t := newbase() -- init globals StyleSheet := newbase() FontTbl := newbase() CurrMap := ansimap DefinedHeader := False if first(s) = "\{" then s := rest(s) end if CurrText := s while CurrText /= "" and first(CurrText) /= "\\000" do t := AppendTo (t, parseGroup(""), False, True) CurrText := rest(CurrText) -- skip "\}" end while return base(t) end function -------------------------------------------------- -- the following provide the four different methods of invoking conversion -- this function can be called from other Ness scripts function fromrtf_to_atk(t) return convert(t) end function -- this function can be called from the 'Ness:' prompt function fromrtf_convert() marker s := currentselection(defaulttext) replace (s, convert(s)) end function -- add an item to the menu for all "textview" objects extend "view:textview" on menu "RTF to ATK" marker s := currentselection(defaulttext) replace (s, convert(s)) end menu end extend -- this main function executes if this file is invoked with nessrun function main(args) marker filename, outname, ext, m, text, outtext filename := token(args, Letters ~ "./_0123456789") ext := filename while ext /= "" do m := anyof (ext, "./") if m = "" then exit while else ext := extent(next(m), ext) end if end while -- now ext is the extension if preceded by "." if ext = "" then printline("You must supply a filename as argument.") exit function elif previous(ext) = "." and ext /= "d" then outname := extent(filename, start(ext)) ~ "d" else outname := filename ~ ".d" end if text := readfile(filename) if text = "" then printline("empty input file: " ~ filename) exit function end if m := search(text, "\{\\\\rtf") if m = "" then printline("Input file does not contain \\"\{\\\\rtf\\"") exit function end if printline("fromrtf(" ~Version ~ "): " ~ filename ~ " -> " ~ outname) outtext := convert(extent(m, text)) if match(system("if test -f "~outname ~ ";" ~ "then mv " ~ outname ~ " " ~ outname ~ ".BAK;" ~ "echo moved;fi"), "moved") /= "" then printline("Moved old " ~ outname ~ " to " ~ outname ~ ".BAK") end if writefile(outname, outtext) end function -- \begindata{bp,537558784} \enddata{bp,537558784} \view{bpv,537558784,19,0,0} -- Copyright 1992 Carnegie Mellon University and IBM. All rights reserved. \smaller{\smaller{-- $Disclaimer: -- Permission to use, copy, modify, and distribute this software and its -- documentation for any purpose is hereby granted without fee, -- provided that the above copyright notice appear in all copies and that -- both that copyright notice, this permission notice, and the following -- disclaimer appear in supporting documentation, and that the names of -- IBM, Carnegie Mellon University, and other copyright holders, not be -- used in advertising or publicity pertaining to distribution of the software -- without specific, written prior permission. -- -- IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS -- DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT -- SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER -- BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -- DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -- ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -- OF THIS SOFTWARE. -- $ }}\enddata{text,538268692}