diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml index 6c122ebc54..c139b35660 100644 --- a/.github/workflows/link-check.yml +++ b/.github/workflows/link-check.yml @@ -11,7 +11,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Link check with lychee (non-blocking) - uses: lycheeverse/lychee-action@v2.0.2 + uses: lycheeverse/lychee-action@v2.8.0 with: # Limit concurrency and accept 429 (rate-limited) as non-fatal args: >- diff --git a/Build/SilVersions.props b/Build/SilVersions.props index de5e0cd9da..e99438cac3 100644 --- a/Build/SilVersions.props +++ b/Build/SilVersions.props @@ -12,7 +12,7 @@ ============================================================= --> - 11.0.0-beta0156 + 11.0.0-beta0158 17.0.0 6.0.0-beta0063 3.7.13 diff --git a/Build/Src/FwBuildTasks/FwBuildTasks.csproj b/Build/Src/FwBuildTasks/FwBuildTasks.csproj index ca96a9f190..8a6ccaba5c 100644 --- a/Build/Src/FwBuildTasks/FwBuildTasks.csproj +++ b/Build/Src/FwBuildTasks/FwBuildTasks.csproj @@ -21,12 +21,12 @@ false - - + + - - - + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 7c13c8d7af..c9d4649642 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -25,20 +25,20 @@ - + - + - + - + - - + + - + diff --git a/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.props b/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.props new file mode 100644 index 0000000000..f23b00e175 --- /dev/null +++ b/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.props @@ -0,0 +1,26 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + /home/dependabot/dependabot-updater/repo/packages + /home/dependabot/dependabot-updater/repo/packages + PackageReference + 7.0.0 + + + + + + + + + + + + + + /home/dependabot/dependabot-updater/repo/packages/sil.buildtasks/3.2.0 + + \ No newline at end of file diff --git a/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.targets b/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.targets new file mode 100644 index 0000000000..6f260c202e --- /dev/null +++ b/Obj/FwBuildTasks/FwBuildTasks.csproj.nuget.g.targets @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Src/views/Test/TestVwTextBoxes.h b/Src/views/Test/TestVwTextBoxes.h index bc278f8ef6..a53e100ca9 100644 --- a/Src/views/Test/TestVwTextBoxes.h +++ b/Src/views/Test/TestVwTextBoxes.h @@ -61,6 +61,45 @@ namespace TestViews IPicturePtr m_qPicture; }; + // View constructor that displays a single string inside a concordance paragraph. + // The keyword region (ichMin..ichLim) is aligned at dmpAlign. + // If textAlign is set to ktalRight, the paragraph gets right alignment so that + // DoSpecialAlignment uses the right edge of the keyword for positioning. + class ConcParaVc : public DummyBaseVc + { + public: + int m_ichMinItem; + int m_ichLimItem; + int m_dmpAlign; + int m_textAlign; // ktalLeft or ktalRight + + ConcParaVc(int ichMin, int ichLim, int dmpAlign, int textAlign) + : m_ichMinItem(ichMin), m_ichLimItem(ichLim), + m_dmpAlign(dmpAlign), m_textAlign(textAlign) + { + } + + STDMETHOD(Display)(IVwEnv * pvwenv, HVO hvo, int frag) + { + pvwenv->put_IntProperty(ktptAlign, ktpvEnum, m_textAlign); + pvwenv->OpenConcPara(m_ichMinItem, m_ichLimItem, + (VwConcParaOpts)kcpoDefault, m_dmpAlign); + pvwenv->AddStringProp(kflidStTxtPara_Contents, NULL); + pvwenv->CloseParagraph(); + return S_OK; + } + STDMETHOD(EstimateHeight)(HVO hvo, int frag, int dxAvailWidth, int * pdyHeight) + { + *pdyHeight = 20; + return S_OK; + } + STDMETHOD(LoadDataFor)(IVwEnv * pvwenv, HVO * prghvo, int chvo, HVO hvoParent, + int tag, int frag, int ihvoMin) + { + return S_OK; + } + }; + class TestVwParagraphBox : public unitpp::suite { // Maximum number of previous strings to add before testing strings @@ -1207,6 +1246,68 @@ namespace TestViews } } + // Helper: lay out a single concordance paragraph and return the Left() of its first child box. + // The paragraph contains the given string with keyword at ichMin..ichLim aligned at dmpAlign. + int LayoutConcParaAndGetFirstBoxLeft(const OLECHAR * pszText, int cch, + int ichMin, int ichLim, int dmpAlign, int textAlign) + { + HVO hvoPara = 1; + ITsStringPtr qtss; + CheckHr(m_qtsf->MakeStringRgch(pszText, cch, g_wsEng, &qtss)); + CheckHr(m_qcda->CacheStringProp(hvoPara, kflidStTxtPara_Contents, qtss)); + + IVwViewConstructorPtr qvc; + qvc.Attach(NewObj ConcParaVc(ichMin, ichLim, dmpAlign, textAlign)); + m_qrootb->SetRootObject(hvoPara, qvc, 1, NULL); + HRESULT hr = m_qrootb->Layout(m_qvg32, 300); + unitpp::assert_true("ConcPara layout succeeded", hr == S_OK); + + VwParagraphBox * ppbox = dynamic_cast(m_qrootb->FirstBox()); + unitpp::assert_true("Root contains a paragraph box", ppbox != NULL); + VwBox * pFirstChild = ppbox->FirstBox(); + unitpp::assert_true("Paragraph has a child box", pFirstChild != NULL); + + int result = pFirstChild->Left(); + + // Clean up so we can reuse the root box + m_qrootb->Close(); + VwRootBox::CreateCom(NULL, IID_IVwRootBox, (void **) &m_qrootb); + m_qrootb->putref_DataAccess(m_qsda); + m_qrootb->putref_RenderEngineFactory(m_qref); + m_qrootb->putref_TsStrFactory(m_qtsf); + m_qrootb->SetSite(m_qdrs); + + return result; + } + + // Tests that DoSpecialAlignment uses the right edge of the keyword + // when the paragraph alignment is ktalRight, and the left edge when + // the alignment is ktalLeft. These should produce different box positions + // because the keyword has nonzero width. + void testConcParaAlignment_RightVsLeftEdge() + { + // Use a string where the keyword ("keyword") is in the middle. + // "Before keyword after end" - keyword at positions 7..14 + const OLECHAR text[] = L"Before keyword after end"; + int cch = (int)wcslen(text); + int ichMin = 7; // start of "keyword" + int ichLim = 14; // end of "keyword" + int dmpAlign = 36000; // 0.5 inch alignment point + + int leftWithLeftAlign = LayoutConcParaAndGetFirstBoxLeft( + text, cch, ichMin, ichLim, dmpAlign, ktalLeft); + int leftWithRightAlign = LayoutConcParaAndGetFirstBoxLeft( + text, cch, ichMin, ichLim, dmpAlign, ktalRight); + + // With left alignment, the left edge of "keyword" is placed at dmpAlign. + // With right alignment, the right edge of "keyword" is placed at dmpAlign. + // Since the keyword has nonzero width, the first child box should be + // shifted further left in the right-aligned case (by the width of the keyword). + unitpp::assert_true( + "Right-aligned conc para should shift boxes further left than left-aligned", + leftWithRightAlign < leftWithLeftAlign); + } + public: TestVwParagraphBox(); diff --git a/Src/views/VwTextBoxes.cpp b/Src/views/VwTextBoxes.cpp index 91a036c915..c3c55766dd 100644 --- a/Src/views/VwTextBoxes.cpp +++ b/Src/views/VwTextBoxes.cpp @@ -10055,7 +10055,11 @@ void VwConcParaBox::DoSpecialAlignment(IVwGraphics * pvg) return; // ignore any problems here, just don't align. } - int dxsAlign = rgxdLefts[0] + psbox->Left(); + int dxsAlign; + if (Style()->ParaAlign() == ktalRight) + dxsAlign = rgxdRights[cxd - 1] + psbox->Left(); + else + dxsAlign = rgxdLefts[0] + psbox->Left(); int dxsGoalAlign = MulDiv(m_dmpAlign, dxsInch, kdzmpInch); int dxsAdjust = dxsGoalAlign - dxsAlign; // Now adjust all the box lefts by this amount