diff --git a/src/imagerenderer.ts b/src/imagerenderer.ts
index c9e6b6f3..9863ae5c 100644
--- a/src/imagerenderer.ts
+++ b/src/imagerenderer.ts
@@ -12,13 +12,15 @@ class ImageRendererModel {
htmlImg : any;
termOpts : TermOptsType;
dataBuf : PtyDataBuffer;
+ fontSize : number;
- constructor(imgDivElem : any, context : RendererContext, termOpts : TermOptsType, isDone : boolean) {
+ constructor(imgDivElem : any, context : RendererContext, termOpts : TermOptsType, isDone : boolean, fontSize : number) {
this.dataBuf = new PtyDataBuffer();
this.htmlImgDivElem = imgDivElem;
this.termOpts = termOpts;
this.context = context;
this.isDone = mobx.observable.box(isDone, {name: "isDone"});
+ this.fontSize = fontSize;
this.reload(0);
}
@@ -39,8 +41,8 @@ class ImageRendererModel {
let blob = new Blob([this.dataBuf.getData()], {type: "image/jpeg"});
this.htmlImg = new Image();
this.htmlImg.src = URL.createObjectURL(blob);
- this.htmlImg.style.maxHeight = termHeightFromRows(this.termOpts.rows) + "px";
- this.htmlImg.style.maxWidth = termWidthFromCols(this.termOpts.cols) + "px";
+ this.htmlImg.style.maxHeight = termHeightFromRows(this.termOpts.rows, this.fontSize) + "px";
+ this.htmlImg.style.maxWidth = termWidthFromCols(this.termOpts.cols, this.fontSize) + "px";
this.htmlImgDivElem.replaceChildren(this.htmlImg);
}
diff --git a/src/main.tsx b/src/main.tsx
index 0bd19142..a806ce67 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -483,7 +483,7 @@ class TerminalRenderer extends React.Component<{sw : ScreenWindow, line : LineTy
}, {name: "computed-isFocused"}).get();
let cmd = GlobalModel.getCmd(line); // will not be null
let usedRows = sw.getUsedRows(line, cmd, width);
- let termHeight = termHeightFromRows(usedRows);
+ let termHeight = termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
let termLoaded = this.termLoaded.get();
return (
@@ -707,12 +707,11 @@ class LineCmd extends React.Component<{sw : ScreenWindow, line : LineType, width
// header is 36px tall, padding+border = 6px
// zero-terminal is 0px
// terminal-wrapper overhead is 11px (margin/padding)
- // each terminal line 16px
// inner-height, if zero-lines => 42
- // else: 53+(lines*16)
+ // else: 53+(lines*lineheight)
let height = 42; // height of zero height terminal
if (usedRows > 0) {
- height = 53 + termHeightFromRows(usedRows);
+ height = 53 + termHeightFromRows(usedRows, GlobalModel.termFontSize.get());
}
return (
@@ -1396,6 +1395,7 @@ class InfoRemoteShow extends React.Component<{}, {}> {
>
);
}
+ let termFontSize = GlobalModel.termFontSize.get();
return (
<>
@@ -1441,14 +1441,14 @@ class InfoRemoteShow extends React.Component<{}, {}> {
-
+
input is only allowed while status is 'connecting'
-
+
>
);
@@ -2604,8 +2604,8 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
this.width.set(width);
this.height.set(height);
let {sw} = this.props;
- let cols = windowWidthToCols(width);
- let rows = windowHeightToRows(height);
+ let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
+ let rows = windowHeightToRows(height, GlobalModel.termFontSize.get());
if (sw == null || cols == 0 || rows == 0) {
return;
}
@@ -2720,9 +2720,11 @@ class ScreenView extends React.Component<{screen : Screen}, {}> {
);
}
+ let fontSize = GlobalModel.termFontSize.get();
+ let swKey = sw.windowId + "-fs" + fontSize;
return (
-
+
);
}
diff --git a/src/model.ts b/src/model.ts
index f346dafe..52afb3f5 100644
--- a/src/model.ts
+++ b/src/model.ts
@@ -8,11 +8,9 @@ import {v4 as uuidv4} from "uuid";
import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenWindowType, ScreenOptsType, LayoutType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType} from "./types";
import {WSControl} from "./ws";
import {ImageRendererModel} from "./imagerenderer";
-import {measureText} from "./textmeasure";
+import {measureText, getMonoFontSize} from "./textmeasure";
var GlobalUser = "sawka";
-const DefaultCellWidth = 7.203125;
-const DefaultCellHeight = 16;
const RemotePtyRows = 8; // also in main.tsx
const RemotePtyCols = 80;
const MinTermCols = 10;
@@ -21,6 +19,9 @@ const ProdServerEndpoint = "http://localhost:1619";
const ProdServerWsEndpoint = "ws://localhost:1623";
const DevServerEndpoint = "http://localhost:8090";
const DevServerWsEndpoint = "ws://localhost:8091";
+const DefaultTermFontSize = 12;
+const MinFontSize = 8;
+const MaxFontSize = 15;
// @ts-ignore
const VERSION = __PROMPT_VERSION__;
@@ -34,26 +35,30 @@ type SWLinePtr = {
sw : ScreenWindow,
};
-function windowWidthToCols(width : number) : number {
- let cols = Math.trunc((width - 50) / DefaultCellWidth) - 1;
+function windowWidthToCols(width : number, fontSize : number) : number {
+ let dr = getMonoFontSize(fontSize);
+ let cols = Math.trunc((width - 50) / dr.width) - 1;
cols = boundInt(cols, MinTermCols, MaxTermCols);
return cols;
}
-function windowHeightToRows(height : number) : number {
- let rows = Math.floor((height - 80)/DefaultCellHeight) - 1;
+function windowHeightToRows(height : number, fontSize : number) : number {
+ let dr = getMonoFontSize(fontSize);
+ let rows = Math.floor((height - 80) / dr.height) - 1;
if (rows <= 0) {
rows = 1;
}
return rows;
}
-function termWidthFromCols(cols : number) : number {
- return Math.ceil(DefaultCellWidth*cols) + 15;
+function termWidthFromCols(cols : number, fontSize : number) : number {
+ let dr = getMonoFontSize(fontSize);
+ return Math.ceil(dr.width*cols) + 15;
}
-function termHeightFromRows(rows : number) : number {
- return Math.ceil(DefaultCellHeight*rows);
+function termHeightFromRows(rows : number, fontSize : number) : number {
+ let dr = getMonoFontSize(fontSize);
+ return Math.ceil(dr.height*rows);
}
function cmdStatusIsRunning(status : string) : boolean {
@@ -559,7 +564,7 @@ class ScreenWindow {
loadImageRenderer(imageDivElem : any, line : LineType, cmd : Cmd) : ImageRendererModel {
let cmdId = cmd.cmdId;
let context = {sessionId: this.sessionId, screenId: this.screenId, windowId: this.windowId, cmdId: cmdId, lineId : line.lineid, lineNum: line.linenum};
- let imageModel = new ImageRendererModel(imageDivElem, context, cmd.getTermOpts(), !cmd.isRunning());
+ let imageModel = new ImageRendererModel(imageDivElem, context, cmd.getTermOpts(), !cmd.isRunning(), GlobalModel.termFontSize.get());
this.renderers[cmdId] = imageModel;
return imageModel;
}
@@ -571,7 +576,7 @@ class ScreenWindow {
console.log("term-wrap already exists for", this.screenId, this.windowId, cmdId);
return;
}
- let cols = windowWidthToCols(width);
+ let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
let usedRows = GlobalModel.getTUR(this.sessionId, cmdId, cols);
if (line.contentheight != null && line.contentheight != -1) {
usedRows = line.contentheight;
@@ -586,6 +591,7 @@ class ScreenWindow {
focusHandler: (focus : boolean) => this.setTermFocus(line.linenum, focus),
isRunning: cmd.isRunning(),
customKeyHandler: this.termCustomKeyHandler.bind(this),
+ fontSize: GlobalModel.termFontSize.get(),
});
this.renderers[cmdId] = termWrap;
if ((this.focusType.get() == "cmd" || this.focusType.get() == "cmd-fg") && this.selectedLine.get() == line.linenum) {
@@ -612,7 +618,7 @@ class ScreenWindow {
}
let termWrap = this.getRenderer(cmd.cmdId);
if (termWrap == null) {
- let cols = windowWidthToCols(width);
+ let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
let usedRows = GlobalModel.getTUR(this.sessionId, cmd.cmdId, cols);
if (usedRows != null) {
return usedRows;
@@ -1535,6 +1541,7 @@ class InputModel {
keyHandler: (e, termWrap) => { this.termKeyHandler(remoteId, e, termWrap)},
focusHandler: this.setRemoteTermWrapFocus.bind(this),
isRunning: true,
+ fontSize: GlobalModel.termFontSize.get(),
});
}
}
@@ -1827,6 +1834,7 @@ class Model {
authKey : string;
isDev : boolean;
activeMainView : OV<"session" | "history" | "bookmarks"> = mobx.observable.box("session", {name: "activeMainView"});
+ termFontSize : OV
= mobx.observable.box(DefaultTermFontSize, {name: "termFontSize"});
inputModel : InputModel;
bookmarksModel : BookmarksModel;
@@ -1863,6 +1871,18 @@ class Model {
return ProdServerEndpoint;
}
+ setTermFontSize(fontSize : number) {
+ if (fontSize < MinFontSize) {
+ fontSize = MinFontSize;
+ }
+ if (fontSize > MaxFontSize) {
+ fontSize = MaxFontSize;
+ }
+ mobx.action(() => {
+ this.termFontSize.set(fontSize);
+ })();
+ }
+
getBaseWsHostPort() : string {
if (this.isDev) {
return DevServerWsEndpoint;
@@ -2749,12 +2769,11 @@ let GlobalCommandRunner : CommandRunner = null;
if ((window as any).GlobalModel == null) {
(window as any).GlobalModel = new Model();
(window as any).GlobalCommandRunner = new CommandRunner();
+ (window as any).getMonoFontSize = getMonoFontSize;
}
GlobalModel = (window as any).GlobalModel;
GlobalCommandRunner = (window as any).GlobalCommandRunner;
-window.measureText = measureText;
-
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, ScreenWindow, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData};
diff --git a/src/term.ts b/src/term.ts
index f0f55bf7..e3707631 100644
--- a/src/term.ts
+++ b/src/term.ts
@@ -29,6 +29,7 @@ type TermWrapOpts = {
dataHandler? : (data : string, termWrap : TermWrap) => void,
isRunning : boolean,
customKeyHandler? : (event : any, termWrap : TermWrap) => boolean,
+ fontSize: number,
};
// cmd-instance
@@ -48,6 +49,7 @@ class TermWrap {
termSize : TermWinSize;
focusHandler : (focus : boolean) => void;
isRunning : boolean;
+ fontSize : number;
constructor(elem : Element, opts : TermWrapOpts) {
opts = opts ?? ({} as any);
@@ -57,6 +59,7 @@ class TermWrap {
this.winSize = opts.winSize;
this.focusHandler = opts.focusHandler;
this.isRunning = opts.isRunning;
+ this.fontSize = opts.fontSize;
if (this.flexRows) {
this.atRowMax = false;
this.usedRows = mobx.observable.box(opts.usedRows ?? (opts.isRunning ? 1 : 0), {name: "term-usedrows"});
@@ -69,13 +72,13 @@ class TermWrap {
this.termSize = {rows: opts.termOpts.rows, cols: opts.termOpts.cols};
}
else {
- let cols = windowWidthToCols(opts.winSize.width);
+ let cols = windowWidthToCols(opts.winSize.width, opts.fontSize);
this.termSize = {rows: opts.termOpts.rows, cols: cols};
}
let theme = {
foreground: "#d3d7cf",
};
- this.terminal = new Terminal({rows: this.termSize.rows, cols: this.termSize.cols, fontSize: 12, fontFamily: "JetBrains Mono", theme: theme});
+ this.terminal = new Terminal({rows: this.termSize.rows, cols: this.termSize.cols, fontSize: opts.fontSize, fontFamily: "JetBrains Mono", theme: theme});
this.terminal._core._inputHandler._parser.setErrorHandler((state) => {
this.numParseErrors++;
return state;
@@ -238,8 +241,8 @@ class TermWrap {
}
resizeWindow(size : WindowSize) : void {
- let cols = windowWidthToCols(size.width);
- let rows = windowHeightToRows(size.height);
+ let cols = windowWidthToCols(size.width, this.fontSize);
+ let rows = windowHeightToRows(size.height, this.fontSize);
this.resize({rows, cols});
}
diff --git a/src/textmeasure.ts b/src/textmeasure.ts
index bf8b909b..7e6eb405 100644
--- a/src/textmeasure.ts
+++ b/src/textmeasure.ts
@@ -1,4 +1,17 @@
-let canvasElem = document.createElement("canvas");
+let MonoFontSizes : {height : number, width : number}[] = [];
+
+MonoFontSizes[8] = {height: 11, width: 4.797};
+MonoFontSizes[9] = {height: 12, width: 5.398};
+MonoFontSizes[10] = {height: 13, width: 6};
+MonoFontSizes[11] = {height: 15, width: 6.602};
+MonoFontSizes[12] = {height: 16, width: 7.203};
+MonoFontSizes[13] = {height: 18, width: 7.797};
+MonoFontSizes[14] = {height: 19, width: 8.398};
+MonoFontSizes[15] = {height: 20, width: 9};
+
+function getMonoFontSize(fontSize : number) : {height : number, width : number} {
+ return MonoFontSizes[fontSize];
+}
function measureText(text : string, textOpts? : {pre? : boolean, mono? : boolean, fontSize? : number|string}) : DOMRect {
if (textOpts == null) {
@@ -28,4 +41,4 @@ function measureText(text : string, textOpts? : {pre? : boolean, mono? : boolean
return measureDiv.getBoundingClientRect()
}
-export {measureText};
+export {measureText, getMonoFontSize};