Full operating system font support.

This commit is contained in:
Justin Marshall
2026-08-06 13:49:53 -07:00
parent 8932607951
commit 27a2f60cd1
17 changed files with 1219 additions and 66 deletions
+4
View File
@@ -988,3 +988,7 @@ add_test(NAME opus_word1_selection_test
COMMAND $<TARGET_FILE:opus_word1_ui_test> $<TARGET_FILE:WORD1> --selection
)
set_tests_properties(opus_word1_selection_test PROPERTIES TIMEOUT 20)
add_test(NAME opus_word1_font_typing_test
COMMAND $<TARGET_FILE:opus_word1_ui_test> $<TARGET_FILE:WORD1> --font-typing
)
set_tests_properties(opus_word1_font_typing_test PROPERTIES TIMEOUT 20)
+33 -3
View File
@@ -807,9 +807,17 @@ LOGFONT *plf;
int fPrinterFont;
{ /* Translate an FCID into a windows logical font request structure */
int ps;
int ibstFont;
struct FFN *pffn;
SetBytes(plf, 0, sizeof(LOGFONT));
#ifdef OPUS_X64
/* Word's selection engine deliberately XOR-inverts rendered glyphs.
ClearType's per-channel subpixels turn into colored fringes under that
operation, so request grayscale antialiasing for screen fonts. */
if (!fPrinterFont)
plf->lfQuality = 4; /* ANTIALIASED_QUALITY */
#endif
/* Scale the request into device units */
@@ -824,11 +832,33 @@ int fPrinterFont;
screen fonts, use positive lfHeight, meaning choose the font by
CELL height instead of CHARACTER height.
ChrisLa says this fiasco is Aldus' fault. */
if (fcid.ibstFont != ibstCourier || fPrinterFont)
ibstFont = (int)fcid.ibstFont;
if (ibstFont != ibstCourier || fPrinterFont)
plf->lfHeight = -plf->lfHeight;
Assert( fcid.ibstFont < (*vhsttbFont)->ibstMac );
pffn = PstFromSttb( vhsttbFont, fcid.ibstFont );
#ifdef OPUS_X64
/* A damaged or partially converted document font map must not turn a
failed STTB lookup into a null dereference in GDI setup. Use Word's
default master font entry as the recoverable display fallback. */
if (vhsttbFont == hNil || *vhsttbFont == NULL)
{
plf->lfPitchAndFamily = fcid.prq;
plf->lfCharSet = DEFAULT_CHARSET;
return fTrue;
}
if (ibstFont < 0 || ibstFont >= (*vhsttbFont)->ibstMac)
ibstFont = ibstFontDefault;
#endif
Assert( ibstFont < (*vhsttbFont)->ibstMac );
pffn = PstFromSttb( vhsttbFont, ibstFont );
#ifdef OPUS_X64
if (pffn == NULL)
{
plf->lfPitchAndFamily = fcid.prq;
plf->lfCharSet = DEFAULT_CHARSET;
return fTrue;
}
#endif
/* bits 0-1: pitch request
bits 4-6: font family */
plf->lfPitchAndFamily = (pffn->ffid & maskFfFfid) | fcid.prq;
+8 -8
View File
@@ -78,15 +78,15 @@ union FCID
struct
{
/* wProps */
int fBold: 1; /* bold, italics in same position as chp */
int fItalic: 1;
int fStrike: 1;
int kul: 3;
int prq: 2; /* pitch request */
int hps: 8;
unsigned int fBold: 1; /* bold, italics in same position as chp */
unsigned int fItalic: 1;
unsigned int fStrike: 1;
unsigned int kul: 3;
unsigned int prq: 2; /* pitch request */
unsigned int hps: 8;
/* wExtra */
int ibstFont: 8; /* index into master font table */
int : 8;
unsigned int ibstFont: 8; /* index into master font table */
unsigned int : 8;
};
};
+4 -1
View File
@@ -1140,7 +1140,10 @@ IBDlgLoop()
KME * pkme;
pkme = PkmeOfKcInChain(KcModified(vmsgLast.wParam & 0xff));
if (pkme->kt == ktMacro)
/* A printable key need not be present in the command key map.
The 16-bit build happened to tolerate the resulting nil pointer;
Win64 does not. Only inspect the entry when one was found. */
if (pkme != NULL && pkme->kt == ktMacro)
{
HDLG hdlgFocus = HdlgGetFocus();
HDLG hdlgOld = HdlgSetCurDlg(hdlgFocus);
+15
View File
@@ -1652,6 +1652,9 @@ WORD iibb;
WORD wParam;
LONG lParam;
{
#ifdef OPUS_X64
extern void OpusX64TraceRibbon();
#endif
switch (ibm)
{
case ibmDblClk:
@@ -1685,6 +1688,12 @@ LONG lParam;
int ftc = ValGetIibbHwndIb(hwnd, IDLKSFONT);
int hps = ValGetIibbHwndIb(hwnd, IDLKSPOINT);
#ifdef OPUS_X64
OpusX64TraceRibbon("original-term", ibm, iibb, ftc, hps,
(long)selCur.cpFirst, (long)selCur.cpLim,
selCur.fIns);
#endif
Assert (vssc == sscNil);
if (ftc >= 0)
{
@@ -1699,6 +1708,12 @@ LONG lParam;
if (cch > 0)
{
ApplyGrpprlSelCur(grpprl, cch, fTrue);
#ifdef OPUS_X64
OpusX64TraceRibbon("original-applied", ibm, cch,
selCur.chp.ftc, selCur.chp.hps,
(long)selCur.cpFirst, (long)selCur.cpLim,
selCur.fIns);
#endif
if (!vmerr.fMemFail)
FSetAgainGrpprl(grpprl, cch, bcmFormatting);
+76
View File
@@ -20,6 +20,9 @@ DEBUGASSERTSZ /* WIN - bogus macro for assert string */
#include "ruler.h"
#include "pic.h"
#include "error.h"
#ifdef OPUS_X64
#include <stdlib.h>
#endif
#ifdef MAC
#include "mac.h"
#include "toolbox.h"
@@ -967,6 +970,79 @@ WORD wParam;
return 0;
}
#ifdef OPUS_X64
/* Native SDM bridge. The historical parser expects a segmented SDM parse
object, which no longer exists on x64. Keep the actual Word font mapping
in this original module and expose flat-string adapters to the native
control layer. */
EXPORT int OpusX64FtcFromFontName(sz)
const char *sz;
{
int cch;
struct FFN *pffn;
char rgch[cbFfnLast];
pffn = (struct FFN *)rgch;
if (sz == NULL || *sz == '\0')
return wNinch;
if (CchSz(sz) > LF_FACESIZE - 1)
{
bltbyte(sz, pffn->szFfn, LF_FACESIZE - 1);
pffn->szFfn[LF_FACESIZE - 1] = '\0';
cch = LF_FACESIZE;
}
else
cch = CchCopySz(sz, pffn->szFfn);
cch = CchStripString(pffn->szFfn, cch);
if (cch == 0)
return wNinch;
return FtcValidateFont(pffn);
}
EXPORT int OpusX64HpsFromFontSize(sz)
const char *sz;
{
char *pchEnd;
double points;
int hps;
if (sz == NULL || *sz == '\0')
return wNinch;
points = strtod(sz, &pchEnd);
while (*pchEnd == ' ' || *pchEnd == '\t')
++pchEnd;
if (*pchEnd != '\0')
return wError;
hps = (int)(points * 2.0 + 0.5);
/* CHP stores the size in one unsigned byte. The original parser's
4..127 point range becomes 8..254 after conversion to half-points. */
if (hps < 8 || hps > 254)
return wError;
return hps;
}
EXPORT void OpusX64FontNameFromFtc(ftc, sz, cchMax)
int ftc;
char *sz;
int cchMax;
{
int ibst;
char *szFont;
if (sz == NULL || cchMax <= 0)
return;
*sz = '\0';
if (ftc == wNinch || selCur.doc == docNil)
return;
ibst = IbstFontFromFtcDoc(ftc, selCur.doc);
if (ibst == iNil)
return;
szFont = ((struct FFN *)PstFromSttb(vhsttbFont, ibst))->szFfn;
bltbyte(szFont, sz, min(CchSz(szFont), cchMax));
sz[cchMax - 1] = '\0';
}
#endif
#endif /* WIN */
+13
View File
@@ -208,6 +208,14 @@ TLV *ptlv;
CP cpLim;
CP dcp;
BOOL fSkipInval = fFalse;
#ifdef OPUS_X64
/* The fast insert path updates EDL character counts in place. That is
* insufficient when a newly committed character run has taller font
* metrics than the existing line: the old EDL height can survive until a
* later repaint and clip both this line and the lines below it. */
CP cpFirstCommitted = cpInsert;
int cchCommitted = ichInsert;
#endif
#ifdef WIN
int cchInsert;
#else /* MAC */
@@ -323,6 +331,11 @@ have to be updated */
#ifdef WIN
LSkipInval:
#ifdef OPUS_X64
if (fEnd && cchCommitted > 0 && cpFirstCommitted != cpNil)
InvalCp(PcaSetDcp(&caT, selCur.doc, cpFirstCommitted,
(CP)cchCommitted));
#endif
if (vfRecording && ptlv->fInsertLoop)
RecordInsert(ichInsert, ptlv);
if (vfRecordNext && (ptlv->fRecordBksp || fEnd))
+6
View File
@@ -754,7 +754,13 @@ get operate efficiently beyond the Eof */
#ifdef MAC
*(hpbFirst + sizeof(FC) + crun) = (!fWord3) ? (bCur / sizeof(int)) : bCur;
#else /* WIN */
/* The FKP byte stores an offset in 16-bit words. That is part of
* the document/scratch-page format, not the host C int width. */
#ifdef OPUS_X64
*(hpbFirst + sizeof(FC) + crun) = bCur >> 1;
#else
*(hpbFirst + sizeof(FC) + crun) = bCur / sizeof(int);
#endif
#endif /* WIN */
*((FC HUGE *)hpbFirst) = fcLim;
pfkpd->bFreeFirst += sizeof(FC) + 1;
+1 -1
View File
@@ -2345,7 +2345,7 @@ int cb;
/* given a prm return a pointer to the list of sprm (pgrpprl) and return
the length of the grpprl */
/* %%Function:PgrpprlFromPrm %%Owner:davidlu */
PgrpprlFromPrm(prm, pcb, grpprl)
char *PgrpprlFromPrm(prm, pcb, grpprl)
struct PRM prm;
int *pcb;
char *grpprl; /* user provided buffer for unloading sprm from piece table */
+10
View File
@@ -64,7 +64,16 @@ typedef long FC;
typedef unsigned PN; /* 512 byte page */
typedef unsigned PO; /* 128 byte page (Old page format) */
#ifdef OPUS_X64
/* The page-cache LRU clock was a wrapping Win16 word. Leaving TS as a
* native 32-bit unsigned value lets tsMruBps grow past tsMax (0xffff), after
* which no old cache page compares as eligible and the fallback can evict
* vibpProtect. That replaces the character page still referenced by
* vhpchFetch with an FKP formatting page during mixed-font line fetches. */
typedef unsigned short TS; /* TS = wrapping 16-bit time stamp */
#else
typedef unsigned TS; /* TS = time stamp */
#endif
typedef unsigned uns;
#ifndef OPUS_X64
@@ -828,6 +837,7 @@ CP CpFirstTap1();
CP CpTableFirst();
CP CpTableLim();
struct SEL *PselActive();
char *PgrpprlFromPrm();
CP CpSkipFormula();
CP CpScaleThumb();
struct PLC **HplcedlWw();
+144
View File
@@ -91,6 +91,11 @@ struct CA caPara;
struct CA caPage;
struct CA caSect;
struct CA caTable;
#ifdef OPUS_X64
extern struct FTI vfti;
extern char (**vhgrpchr)[];
extern int vbchrMac;
#endif
extern struct FCB **mpfnhfcb[];
extern int vfnPreload;
extern int vcPreload;
@@ -372,6 +377,10 @@ extern struct RF vrf;
extern BOOL vfInCommit;
extern int cbMemChunk;
extern struct BPTB vbptbExt;
#ifdef OPUS_X64
extern int vibp;
extern int vibpProtect;
#endif
extern int vgrfMenuKeysAreDirty;
extern BOOL vfEmptyMenu;
@@ -1590,6 +1599,141 @@ LONG lParam;
return LOWORD(wParam) == 47 ?
(LRESULT) edl.dlk : (LRESULT) edl.fEnd;
}
case 49: return (LRESULT) selCur.chp.ftc;
case 50: return (LRESULT) selCur.chp.hps;
case 51:
case 52:
{
CP cp = (CP) lParam;
if (cp < cp0 || cp >= CpMacDocEdit(selCur.doc))
return (LRESULT) -1;
FetchCp(selCur.doc, cp, fcmProps);
return LOWORD(wParam) == 51 ?
(LRESULT) vchpFetch.ftc : (LRESULT) vchpFetch.hps;
}
case 53:
return (LRESULT) IbstFontFromFtcDoc(selCur.chp.ftc,
selCur.doc);
case 54:
{
union FCID fcid;
fcid.lFcid = 0L;
fcid.ibstFont = (int)lParam;
return (LRESULT) fcid.ibstFont;
}
case 58:
return (LRESULT) sizeof(union FCID);
case 55:
case 56:
case 57:
InvalFli();
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
if (LOWORD(wParam) == 55)
return (LRESULT) vfli.dypLine;
if (LOWORD(wParam) == 56)
return (LRESULT) vfti.fcid.hps;
return (LRESULT) (vfti.dypAscent + vfti.dypDescent);
case 59:
case 60:
case 61:
case 62:
{
int bchr = 0;
int cchp = 0;
int hpsChpMax = 0;
int hpsFcidMax = 0;
int ichMax = 0;
InvalFli();
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
while (bchr < vbchrMac)
{
struct CHR *pchr =
(struct CHR *)&(**vhgrpchr)[bchr];
int cb = CbFromChrm(pchr->chrm);
if (cb <= 0 || cb > vbchrMac - bchr)
break;
if (pchr->chrm == chrmChp)
{
++cchp;
hpsChpMax = max(hpsChpMax,
(int)pchr->chp.hps);
hpsFcidMax = max(hpsFcidMax,
(int)pchr->fcid.hps);
ichMax = max(ichMax,
(int)(unsigned char)pchr->ich);
}
bchr += cb;
}
if (LOWORD(wParam) == 59) return (LRESULT) hpsChpMax;
if (LOWORD(wParam) == 60) return (LRESULT) hpsFcidMax;
if (LOWORD(wParam) == 61) return (LRESULT) cchp;
return (LRESULT) ichMax;
}
case 63:
InvalFli();
FormatLine(selCur.ww, selCur.doc, cp0);
if ((int)lParam < 0 || (int)lParam >= vfli.ichMac)
return (LRESULT) -1;
return (LRESULT) vfli.rgdxp[(int)lParam];
case 64:
case 65:
case 66:
case 67:
{
struct DR *pdr = PdrGalley(PwwdWw(WwFromHwnd(hwnd)));
CP cp = CpPlc(pdr->hplcedl, 0);
InvalFli();
FormatLineDr(selCur.ww, cp, pdr);
if (LOWORD(wParam) == 64)
{
if ((int)lParam < 0 || (int)lParam >= vfli.ichMac)
return (LRESULT) -1;
return (LRESULT) vfli.rgdxp[(int)lParam];
}
if (LOWORD(wParam) == 65) return (LRESULT) vfli.dxsInch;
if (LOWORD(wParam) == 66) return (LRESULT) vfli.dxuInch;
return (LRESULT) vfti.dxpInch;
}
case 68:
{
int ich = (int)HIWORD(wParam);
InvalFli();
FormatLine(selCur.ww, selCur.doc, (CP)lParam);
if (ich < 0 || ich >= vfli.ichMac)
return (LRESULT)-1;
return (LRESULT)(unsigned char)vfli.rgch[ich];
}
case 69:
{
CP cp = (CP)lParam;
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
return (LRESULT)-1;
FetchCp(selCur.doc, cp, fcmChars);
if (vccpFetch <= 0 || vhpchFetch == NULL)
return (LRESULT)-1;
return (LRESULT)(unsigned char)*vhpchFetch;
}
case 70:
{
CP cp = (CP)lParam;
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
return (LRESULT)-1;
FetchCp(selCur.doc, cp,
fcmChars + fcmProps + fcmParseCaps);
if (vccpFetch <= 0 || vhpchFetch == NULL)
return (LRESULT)-1;
return (LRESULT)(unsigned char)*vhpchFetch;
}
case 71:
{
CP cp = (CP)lParam;
if (cp < cp0 || cp >= CpMacDoc(selCur.doc))
return (LRESULT)-1;
FetchCp(selCur.doc, cp,
fcmChars + fcmProps + fcmParseCaps);
return (LRESULT)MAKELONG((WORD)vibpProtect,
(WORD)vibp);
}
}
return (LRESULT) -1;
#endif
+7 -5
View File
@@ -1,7 +1,9 @@
#pragma once
/*
* Compile-stage template boundary for Opus/dlg/char.des. The native SDM
* resource compiler/runtime will replace this descriptor during UI bring-up.
*/
DLG_CONST DLT dltCharacter = { 0 };
/* Regenerated header from Opus/dlg/char.des. The x64 SDM runtime consumes
the header and materializes the archived controls as native Win32 items. */
extern BOOL FDlgCharacter(DLM, TMC, WORD, WORD, WORD);
DLG_CONST DLT dltCharacter = {
{ 34, 38, 180, 152 }, IDDCharacter, tmcCharName, FDlgCharacter,
24, bdrSysMenu, { 0 }
};
+6 -5
View File
@@ -1,5 +1,6 @@
/*
* Compile-only boundary for Opus/dlg/edstyle.des. Regenerate the complete
* template with the ported historical dialog compiler before activation.
*/
DLG_CONST DLT dltDefineStyle = { 0 };
/* Regenerated header from Opus/dlg/edstyle.des. */
extern BOOL FDlgDefineStyle(DLM, TMC, WORD, WORD, WORD);
DLG_CONST DLT dltDefineStyle = {
{ 34, 18, 188, 101 }, IDDDefineStyle, tmcDSStyle, FDlgDefineStyle,
19, bdrSysMenu, { 0 }
};
@@ -12,6 +12,30 @@ extern "C" int WINAPI OpusOriginalWinMain(HINSTANCE instance,
HINSTANCE previous,
LPSTR command_line,
int show_command);
using OpusOriginalListProc = unsigned short (*)(
unsigned short, char*, int, unsigned short, unsigned short,
unsigned short);
using OpusFontValueProc = int (*)(const char*);
using OpusFontNameFromValueProc = void (*)(int, char*, int);
extern "C" unsigned short WListFontName(unsigned short, char*, int,
unsigned short, unsigned short,
unsigned short);
extern "C" unsigned short WListFontSize(unsigned short, char*, int,
unsigned short, unsigned short,
unsigned short);
extern "C" unsigned short WListStyles(unsigned short, char*, int,
unsigned short, unsigned short,
unsigned short);
extern "C" unsigned short Look1WListEntbl(unsigned short, char*, int,
unsigned short, unsigned short,
unsigned short);
extern "C" int OpusX64FtcFromFontName(const char*);
extern "C" int OpusX64HpsFromFontSize(const char*);
extern "C" void OpusX64FontNameFromFtc(int, char*, int);
extern "C" void OpusRegisterOriginalDialogCallbacks(
OpusOriginalListProc, OpusOriginalListProc, OpusOriginalListProc,
OpusOriginalListProc, OpusFontValueProc, OpusFontValueProc,
OpusFontNameFromValueProc);
namespace {
@@ -36,6 +60,22 @@ void BuildDiagnosticPath(const char* file_name, char* path, size_t path_size) {
file_name);
}
void ResetRibbonTrace() {
char trace_path[MAX_PATH] = {};
BuildDiagnosticPath("WORD1-ribbon.txt", trace_path, sizeof(trace_path));
HANDLE file = CreateFileA(trace_path, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) {
return;
}
char header[128] = {};
std::snprintf(header, sizeof(header), "WORD1 ribbon trace pid=%lu\r\n",
GetCurrentProcessId());
WriteCrashText(file, header);
CloseHandle(file);
}
void WriteCurrentStack(HANDLE file, unsigned frames_to_skip) {
void* frames[64] = {};
const USHORT frame_count =
@@ -334,6 +374,28 @@ LONG WINAPI ObserveVectoredException(EXCEPTION_POINTERS* exception) {
} // namespace
extern "C" void OpusX64TraceRibbon(const char* stage, int message, int tmc,
int first_value, int second_value,
long cp_first, long cp_limit,
int insertion) {
char trace_path[MAX_PATH] = {};
BuildDiagnosticPath("WORD1-ribbon.txt", trace_path, sizeof(trace_path));
HANDLE file = CreateFileA(trace_path, FILE_APPEND_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) {
return;
}
char line[384] = {};
std::snprintf(line, sizeof(line),
"%llu %s msg=%d tmc=%d a=%d b=%d sel=%ld,%ld ins=%d\r\n",
static_cast<unsigned long long>(GetTickCount64()),
stage != nullptr ? stage : "", message, tmc, first_value,
second_value, cp_first, cp_limit, insertion);
WriteCrashText(file, line);
CloseHandle(file);
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous,
PWSTR command_line, int show_command) {
if ((command_line != nullptr &&
@@ -345,6 +407,15 @@ int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous,
SetUnhandledExceptionFilter(WriteCrashStack);
AddVectoredExceptionHandler(1, ObserveVectoredException);
_RTC_SetErrorFuncW(WriteRtcFailure);
ResetRibbonTrace();
/* The native SDM shim owns the controls, while Microsoft's original
callbacks still own every font, point-size, color, and style list. */
OpusRegisterOriginalDialogCallbacks(WListFontName, WListFontSize,
WListStyles, Look1WListEntbl,
OpusX64FtcFromFontName,
OpusX64HpsFromFontSize,
OpusX64FontNameFromFtc);
char command_line_ansi[32768] = {};
if (command_line != nullptr) {
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -1,2 +1,6 @@
/* Template boundary for the original Opus/dlg/style.des description. */
DLG_CONST DLT dltApplyStyle = { 0 };
/* Regenerated header from Opus/dlg/style.des. */
extern BOOL FDlgApplyStyle(DLM, TMC, WORD, WORD, WORD);
DLG_CONST DLT dltApplyStyle = {
{ 32, 16, 150, 102 }, IDDApplyStyle, tmcASStyle, FDlgApplyStyle,
6, bdrSysMenu, { 0 }
};
+2 -2
View File
@@ -17,9 +17,9 @@
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">System</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>