/* * Help Access Library * A Library to access the contents of Windows Help files. * * Copyright (C) 1995-2000 Bernd Herd, http://www.herdsoft.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* PARA.C ------------------------------------------- * @doc * * @module PARA.C | * topic Paragraph enumeration * * Help Access Library Project. * *-----------------------------------------------------*/ #include #include #include #include #include #include #include "hlpacces.h" #include "top.h" void LOCAL nMciStatement(HTOPIC topic, TOPICENUMPROC fnenum, LPARAM lParam, LPBYTE String, char Align); /* RtfTopicParagraph -------------------------------------------* * Convert a Topic-String to a RTF-String... * *--------------------------------------------------------------*/ #pragma pack(1) typedef struct { // Description of a Bitmap or Embedded Window // BYTE V22; BYTE StatementType; // {ewx} 0x05 or {bwl} 0x22 LONG HeaderLength; // {ewx} Value Dependend on Length of String or {bwx} 08, Stored with Sign (iGetLongValue) WORD PrivateStringBytes; // 00:{ewx], 0x02-> Display Bitmap, 0x0e -> SHG BOOL WithData; // Bitmap stored with Data {bmlwd} (No reference to Baggage) WORD BitmapNumber; } PACKED BMX; #pragma pack() //-- Define paragraph attribute bits -- #define FORMATF_UNKNOWN0001 0x0001 // Unknown Format-Flag used by Media View 1.3 #define FORMATF_SB 0x0002 // Line-Spacing before Paragraph #define FORMATF_SA 0x0004 // Line-Spacing after Paragraph #define FORMATF_SL 0x0008 // Line-Spacing #define FORMATF_LEFT 0x0010 // Left Border value Exits #define FORMATF_RIGHT 0x0020 // Right Border value Exists #define FORMATF_LEFTFIRST 0x0040 // Left Border First exits #define FORMATF_BOX 0x0100 // \box-Statement: Attributes Follow... #define FORMATF_TABS 0x0200 // tab-Positions #define FORMATF_JUSTRIGHT 0x0400 //Right justified #define FORMATF_JUSTCENTER 0x0800 // Center justified #define FORMATF_NONWRAP 0x1000 // Non-wrapping text \keep #define CMD_FONT 0x80 #define CMD_LINE 0x81 #define CMD_PAR 0x82 #define CMD_TAB 0x83 #define CMD_POPUP30 0xe0 // Assumed to be a Pupup by Topic-Offset #define CMD_JUMP30 0xe1 // Assumed to be a Jump by Topic-Offset #define CMD_JUMP 0xe3 // Topic-Jump... #define CMD_JUMPHIDE 0xe7 // Hidden Jump \uldb (\v %.....) #define CMD_POPUPHIDE 0xe6 // Hidden Jump to Popup \ul (\v %.....) #define CMD_HOTSPOTEND 0x89 #define CMD_POPUP 0xe2 // Popup-Jump... #define CMD_POPUPINTER 0xea // Inter-File Popup #define CMD_POPUPHIDEINTER 0xee // Hidden Popup Inter-File ? 30.11.95 LZAPIART.HLP #define CMD_JUMPHIDEINTER 0xef // Hidden Jump Inter-File? 30.11.95 LZAPIART.HLP #define CMD_SECONDWIN 0xeb // Jump to secondary Window #define CMD_MACRO 0xc8 #define CMD_MACROHIDE 0xcc // Hotspot for a Macro with userdefined Font (\v %!) #define CMD_BMC 0x86 #define CMD_BML 0x87 #define CMD_BMR 0x88 #define CMD_NON_BREAKABLE_SPACE 0x8b // Encoding \~ used at least by media view library 1.4 #define CMD_END 0xff // Unknown... #define SMT_BMX 0x22 // Type of {...}-Statement is: BMX #define SMT_BMX30 0x03 // Type of {...[-Statemenz is: {bmx} for HC30 #define SMT_EWX 0x05 // Type of {...}-Statement is: ewx //-- Define border bytes -- #define BORDER_DOT 0x80 //Dotted border #define BORDER_DOUBLE 0x40 //Double border #define BORDER_THICK 0x20 //Thick border #define BORDER_RIGHT 0x10 //Right border #define BORDER_BOTTOM 0x08 //Bottom border #define BORDER_LEFT 0x04 //Left border #define BORDER_TOP 0x02 //Top border #define BORDER_BOX 0x01 //Boxed border #define JUMPF_WINDOWNUMBER 0x0001 // Jump Includes a Window-Number #define JUMPF_WINDOWNAME 0x0002 // Jump Includes a Window-Name #define JUMPF_FILENAME 0x0004 // Jump includes a File-Name /* nJump -------------------------------------------------------* * Creates a Jump-Reference * *--------------------------------------------------------------*/ LPCSTR LOCAL nJump( HTOPIC topic, TOPICENUMPROC fnenum, LPARAM lParam, BYTE Option, LPBYTE *FormatData, UINT *FormatLength) { LPCSTR Data = (LPCSTR) (*FormatData); LPSTR MacroString; WORD Flags = 0; BOOL IsPopup = FALSE, // Default: A Jump IsHidden = FALSE, IsInter = FALSE; // Is Inter-file reference UINT EntryBytes = 4; DWORD HashValue; BYTE WindowNumber; char *contextId = NULL; // ------------ Get additional Parameters (if any) ------- switch (Option) { case CMD_JUMPHIDEINTER: case CMD_POPUPHIDEINTER: case CMD_POPUPINTER: // Inter-File (Giving .HLP-Filename) Popup reference case CMD_SECONDWIN: // Jump to secondary Window. Additional Parameters: 3 Bytes Unknown purpose... // EntryBytes = (*((WORD FAR *) Data)++)+2; // Length of Jump Entry... EntryBytes = iGetLeWordValue(&Data, NULL)+2; Flags = *Data++; // Get Flag Bytes IsInter = TRUE; } // ----------- Pessimistic Test -------------------------- /* if (EntryBytes > *FormatLength) { HlpDisplayWarning(ifs, IDS_ILLHOTSPOT); return NULL; }*/ // ------------ Decide if pupop or Jump ------------------ switch (Option) { case CMD_POPUPINTER: case CMD_POPUP: case CMD_POPUP30: case CMD_POPUPHIDEINTER: case CMD_POPUPHIDE: IsPopup = TRUE; } // ------------ Ask for hidden Jumps --------------------- switch (Option) { case CMD_POPUPHIDE: case CMD_POPUPHIDEINTER: case CMD_JUMPHIDEINTER: case CMD_JUMPHIDE: IsHidden = TRUE; } // ---------- Get Hash Value (Always available) ---------- // HashValue = *( (DWORD *) Data)++; HashValue = iGetLeDWordValue(&Data, NULL); MacroString = (LPSTR) Hlpmalloc(1000); strcpy(MacroString, IsHidden ? "%" : ""); if (topic->contents) { contextId = iContentsFromHash(topic->contents, HashValue); } if (contextId) { strcat(MacroString, contextId); Hlpfree(contextId); } else { HlpCreateStringForHashValue(HashValue, MacroString+lstrlen(MacroString)); } // ---------- Secondary Window by Number ----------------- if (Flags & JUMPF_WINDOWNUMBER) { WindowNumber=*Data++; /* if (WindowNumber==0xff || WindowNumber < ifs->SecondaryWindowCount) sprintf(MacroString+strlen(MacroString), ">%s", WindowNumber == 0xff ? "main" : ifs->SecondaryWindowName[WindowNumber]); else HlpDisplayWarning(ifs, IDS_ILLWINDOW, WindowNumber); */ } // ---------- Secondary Window by Name ------------------- if (Flags & JUMPF_WINDOWNAME) { sprintf(MacroString+strlen(MacroString), ">%s", Data); Data+=strlen(Data)+1; } else if (IsPopup) { sprintf(MacroString+strlen(MacroString), ">popup", Data); } // ---------- Help-Filename ------------------------------ if (Flags & JUMPF_FILENAME) { sprintf(MacroString+strlen(MacroString), "@%s", Data); Data+=strlen(Data)+1; } // ---------- Step Forward ------------------------------- *FormatData += EntryBytes; *FormatLength -= EntryBytes; return MacroString; } /* nMciStatement -----------------------------------------------* * re-generate {mci ... } statement *--------------------------------------------------------------*/ void LOCAL nMciStatement(HTOPIC topic, TOPICENUMPROC fnenum, LPARAM lParam, LPBYTE String, char Align) { LPSTR cpy =(LPSTR) Hlpstrdup(String), DllName, ClassName, AuthorString; LPBYTE buf = (LPBYTE) Hlpcalloc(5000,1), ptr = buf, plus; WORD flags; if (NULL != (DllName = strtok(cpy , ",")) && NULL != (ClassName = strtok(NULL , ",")) && NULL != (AuthorString= strtok(NULL , ",")) ) { lstrcpy(buf, "{mci "); flags=atoi(DllName); if (flags & 8) lstrcat(buf, " nomenu"); if (flags & 2) lstrcat(buf, " noplaybar"); flags=atoi(ClassName); if (flags & 1) lstrcat(buf, " repeat"); if (flags & 2) lstrcat(buf, " play"); if (NULL==(plus=(LPBYTE) strchr(AuthorString,'+'))) { lstrcat(buf, " external"); plus=(LPBYTE) AuthorString; } else plus++; lstrcat(buf,","); lstrcat(buf,plus); lstrcat(buf,"}"); iTopicString(topic, fnenum, lParam, &ptr, NULL, TOPIC_MCI); } Hlpfree(cpy); Hlpfree(buf); } /* RtfTopicParagraph -------------------------------------------* * Write Text of a Topic as RTF-Output * *--------------------------------------------------------------*/ UINT iTopicParagraph(HTOPIC topic, TOPICENUMPROC fnenum, LPARAM lParam, BYTE **String, UINT *Length, BYTE **FormatData, UINT *FormatLength, DWORD TopicOffset, BOOL InNonScrollingRegion, BOOL InTable) { BYTE *more = *FormatData; UINT moreLength = *FormatLength; BYTE Byte1, Byte2; LPCSTR p; char Align; int Option, FontNo, TabCount, TabPos, i; FORMAT mFormat, *Format = &mFormat; DWORD HashValue; LPCSTR MacroString=NULL; LPSTR Pointer; BMX bmx; WORD Flags; char Temp[200]; UINT CharsWritten=0; # ifdef MVB int BorderFactor = ISMVCC(topic) ? 1 : 10; # else # define BorderFactor 10 # endif // -------- Get Format Structure ... --------------------- memset(&mFormat, 0, sizeof(mFormat)); Format->Zero = *more++; moreLength--; Format->EightZeroSecond = *more++; moreLength--; Format->Zero2 = iGetLeWordValue(&more, &moreLength); Format->Flags = iGetLeWordValue(&more, &moreLength); Flags = Format->Flags; iFormatString(topic, fnenum, lParam, InNonScrollingRegion ? "\\pard\\keepn\\s1" :"\\pard\\s0"); if (InTable) iFormatString(topic, fnenum, lParam, "\\intbl"); if (Flags & FORMATF_UNKNOWN0001) { int val1 = iGetShortValue(&more, &moreLength); int val2 = iGetShortValue(&more, &moreLength); HLPTRACE(("Unknown0001 val: %d %d\n", val1, val2)); } if (Flags & FORMATF_NONWRAP) iFormatString(topic, fnenum, lParam, "\\keep"); iFormatString(topic, fnenum, lParam, Flags & FORMATF_JUSTCENTER ? "\\qc" : Flags & FORMATF_JUSTRIGHT ? "\\qr" : "\\ql"); if (Flags & FORMATF_SB) iFormatString(topic, fnenum, lParam, "\\sb%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_SA) iFormatString(topic, fnenum, lParam, "\\sa%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_SL) { int slval = iGetShortValue(&more, &moreLength) * BorderFactor; iFormatString(topic, fnenum, lParam, "\\sl%d", slval); } // iFormatString(topic, fnenum, lParam, "\\sl%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_LEFT) iFormatString(topic, fnenum, lParam, "\\li%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_RIGHT) iFormatString(topic, fnenum, lParam, "\\ri%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_LEFTFIRST) iFormatString(topic, fnenum, lParam, "\\fi%d", iGetShortValue(&more, &moreLength) * BorderFactor); if (Flags & FORMATF_BOX) { Option = *more; if (Option & BORDER_DOT) iFormatString(topic, fnenum, lParam, "\\brdrl" ); /* if (Option & BORDER_RIGHT) iFormatString(topic, fnenum, lParam, "\\brdrr" ); if (Option & BORDER_BOTTOM) iFormatString(topic, fnenum, lParam, "\\brdrb" ); if (Option & BORDER_LEFT) iFormatString(topic, fnenum, lParam, "\\brdrbar"); if (Option & BORDER_TOP) iFormatString(topic, fnenum, lParam, "\\brdrt" ); if (Option & BORDER_BOX) iFormatString(topic, fnenum, lParam, "\\box" ); if (Option & BORDER_THICK) iFormatString(topic, fnenum, lParam, "\\brdrth" ); else iFormatString(topic, fnenum, lParam, "\\brdrs" );*/ p=(Option & BORDER_DOT) ? "\\brdrdot": (Option & BORDER_THICK) ? "\\brdrth" : "\\brdrs"; if (Option & BORDER_RIGHT) iFormatString(topic, fnenum, lParam, "\\brdrr%s", p); if (Option & BORDER_BOTTOM) iFormatString(topic, fnenum, lParam, "\\brdrb%s", p); if (Option & BORDER_LEFT) iFormatString(topic, fnenum, lParam, "\\brdrl%s", p); if (Option & BORDER_TOP) iFormatString(topic, fnenum, lParam, "\\brdrt%s", p); if (Option & BORDER_BOX) iFormatString(topic, fnenum, lParam, "\\box%s" , p); more +=3; moreLength-=3; } if (Flags & FORMATF_TABS) { TabCount = ( (*more++) & 0x7f) /2; moreLength--; for (i=0; iFlags & RTF_LOCALIZE) && ifs->LocalizeTextFile && !ifs->NewParagraph ) { ifs->NewParagraph=TRUE; fputc('\n', ifs->LocalizeTextFile); } # endif } break; case CMD_TAB : iFormatString(topic, fnenum, lParam, "\\tab "); p="\t"; iTopicString (topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_TEXT_CONTROL); break; case CMD_NON_BREAKABLE_SPACE: iFormatString(topic, fnenum, lParam, "\\~ "); p=" "; iTopicString (topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_TEXT_CONTROL); break; case CMD_FONT: Byte1 = *more++; Byte2 = *more++; FontNo = Byte1 +((WORD)Byte2 <<8); if (NULL!=(p=iFontsGetRtfSelection(topic, FontNo))) { if (MacroString && NULL != (Pointer=strstr(p, "\\ul"))) *Pointer=0; iFormatString(topic, fnenum, lParam, "%s ", p); Hlpfree(p); } /* if (FontNoFontSelectors->FontCount) { strcpy(Temp, ifs->FontSelectors->FontSelectString[FontNo]); if (MacroString && NULL != (Pointer=strstr(Temp, "\\ul"))) *Pointer=0; iFormatString(topic, fnenum, lParam, "%s ", Temp); HLPTRACE(("\\fontselection %s\n", Temp)); } // iFormatString(topic, fnenum, lParam, "%s ", ifs->FontSelectors->FontSelectString[FontNo]); else HlpDisplayWarning(ifs, IDS_ILLFONT); */ CharsWritten+=1; moreLength-=2; break; case CMD_POPUPINTER: // Inter-File (Giving .HLP-Filename) Popup reference case CMD_SECONDWIN: // Jump to secondary Window. Additional Parameters: 3 Bytes Unknown purpose... case CMD_POPUPHIDE: case CMD_POPUPHIDEINTER: case CMD_JUMPHIDE: case CMD_JUMPHIDEINTER: case CMD_POPUP: case CMD_JUMP30: case CMD_POPUP30: case CMD_JUMP: MacroString = nJump(topic, fnenum, lParam, Option, &more, &moreLength); CharsWritten+=2; p=(LPBYTE)MacroString; iTopicString (topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_HOTSPOT_START); break; case CMD_MACROHIDE: case CMD_MACRO://i = *((short FAR *) more)++; i = (short) iGetLeWordValue(&more, &moreLength); if (i>0) { MacroString = (LPSTR) Hlpmalloc(i+5); sprintf((LPSTR) MacroString, Option==CMD_MACROHIDE ? "%%!%s" : "!%s", more); // moreLength -= i+1; more += i; moreLength -= i; iFormatString(topic, fnenum, lParam, "\\strike "); p=(LPBYTE)MacroString; iTopicString (topic, fnenum, lParam, (LPBYTE *)&p, NULL, TOPIC_MACRO_HOTSPOT); } else HlpDisplayWarning(ifs, IDS_ILLMACROHOT); break; case CMD_HOTSPOTEND: if (MacroString) { iFormatString(topic, fnenum, lParam, "\\strike0\\ul0{\\v %s}", MacroString); p=(LPBYTE)MacroString; iTopicString (topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_HOTSPOT_END); Hlpfree(MacroString); MacroString=NULL; } else HlpDisplayWarning(ifs, IDS_HOTENDWOSTART); break; case CMD_BML: case CMD_BMR: case CMD_BMC: switch (Option) { case CMD_BML: Align='l'; break; case CMD_BMR: Align='r'; break; case CMD_BMC: Align='c'; break; } // ------- Get Bitmap definition Structure --------------- bmx.StatementType = *more++; --moreLength; bmx.HeaderLength = iGetLongValue(&more, &moreLength); bmx.PrivateStringBytes = (bmx.StatementType!=SMT_BMX30) ? iGetWordValue(&more, &moreLength) : 0; bmx.WithData = iGetLeWordValue(&more, &moreLength); if (bmx.WithData && bmx.StatementType==SMT_BMX) bmx.BitmapNumber = 0xffff; else bmx.BitmapNumber = iGetLeWordValue(&more, &moreLength); // (*DataOffsetAdd) += bmx.PrivateStringBytes; CharsWritten += bmx.PrivateStringBytes; switch (bmx.StatementType) { case SMT_BMX30: case SMT_BMX: // -------- Bitmap stored with Data ?! ------------------- if (bmx.WithData) { /* if (ifs->SecondPass) { static char *tempfilename = "emtmp$"; char szbmwd[15], szbmwdSaved[50]; FILE *em = fopen(tempfilename, "wb+"); fwrite(more, 1, bmx.HeaderLength-2, em); sprintf(szbmwd, "bmw%d", ifs->Bitmaps->BitmapCount); SHGDump(ifs, em, 0, bmx.HeaderLength-2, szbmwd, szbmwdSaved); fclose(em); unlink(tempfilename); bmx.BitmapNumber = ifs->Bitmaps->BitmapCount; HlpAddBitmapFileName(ifs, bmx.BitmapNumber, szbmwdSaved); } */ more += bmx.HeaderLength-2; moreLength -= bmx.HeaderLength-2; } // -------- Access the Bitmap ---------------------------- if (bmx.BitmapNumber != 0xffff) { char szbmx[50]; wsprintf(szbmx, ISV30(topic)?"{bm%c bm%d}" :"{bm%c |bm%d}", Align, bmx.BitmapNumber); p=(LPBYTE) szbmx; iTopicString(topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_BMX); } /* if (bmx.BitmapNumber != 0xffff) { if (bmx.BitmapNumber < ifs->Bitmaps->BitmapCount) RtfPutPicture(ifs, rtf, ifs->Bitmaps->BitmapFileName[bmx.BitmapNumber], Align, bmx.WithData); else HlpDisplayWarning(ifs, IDS_ILLBITMAP, bmx.BitmapNumber); } */ break; case SMT_EWX: more++; // ??? //------------ Windows 4.0 Button and mci are subsets of {ewx} coding --------- if (*more=='!') // a {button ...} - statement`? { p=more+1; iTopicString(topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_BUTTON); } else if (*more=='*') // a {mci ...} - statement`? nMciStatement(topic, fnenum, lParam, more+1, Align); // more complex coding else { iFormatString(topic, fnenum, lParam, "\\{ew%c ", Align); p=more; iTopicString(topic, fnenum, lParam, (LPBYTE*)&p, NULL, TOPIC_EWX); iFormatString(topic, fnenum, lParam, "\\}"); // iFormatString(topic, fnenum, lParam, "\\{ew%c %s\\}", Align, more); } moreLength-=strlen(more)+2; more +=strlen(more)+1; } break; default: HLPTRACE(("\n|%02x:%dmoreLength| unknown\n", (BYTE) Option, moreLength)); } } if (moreLength) moreLength--; CharsWritten += iTopicString(topic, fnenum, lParam, String, Length, TOPIC_TEXT)+1; *FormatData = more; *FormatLength = moreLength; return CharsWritten; } // iTopicParagraph