Erste funktionierende Version

This commit is contained in:
2026-07-01 11:16:02 +02:00
parent 0544fc88c2
commit f43915c29f
10 changed files with 517 additions and 95 deletions
-63
View File
@@ -1,63 +0,0 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
+18
View File
@@ -7,9 +7,27 @@
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ForceDesignerDPIUnaware>true</ForceDesignerDPIUnaware>
<ImplicitUsings>disable</ImplicitUsings>
<StartupObject>BonNotiz.Program</StartupObject>
<ErrorReport>none</ErrorReport>
<ApplicationIcon>BonNotiz.ico</ApplicationIcon>
<Title>BonNotiz</Title>
<Authors>Anna Christina Naß</Authors>
<Company />
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<Content Include="BonNotiz.ico" />
</ItemGroup>
<ItemGroup>
<None Include="..\LICENSE.txt">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\README.md" Link="README.md" />
</ItemGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+24 -26
View File
@@ -3,7 +3,7 @@ using System.Text;
using System.IO;
using System.Drawing;
namespace KohaCompanion.Shared
namespace BonNotiz
{
/// <summary>
/// Stellt einen zustandsbehafteten ESC/POS-Drucker dar.
@@ -34,10 +34,10 @@ namespace KohaCompanion.Shared
public class PrinterCodepage
{
public static readonly PrinterCodepage Cp437 = new PrinterCodepage(0, CodePagesEncodingProvider.Instance.GetEncoding(437));
public static readonly PrinterCodepage Cp852 = new PrinterCodepage(18, CodePagesEncodingProvider.Instance.GetEncoding(852));
public static readonly PrinterCodepage Cp866 = new PrinterCodepage(17, CodePagesEncodingProvider.Instance.GetEncoding(866));
public static readonly PrinterCodepage Cp1252 = new PrinterCodepage(16, CodePagesEncodingProvider.Instance.GetEncoding(1252));
public static readonly PrinterCodepage Cp437 = new(0, CodePagesEncodingProvider.Instance.GetEncoding(437));
public static readonly PrinterCodepage Cp852 = new(18, CodePagesEncodingProvider.Instance.GetEncoding(852));
public static readonly PrinterCodepage Cp866 = new(17, CodePagesEncodingProvider.Instance.GetEncoding(866));
public static readonly PrinterCodepage Cp1252 = new(16, CodePagesEncodingProvider.Instance.GetEncoding(1252));
private readonly byte _pageNumber;
private readonly Encoding? _encoding;
@@ -52,8 +52,10 @@ namespace KohaCompanion.Shared
public Encoding Encoding { get { return _encoding; } }
}
// Steuercodes für neue Zeile
private static readonly byte[] newLineBytes = { 0xA, 0xD };
// Steuercodes
private static readonly byte[] newLineBytes = [0xA, 0xD];
private static readonly byte esc = 0x1b;
private static readonly byte gs = 0x1d;
// Interner Buffer
private MemoryStream memstr = new();
@@ -63,10 +65,8 @@ namespace KohaCompanion.Shared
private bool underline = false;
private bool underlineDouble = false;
private bool emphasized = false;
//private bool redColor = false; * unused
private int currentFontX = 0;
private int currentFontY = 0;
//private bool panelButtonsEnabled = true; * unused
private Alignment _alignment = Alignment.Left;
/// <summary>
@@ -80,7 +80,7 @@ namespace KohaCompanion.Shared
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// Initialize Printer Command senden
byte[] buf = new byte[] { 0x1B, 0x40 };
byte[] buf = [esc, 0x40];
memstr.Write(buf, 0, buf.Length);
}
@@ -119,12 +119,10 @@ namespace KohaCompanion.Shared
byte[] buf = printerEnc.Encoding.GetBytes(str);
// Aufpassen, dass kein ASCII-Steuerzeichen vorkommt.
// For i As Integer = 0 To buf.Length - 1
// Dim c As Byte = buf(i)
// If Not (c >= &H20 AndAlso c <> &H7F) Then
// buf(i) = CByte(AscW(" "c))
// End If
// Next
for (int i = 0; i < buf.Length; i++) {
if ((int)buf[i] < 0x20 || (int)buf[i] == 0x7F)
buf[i] = 0x20;
}
memstr.Write(buf, 0, buf.Length);
}
@@ -170,7 +168,7 @@ namespace KohaCompanion.Shared
byte[] buf;
byte[] zeilenAnfang = new byte[] { 0x1B, 0x2A, 33, System.Convert.ToByte(bmp.Width & 0xFF), System.Convert.ToByte((bmp.Width >> 8) & 0xFF) };
byte[] zeilenAnfang = [esc, 0x2A, 33, System.Convert.ToByte(bmp.Width & 0xFF), System.Convert.ToByte((bmp.Width >> 8) & 0xFF)];
byte[] bildBuf = new byte[bmp.Width * 3 - 1 + 1];
for (int i = 0; i <= bmp.Height / 24 - 1; i++)
@@ -201,10 +199,10 @@ namespace KohaCompanion.Shared
// Zeile, aber geht mit kleineren Werten auch)
// Nicht LF verwenden, weil bei LF der normale Zeilenabstand verwendet
// wird!
buf = new byte[] { 0x1B, 0x4A, 0 };
buf = [esc, 0x4A, 0];
else
// Am Schluss normaler Zeilenabstand nach unten.
buf = new byte[] { 0xA };
buf = [0xA];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -217,13 +215,13 @@ namespace KohaCompanion.Shared
/// sonst false</param>
/// <param name="doubleThickness">true, wenn die Linie 2 Pixel statt 1 Pixel
/// dick sein soll</param>
public void SetUnderline(bool value, bool doubleThickness)
public void SetUnderline(bool value, bool doubleThickness = false)
{
if (value != underline || (value & doubleThickness != underlineDouble))
{
underline = value;
underlineDouble = doubleThickness;
byte[] buf = new byte[] { 0x1B, 0x2D, System.Convert.ToByte(value ? doubleThickness ? 2 : 1 : 0) };
byte[] buf = [esc, 0x2D, System.Convert.ToByte(value ? doubleThickness ? 2 : 1 : 0)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -238,7 +236,7 @@ namespace KohaCompanion.Shared
if (value != emphasized)
{
emphasized = value;
byte[] buf = new byte[] { 0x1B, 0x45, System.Convert.ToByte(value ? 1 : 0) };
byte[] buf = [esc, 0x45, System.Convert.ToByte(value ? 1 : 0)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -260,7 +258,7 @@ namespace KohaCompanion.Shared
currentFontX = x;
currentFontY = y;
byte[] buf = new byte[] { 0x1D, 0x21, System.Convert.ToByte((x << 4) | y) };
byte[] buf = [gs, 0x21, System.Convert.ToByte((x << 4) | y)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -274,7 +272,7 @@ namespace KohaCompanion.Shared
if (printerEnc != codepage)
{
printerEnc = codepage;
byte[] buf = new byte[] { 0x1B, 0x74, codepage.PageNumber };
byte[] buf = [esc, 0x74, codepage.PageNumber];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -289,7 +287,7 @@ namespace KohaCompanion.Shared
if (_alignment != alignment)
{
_alignment = alignment;
byte[] buf = new byte[] { 0x1B, 0x61, System.Convert.ToByte(alignment) };
byte[] buf = [esc, 0x61, System.Convert.ToByte(alignment)];
memstr.Write(buf, 0, buf.Length);
}
}
@@ -303,7 +301,7 @@ namespace KohaCompanion.Shared
/// werden soll</param>
public void CutPaper(bool fullCut)
{
byte[] buf = new byte[] { 0x1D, 0x56, System.Convert.ToByte(fullCut ? 65 : 66), 0x40 };
byte[] buf = [gs, 0x56, System.Convert.ToByte(fullCut ? 65 : 66), 0x40];
memstr.Write(buf, 0, buf.Length);
}
+20 -2
View File
@@ -31,9 +31,11 @@ namespace BonNotiz
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main));
TextBox = new TextBox();
PrinterSelect = new ComboBox();
Print = new Button();
Info = new Button();
SuspendLayout();
//
// TextBox
@@ -58,23 +60,38 @@ namespace BonNotiz
//
// Print
//
Print.Location = new Point(407, 357);
Print.Location = new Point(389, 357);
Print.Name = "Print";
Print.Size = new Size(75, 23);
Print.Size = new Size(93, 23);
Print.TabIndex = 3;
Print.Text = "&Drucken";
Print.UseVisualStyleBackColor = true;
Print.Click += Print_Click;
//
// Info
//
Info.Location = new Point(245, 357);
Info.Name = "Info";
Info.Size = new Size(109, 23);
Info.TabIndex = 4;
Info.Text = "&Info...";
Info.UseVisualStyleBackColor = true;
Info.Click += Info_Click;
//
// Main
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(493, 391);
Controls.Add(Info);
Controls.Add(Print);
Controls.Add(PrinterSelect);
Controls.Add(TextBox);
FormBorderStyle = FormBorderStyle.FixedSingle;
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
Name = "Main";
SizeGripStyle = SizeGripStyle.Hide;
Text = "BonNotiz";
ResumeLayout(false);
PerformLayout();
@@ -85,5 +102,6 @@ namespace BonNotiz
private TextBox TextBox;
private ComboBox PrinterSelect;
private Button Print;
private Button Info;
}
}
+21 -3
View File
@@ -1,4 +1,3 @@
using KohaCompanion.Shared;
using System;
using System.Windows.Forms;
@@ -32,13 +31,16 @@ namespace BonNotiz
static void Drucken(String bondrucker, String text)
{
EscPosPrinter pos = new();
/* EscPosPrinter pos = new();
pos.Write(text);
pos.WriteLine();
pos.WriteLine();
pos.CutPaper(true);
Byte[] buf = pos.GetCurrentBuffer();
Byte[] buf = pos.GetCurrentBuffer(); */
MarkdownToEscPos md = new();
Byte[] buf = md.Render(text);
using RawPrinter prn = new(bondrucker);
using RawPrinter.RawDocumentStream doc = prn.CreateDocument("BonNotiz");
@@ -56,5 +58,21 @@ namespace BonNotiz
Drucken(PrinterSelect.SelectedItem.ToString()!, TextBox.Text);
}
}
private void Info_Click(object sender, EventArgs e)
{
String text = "BonNotiz\n(c) 2026 Anna Christina Naß\n\n"
+ "Folgende Markdown-Formatierungen werden umgesetzt:\n\n"
+ "# Überschrift 1\n"
+ "## Überschrift 2\n"
+ "### Überschrift 3 (und weitere analog)\n"
+ "--- (Horizontale Linie)\n"
+ "- Aufzählung\n"
+ "**fett**\n"
+ "*kursiv* (wird ebenfalls fett gedruckt)\n"
+ "_unterstrichen_";
MessageBox.Show(text, "Über BonNotiz", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
+167
View File
@@ -117,4 +117,171 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAACkAAAA5AAAAOQAA
ADkAAAA5AAAAOQAAADkAAAA5AAAAOQAAADkAAAA5AAAAOQAAADkAAAA5AAAAOgAAEkYhJUK9ISVAtgAA
E0wAAAA6AAAAOQAAADkAAAA5AAAAOQAAADkAAAAoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAA
AGOrq6vCsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsbGxw7GxscOxsbHDsLCww1J6
peVHhbH+Jk19+GJmd+CqqqrFsbGxw7GxscOxsbHDsbGxw6urq8IAAABjAAAADwAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAACgAAAFzs7Ozs////////////////////////////////////////////////////////
/////////////zdlpP9NwN7/GEqN/05gff/Gys//+/v7/////////////////+zs7OsAAABcAAAACgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAB6enr/d3d3/1VVVf/FxcX/////////////////////////////////////////
/////////////////////////////36gy/8lirv/L7nh/xlNkv9rc4T/5+ft//7+/v///////////8TE
xP9VVVX/d3d3/3p6ev8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6enr/fn5+53V1demvr6/5+vn5//39/f//////////////
//////////////////////////////////////////////D0+P8aRoX/ONj3/yB4rv8wW47/lZmo//j4
+P/9/f3/+vn5/66urvh2dnbpfn5+53p6ev8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEhIT/hISE/7Gxsf+lpKT/9fT0//j3
9//6+vr//f39//////////////////////////////////////////////////////8yX5//Kbrn/yXF
7P8XUJb/TWF+/8LGy//08/P/9fT0/6Sjo/+wsLD/g4OD/4SEhP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOjo7/d3d3/4yM
jP9+fX3/7evr//Hv7//08/P/9/b2//n5+f/7+vr//Pz8//79/f//////////////////////////////
//+GpMz/IXmt/xSy6/8nrdr/G1eY/2tzgv/b2d7/7Orq/359ff+NjY3/d3d3/46Ojv8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADm5ub/jIyM/1lZWf9UU1P/5OLi/+jm5v/s6ur/7+3t//Lw8P/08/P/9vX1//f29v/49/f/+fj4//n4
+P/5+Pj/+fj4//j39//u7/L/F0J+/yG78P8St+j/H3u0/zFgjv+Ljpz/3tzc/1RUVP9ZWVn/jIyM/+bm
5v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADd3d3/gICA/y4uLv8oJyf/19TU/9/c3P/i4OD/5ePj/+jm5v/q6en/7Ovr/+7s
7P/v7u7/8O/v//Hv7//x7+//8O/v/+/u7v/u7Oz/NF+a/yGv3/8CoeP/IL/p/xhdn/9JXHn/qauw/ycm
Jv8uLi7/gICA/93d3f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkIiIH5aQ
kPSbmpr+m5qa/puamv6bmpr+m5qa/n18fP7n5+f/hYWF/yEhIf8XFxf/s7Cw/9TQ0P/Y1NT/29jY/9/c
3P/h3t7/4+Dg/+Ti4v/l4+P/5uTk/+bk5P/m5OT/5uTk/+Xj4//k4uL/gJ2+/xpkl/8Sq+//BKbg/yGq
2P8bY53/Vl1s/xUVGv8hISH/hYWF/+fn5/99fHz+m5qa/puamv6bmpr+m5qa/puamv6WkJD0kIiIHwAA
AAAAAAAAkYeHMqahof++vr7/vr6+/76+vv++vr7/vr6+/5iYmP/w8PD/iYmJ/yEhIf8YGBj/j4yM/8jD
w//Mx8f/z8vL/9LOzv/V0dH/19PT/9nV1f/a19f/29jY/9vY2P/b2Nj/29jY/9rX1//Z1dX/08/R/xY/
eP8dufD/AqTj/w636P8agrn/KF6G/x0gL/8gICD/iYmJ//Dw8P+YmJj/vr6+/76+vv++vr7/vr6+/76+
vv+moaH/jYeHMAAAAAAAAAAAlo+PQ7GsrP/Hx8f/x8fH/8fHx//Hx8f/x8fH/6Ojo//6+vr/ioqK/xsb
G/8VFRX/YV5e/6WgoP+oo6P/qqam/62oqP+vq6v/sa2t/7Ourv+0sLD/tbGx/7Wxsf+1sbH/tbGx/7Sw
sP+zrq7/sa2t/y5Zi/8co9T/BqTr/wCp4f8Yvun/FG2p/xw0TP8dISb/iIiI//r6+v+jo6P/x8fH/8fH
x//Hx8f/x8fH/8fHx/+wrKz/l4uLQQAAAAAAAAAApp2dVcC9vf/R0dH/0dHR/9HR0f/R0dH/0dHR/6+v
r///////hoaG/w0NDf8LCwv/CQkJ/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgI
CP8ICAj/CAgI/wgICP8ICAj/CAgI/womQP8YUX//FLHx/wGq5P8Dr+T/G6va/xZpm/8dJTT/e3uA//7+
/v+vr6//0dHR/9HR0f/U1NT/0tLS/9HR0f+/vLz/pp2dUgAAAAAAAAAAtK+vZc/Nzf/b29v/29vb/9vb
2//b29v/29vb/8PDw/98fHz/QkJC/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgI
CP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8ICAj/CAgI/wgICP8SOWv/Gbbs/waq6/8Ar+T/Cbzq/xiN
v/8YU3b/MzlD/3l5ef/FxcX/29vb/9vb2/+1tbX/o6Oj/9vb2//OzMz/tbCwYwAAAAAAAAAAxL+/btnX
1//i4uL/4uLi/+Li4v/i4uL/4uLi/+Pj4/+QkJD/EBAQ/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMD
A/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wMDA/8NO2b/GZTD/w2u
8v8BsOX/ALPm/xPA6/8YgbL/GzVL/3V5f//g4OD/4uLi/+Li4v+3uLj/rq6u/+Li4v/Y1tb/xMDAawAA
AAAAAAAA0s3NdOLh4f/p6en/6enp/+np6f/p6en/6enp/+jo6P/b29v/5eXl/+Xl5f/l5eX/5OTk/+Pj
4//i4uL/4eHh/+Dg4P/f39//3t7e/93d3f/c3Nz/29vb/9ra2v/a2tr/29vb/9zc3P/d3d3/3d3d/97e
3v+Zssb/E0Bm/xK38v8Fsez/ALTm/wK56P8Vsdz/IYOr/2VtfP/V1dr/6Ojo/+np6f/Q0ND/xMTE/+np
6f/j4uL/0c/PcgAAAAAAAAAA3Nrae+vq6v/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw
8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw
8P/w8PD/8PDw//Dw8P/v7+//Fj5p/xOz5/8LsvL/ALbo/wC56f8Fwu3/Fp3I/zh3lv+SmKL/6enp//Dw
8P/Gx8f/x8fH/+3t7f/r6ur/3NnZeAAAAAAAAAAAwsDAje/u7v/29vb/9vb2//b29v/29vb/9vb2//b2
9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2
9v/29vb/9vb2//b29v/29vb/9vb2//b29v/19fX/Rnec/xGAqv8OtfP/Bbft/wC66f8Avuv/DMbt/xiT
vv9Ran//xMTL//Pz8//W1tb/yMjI//b29v/v7u7/wsDAjAAAAAAAAAAAzMzLmtPT0//R0dH/0dHR/9HR
0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR
0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0NDQ/8bGxv+8vML/j6S3/w0tTv8Qu/L/C7ny/wC7
6v8Av+v/AMPt/xG43/8iia//Y2p5/8DAxf/Q0ND/0dHR/9HR0f/T09P/zMzKmAAAAAAAAAAA09XTcqWl
pf+RkZH/kZGR/5GRkf+RkZH/kZGR/5GRkf+RkZH/b29v/2JiYv9iYmL/YmJi/2JiYv9iYmL/YmJi/2Ji
Yv9iYmL/UlJS/1JSUv9SUlL/UlJS/1JSUv9SUlL/UlJS/1JSUv9SUlL/SUlP/y80Qv8kLT3/Ii08/xE8
Y/8Or9//Dbv0/wS87f8AwOz/AMPt/wDJ8P8Rpc//LGuK/19lcP+NjY3/kZGR/5GRkf+lpaX/1NTUbwAA
AAAAAAAA0NLSa+3u7v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/jY2N/0FBQf9BQUH/QUFB/0FB
Qf9BQUH/QUFB/0FBQf9BQUH/YmJi/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/Q3SV/0uR
t/8ZV5P/GV+a/xZRgv8Na4//Db30/wu/8v8Awez/AMTu/wDI7/8DyvD/FpnG/1VrgP/IzNH/9/f3//r6
+v/t7u3/0dTRaAAAAAAAAAAAzdLQX+jq6f/39/f/9/f3//f39//39/f/9/f3//f39//39/f/mJiY/1BQ
UP9QUFD/UFBQ/1BQUP9QUFD/UFBQ/1BQUP9QUFD/ZmZm/3h4eP93d3f/d3d3/3d3d/93d3f/d3d3/3d3
d/94eHj/Jl2Q/yCLxf8Vr/L/DrDy/wy28/8Nu/T/Dr71/w7B9f8Dwu//AMbu/wDJ8P8AzPH/Cbrj/yOM
tf9qc4f/4+Po//b29v/o6en/ztHOXQAAAAAAAAAAzNDMT+Pl5f/09PT/9PT0//T09P/09PT/9PT0//T0
9P/09PT/m5ub/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VV
Vf9VVVX/VVVV/1VVVf9VVVX/Olp1/xZPjf8ZsfL/Jrjz/yy/9f8owvX/Lcf2/zvO+P890/j/EMvw/wDK
8P8AzvL/ANL0/w6j1v86dJj/mZyn/+7u7v/j5eT/ytHOTAAAAAAAAAAAxsrKPd3f3v/x8fH/8fHx//Hx
8f/x8fH/8fHx//Hx8f/x8fH/np6e/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VV
Vf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VFVV/xdQj/8JpuX/C7Dy/w228/8Wy/r/FdP9/xjW
/f8c2P3/QuH9/2Di+v9J3vf/BdP0/wLQ8/8Tks7/U2qC/9bW2f/b3t3/xMjIOwAAAAAAAAAAu8fBLNbZ
1//u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/0NDQ/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm
5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/0J9sf8OhcP/C7Dy/wy2
8/8Kwff/ANX//wDX//8A2P//ANr//wDb//8Y3///XOf9/1Lm+/8Ouej/Koe8/9fc3P/U2Nb/vsS+KgAA
AAAAAAAAqqqqF8TGxc3f4ODi3+Hg4uDi4eLh4+Li4uPj4uLk4+Li5OPiqKio8oaHh/CGh4fwh4eH8IeH
h/CHh4fwh4mH8IeJh/CHiYfwh4mJ8IeJifCHiYnwh4mJ8IeJifCHiYnwh4mJ8IeJifCHiYnwh4mJ8Fh6
lvUVVJP/CrLz/wy28/8OvfX/A9H9/wDX//8A2f//ANr//wm85P8LtuH/Crjj/xm95/9h0fD/icfo/N7f
3+LExsXNqqqqFwAAAAAAAAAAAAAAAJOTk+ucnJz/pKSk/6urq/+zs7P/u7u7/76+vv/AwMD/d3d3/0FB
Qf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FBQf9BQUH/QUFB/0FB
Qf9BQUH/QUFB/z9AQv8WVJP/Cqzq/wy28/8OvfX/Csn5/wDY//8A2f//ANv//wm+5/8Vj8H/KWeJ/2OZ
tv9soLv/laSt/5ycnP+Tk5PsAAAAAAAAAAAAAAAAAAAAAJCQkL2YmJj/n5+f/6enp/+urq7/tra2/7y8
vP++vr7/aGho/0RERP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP9AQED/QEBA/0BA
QP9AQED/QEBA/0BAQP9AQED/QEBA/0BAQP8cW47/DY7K/wy28/8OvfX/D8T2/wLW/v8A2f//ANv//wHb
/v8Rn9D/H2SI/2Noc/+ioqL/n5+f/5iYmP+Pj4+8AAAAAAAAAAAAAAAAAAAAAImJiY6Tk5P/m5ub/6Ki
ov+pqan/sLCw/7e3t/+8vLz/aWlp/ycnJ/9YVVX/WVZW/1tYWP9cWlr/XVpa/11bW/9eXFz/Xlxc/19d
Xf9gXl7/YF5e/2BeXv9gXl7/YF5e/2BeXv9fXV3/Xlxc/15cXP8+YHz/FFyb/wu39P8OvfX/D8T2/wnQ
+v8A2v//ANv//wDd//8KyvD/EonD/zJFVf+JiYz/mpqa/5OTk/+KioqNAAAAAAAAAAAAAAAAAAAAAIiI
iF+Ojo7/lpaW/52dnf+kpKT/q6ur/7Kysv+4uLj/dnZ2/yUlJf+1r6//urS0/764uP/BvLz/xcDA/8fD
w//KxcX/zMjI/87Kyv/Py8v/0MzM/9DMzP/QzMz/0MzM/8/Ly//Oysr/zMjI/8rFxf/Cv8H/GV2b/wqz
7P8NvPT/D8P2/w/L9/8B2f//ANz//wDd//8C3///EabZ/xhrnP9NUF3/kJCQ/46Ojv+GhoZeAAAAAAAA
AAAAAAAAAAAAAIeHhzCJiYn/kJCQ/5eXl/+enp7/paWl/6ysrP+ysrL/rq6u/ysrK/+9t7f/wby8/8XA
wP/JxcX/zMjI/8/Ly//Szs7/1NHR/9bT0//X1NT/2NXV/9nV1f/Z1dX/2NXV/9fU1P/W0tL/1NHR/9LO
zv/Py8v/PHqu/w2V0P8NvPT/D8P2/xDK9/8I1vz/ANz//wDe//8A3///C9b2/xCIzP8kRl7/a3B2/4eH
h/+FhYUvAAAAAAAAAAAAAAAAAAAAAG1tbQaIiIiIioqKiJGRkYiXl5eInp6eiKSkpIirq6uInJyc9jEx
Mf/Ev7//ycTE/83Jyf/Rzc3/1NHR/9fU1P/a19f/3dnZ/97b2//f3Nz/4N3d/+De3v/g3t7/4N3d/9/c
3P/e29v/3dnZ/9rX1//X1NT/hafD/xRjo/8Nu/T/D8L2/xDK9/8P0vn/ANz//wDe//8A4P//AeH//xKu
4v8Rbqz+MDdK5Hd3d5FtbW0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAmZmZ5TY2Nv/Lx8f/0MzM/9TR0f/Y1dX/3NnZ/9/c3P/h39//4+Hh/+Xi4v/m4+P/5+Tk/+fl
5f/n5eX/5+Tk/+bj4//l4uL/4+Hh/+Hf3//f3Nz/1tbX/xhen/8LuO//DsL1/xDJ9/8R0fj/Btv9/wDe
//8A4P//AOL//wzd+/8NhtT/GUZw9CYsOnEAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAnJyc3z09Pf/Sz8//19TU/9zZ2f/g3d3/4+Dg/+Xj4//n5eX/6efn/+vp
6f/s6ur/7evr/+3s7P/t7Oz/7evr/+zq6v/r6en/6efn/+fl5f/l4+P/4+Dg/0B/tf8NnNb/DsD1/xDI
9/8R0Pj/D9j6/wDf//8A4P//AOL//wDj//8buuv/C26+/iUsQNwAKiojAAAAAQAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo6Oj1URERP/Z1tb/3tvb/+Lf3//l4+P/6Obm/+vp
6f/u7Oz/8O7u//Hw8P/z8fH/8/Ly//Tz8//08/P/8/Ly//Px8f/x8PD/8O7u/+7s7P/r6en/6Obm/42w
zv8Raav/DsD1/w/H9v8Rz/j/Etf5/wXf/v8A4P//AOL//wDk//8R5f7/FYzb/xVMhvgbLjyTAAAACAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJyc1UlJSf/g3d3/5OHh/+jl
5f/r6en/7u3t//Hw8P/08/P/9vX1//f29v/49/f/+Pj4//n4+P/5+Pj/+Pj4//j39//39vb/9vX1//Ty
8v/x8PD/7u3t/+Xl5/8YX6T/C7zx/w/F9v8Rzvj/Etb5/w7e/P8A4P//AOL//wDk//8A5v//K8ny/wdr
zv8fM0jqISEyPAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlpaW1FNT
U//l4uL/6efn/+3r6//x7+//9PPz//f29v/4+Pj/+vn5//v7+//8/Pz//Pz8//39/f/9/f3//Pz8//z8
/P/7+/v/+vn5//j4+P/39vb/9PPz//Hv7/9CgLr/C5/b/w/D9v8QzPf/EtX5/xPd+v8D4v//AOL//wDk
//8A5v//Euj//ySX4/8PUZn8IilAswAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAcnJyUkZGRsPq6Oj/7u3t//Lx8f/29fX/+Pj4//r6+v/8/Pz//v7+////////////////////
/////////////////////////v7+//z8/P/6+vr/+Pj4//b19f+Rtdb/D22z/w7B9f8Qyvf/EtP5/xPc
+v8N4v3/AOL//wDk//8A5v//AOf//z3Z+P8FbNn/HDVa8RspOlsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGjv7e3/8/Ly//f29v/6+fn//Pz8//7+/v//////////////
///////////////////////////////////////////////////+/v7//Pz8//r5+f/u8fT/Fl2o/wu+
8/8Px/b/EdH4/xPa+v8T4/v/AuP//wDk//8A5f//AOf//wvp//87re3/C1qx/iEqOswAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj08vL/9/f3//r6+v/9/f3/////////
//////////////////////////////////////////////////////////////////////////////39
/f/6+vr/Q4C//wqj3v8PxPb/Ec74/xLX+f8U4fv/C+b+/wDj//8A5f//AOb//wDn//9F4vv/CnXi/xpA
c90AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj39/f/+/r6//79
/f//////////////////////////////////////////////////////////////////////////////
///////////////////+/f3/ob/i/3Ck0v80seL/NbXl/ze55/84ven/Ob3p/zax5/81sun/NbTr/zW1
7f84t/D/jsvy/zGA2I8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAA
AGj6+vr//f39////////////////////////////////////////////////////////////////////
/////////////////////////////////////////f39/6TB4/8GQ4e4CViujQdev4EIYMF+BmHGewZi
x3kEZcx2BGPPcwRn0HECZ9ZuAmrZXSBgwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAEgAAAGj9/f3/////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////39/f8AAABoAAAAEgAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj/////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//8AAABoAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAGj/////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////8AAABoAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAE4AAABoAAAAaAAA
AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABoAAAAaAAA
AGgAAABoAAAAaAAAAGgAAABoAAAAaAAAAGgAAABOAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAoAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAA
ABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAKAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/
AAD/gAAAAf8AAP+AAAAB/wAA/4AAAAH/AAD/gAAAAf8AAP+AAAAB/wAA/4AAAAH/AACAAAAAAAEAAIAA
AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAB
AACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA
AAAAAQAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAA/8AAAAAD
AAD/wAAAAAEAAP/AAAAAAQAA/8AAAAAAAAD/wAAAAAAAAP/AAAAAAAAA/8AAAAAAAAD/wAAAAAAAAP/A
AAAAAAAA/8AAAAAAAAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/gAAAH/wAA////////
AAA=
</value>
</data>
</root>
+110
View File
@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using static BonNotiz.MiniMarkdown;
namespace BonNotiz
{
public class MarkdownToEscPos
{
private readonly EscPosPrinter epp;
public MarkdownToEscPos()
{
epp = new();
}
public byte[] Render(String text)
{
MdDocument doc = MiniMarkdown.Parse(text);
return Render(doc);
}
public byte[] Render(MdDocument doc)
{
foreach (MdBlock block in doc.Blocks)
RenderBlock(block);
epp.WriteLine();
epp.CutPaper(true);
return epp.GetCurrentBuffer();
}
private void RenderBlock(MdBlock block)
{
switch (block)
{
case MdHeading h:
switch (h.Level)
{
case 1:
epp.SetFontSize(1, 1);
break;
case 2:
epp.SetFontSize(1, 0);
break;
default:
epp.SetFontSize(0, 1);
break;
}
RenderInline(h.Content);
epp.WriteLine();
epp.WriteLine();
epp.SetFontSize(0, 0);
break;
case MdParagraph p:
RenderInline(p.Content);
epp.WriteLine();
epp.WriteLine();
break;
case MdList l:
foreach (var item in l.Items)
{
epp.Write(new string([(char)0xBB, ' ']));
RenderInline(item.Content);
epp.WriteLine();
}
break;
case MdHorizontalRule:
epp.WriteLine(new string((char)0x2550, 42));
break;
}
}
private void RenderInline(List<MdInline> inlines)
{
foreach (var inline in inlines)
{
switch (inline)
{
case MdText t:
epp.Write(t.Value);
break;
case MdBold b:
epp.SetEmphasized(true);
RenderInline(b.Content);
epp.SetEmphasized(false);
break;
case MdItalic i:
epp.SetEmphasized(true);
RenderInline(i.Content);
epp.SetEmphasized(false);
break;
case MdUnderline u:
epp.SetUnderline(true);
RenderInline(u.Content);
epp.SetUnderline(false);
break;
}
}
}
}
}
+156
View File
@@ -0,0 +1,156 @@
using System.Collections.Generic;
using System.Linq;
namespace BonNotiz
{
public static class MiniMarkdown
{
public abstract record MdBlock;
public record MdDocument(List<MdBlock> Blocks) : MdBlock;
public record MdHeading(int Level, List<MdInline> Content) : MdBlock;
public record MdParagraph(List<MdInline> Content) : MdBlock;
public record MdList(List<MdListItem> Items) : MdBlock;
public record MdListItem(List<MdInline> Content);
public record MdHorizontalRule() : MdBlock;
public abstract record MdInline;
public record MdText(string Value) : MdInline;
public record MdBold(List<MdInline> Content) : MdInline;
public record MdItalic(List<MdInline> Content) : MdInline;
public record MdUnderline(List<MdInline> Content) : MdInline;
public static MdDocument Parse(string markdown)
{
List<MdBlock> blocks = [];
List<MdListItem> listBuffer = [];
string[] lines = markdown.Replace("\r\n", "\n").Split('\n');
// Wenn listBuffer etwas enthält, dieses an blocks anhängen und listBuffer leeren
void FlushList()
{
if (listBuffer.Count > 0)
{
blocks.Add(new MdList(listBuffer.ToList()));
listBuffer.Clear();
}
}
foreach (string rawLine in lines)
{
string line = rawLine.TrimEnd();
if (string.IsNullOrWhiteSpace(line))
{
FlushList();
continue;
}
// Horizontal rule
if (line.StartsWith("---"))
{
FlushList();
blocks.Add(new MdHorizontalRule());
continue;
}
// Heading
if (line.StartsWith('#'))
{
FlushList();
int level = line.TakeWhile(c => c == '#').Count();
string text = line[level..].Trim();
blocks.Add(new MdHeading(level, ParseInline(text)));
continue;
}
// List item
if (line.StartsWith("- "))
{
listBuffer.Add(new MdListItem(ParseInline(line[2..])));
continue;
}
// Paragraph
FlushList();
blocks.Add(new MdParagraph(ParseInline(line)));
}
FlushList();
return new MdDocument(blocks);
}
private static List<MdInline> ParseInline(string text)
{
List<MdInline> result = [];
int i = 0;
while (i < text.Length)
{
// Bold **
if (i + 1 < text.Length && text[i] == '*' && text[i + 1] == '*')
{
int end = text.IndexOf("**", i + 2);
if (end == -1) break;
string inner = text[(i + 2)..end];
result.Add(new MdBold(ParseInline(inner)));
i = end + 2;
continue;
}
// Italic *
if (text[i] == '*')
{
int end = text.IndexOf('*', i + 1);
if (end == -1) break;
string inner = text[(i + 1)..end];
result.Add(new MdItalic(ParseInline(inner)));
i = end + 1;
continue;
}
// Underline _
if (i + 1 < text.Length && text[i] == '_')
{
int end = text.IndexOf("_", i + 1);
if (end == -1) break;
string inner = text[(i + 1)..end];
result.Add(new MdUnderline(ParseInline(inner)));
i = end + 1;
continue;
}
// Plain text
int nextSpecial = FindNextSpecial(text, i);
result.Add(new MdText(text[i..nextSpecial]));
i = nextSpecial;
}
return result;
}
private static int FindNextSpecial(string text, int start)
{
int[] candidates = [ text.IndexOf('*', start), text.IndexOf("_", start) ];
int min = int.MaxValue;
foreach (var c in candidates)
if (c != -1 && c < min)
min = c;
return min == int.MaxValue ? text.Length : min;
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
using System.IO;
using System.Runtime.InteropServices;
namespace KohaCompanion.Shared
namespace BonNotiz
{
/// <summary>
/// Eine Klasse zum Kapseln eines Druckers. Mit der Methode