Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]

Krzysztof Kowalczyk blog

Krzysztof Kowalczyk...
New Edna feature: multiple notes I started working on Edna several months ago and I’ve implemented lots of functionality. Edna is a...
2 days ago
4
2 days ago
I started working on Edna several months ago and I’ve implemented lots of functionality. Edna is a note taking application with super powers. I figured I’ll make a series of posts about all the features I’ve added in last few months. The first is multiple notes. By default we...
Krzysztof Kowalczyk...
Desktop UI frameworks written by a single person Less known desktop UI frameworks Writing desktop software is hard. The UI technologies...
3 days ago
6
3 days ago
Less known desktop UI frameworks Writing desktop software is hard. The UI technologies of Windows or MacOS are awful compared to web technology. What can trivially be done with HTML/CSS/JavaScript in few minutes can take hours using Windows’s win32 APIs or Mac’s...
Krzysztof Kowalczyk...
Evolving Edna Ask AI UI This is a real life example of tweaking UI in Edna, my note taking application with super...
3 days ago
5
3 days ago
This is a real life example of tweaking UI in Edna, my note taking application with super powers. Ask AI is a simple AI chat: you write a question, send it to LLM model and get a response. Here’s my first version of the UI: What is good and bad about this version? Good: there’s...
Krzysztof Kowalczyk...
Implementing UI translation in SumatraPDF, a C++ Windows application Translating user interface of SumatraPDF SumatraPDF is the best PDF/eBook/Comic Book...
4 days ago
5
4 days ago
Translating user interface of SumatraPDF SumatraPDF is the best PDF/eBook/Comic Book viewer for Windows. It’s small, fast, full of features, free and open-source. It became popular enough that it made sense to translate the UI for non-English users. Currently we...
Krzysztof Kowalczyk...
Calling Grok, OpenAI, Anthropic, Google, OpenRouter API from the browser Here’s what I learned about calling LLM APIs from the browser when building AI chat functionality in...
4 days ago
6
4 days ago
Here’s what I learned about calling LLM APIs from the browser when building AI chat functionality in my note taking app Edna. The API I care about is getting LLM response to a question in a streaming way. OpenAI pioneered this and created...
Krzysztof Kowalczyk...
Case study of over-engineered C++ code You’ve heard of over-engineered, unnecessarily complex code but what exactly is it? I believe it’s...
5 days ago
7
5 days ago
You’ve heard of over-engineered, unnecessarily complex code but what exactly is it? I believe it’s best to show by example. While it’s not my intention to criticize other people’s code, I think it’s better to show code and how to improve it rather than vaguely talk about...
Krzysztof Kowalczyk...
Increase open file limit on Ubuntu Linux What and why of open file limit If you run a webapp on a Linux server, your webapp needs...
5 days ago
5
5 days ago
What and why of open file limit If you run a webapp on a Linux server, your webapp needs to open files and make network connections. Most Linux servers have horrible default for this and limit the number of opened files at the same time to e.g. 1024. To check the...
Krzysztof Kowalczyk...
Explaining nil interface{} gotcha in Go Explaining nil interface{} gotcha in Go A footgun In Go empty interface is...
6 days ago
9
6 days ago
Explaining nil interface{} gotcha in Go A footgun In Go empty interface is an interface without any methods, typed as interface{}. A zero value of interface{} is nil: var v interface{} // compiler sets this to nil, you could explicitly write = nil if v ==...
Krzysztof Kowalczyk...
Size textarea to content To size textarea to content: textarea { field-sizing: content; min-height: 8rem; max-height:...
a week ago
5
a week ago
To size textarea to content: textarea { field-sizing: content; min-height: 8rem; max-height: 70vh; } Using tailwindcss: <textarea class="min-h-[8rem] max-h-[70vh] field-sizing-content"></textarea> Needs Chrome 123+, Firefox 126+
Krzysztof Kowalczyk...
All about Svelte 5 snippets Snippets are a useful addition to Svelte 5. I use them in my Svelte 5 projects like Edna. Snippet...
a week ago
10
a week ago
Snippets are a useful addition to Svelte 5. I use them in my Svelte 5 projects like Edna. Snippet basics A snippet is a function that renders html based on its arguments. Here’s how to define and use a snippet: {#snippet hello(name)} <div>Hello...
Krzysztof Kowalczyk...
C++ engineering decision in SumatraPDF code SumatraPDF is a medium size (120k+ loc, not counting dependencies) Windows GUI (win32) C++ code base...
a week ago
11
a week ago
SumatraPDF is a medium size (120k+ loc, not counting dependencies) Windows GUI (win32) C++ code base started by me and written by mostly 2 people. The goals of SumatraPDF are to be: fast small packed with features and yet with thoughtfully minimal UI It’s not just a matter of...
Krzysztof Kowalczyk...
Bugs I fixed in SumatraPDF Unexamined life is not worth living said Socrates. I don’t know about that but to become a better,...
a week ago
11
a week ago
Unexamined life is not worth living said Socrates. I don’t know about that but to become a better, faster, more productive programmer it pays to examine what makes you un-productive. Fixing bugs is one of those un-productive activities. You have to fix them but it would be even...
Krzysztof Kowalczyk...
Implementation of optimized vector of strings in C++ in SumatraPDF SumatraPDF is a fast, small, open-source PDF reader for Windows, written in C++. This article...
a week ago
11
a week ago
SumatraPDF is a fast, small, open-source PDF reader for Windows, written in C++. This article describes how I implemented StrVec class for efficiently storing multiple strings. Much ado about the strings Strings are among the most used types in most programs. Arrays...
Krzysztof Kowalczyk...
Custom search UI in CodeMirror 6 and Svelte 5 CodeMirror 6 has @codemirror/search package which provides UI for searching within a document,...
a week ago
11
a week ago
CodeMirror 6 has @codemirror/search package which provides UI for searching within a document, triggered via Ctrl + F. In my note-taking application Edna I wanted something slightly different. This article describes how I implemented it. The UI went from: to: CodeMirror is very...
Krzysztof Kowalczyk...
Notion-like compact table of contents in JavaScript Large web pages, especially documentation, benefit from having a table of contents for navigating...
2 weeks ago
12
2 weeks ago
Large web pages, especially documentation, benefit from having a table of contents for navigating within document. This article describes how I implemented a compact table of contents for documentation page for my Edna note taking application as well as for this very blog. I was...
Krzysztof Kowalczyk...
Go is 80/20 language Go is the most hated programming language. Compared to other languages, it provides 80% of utility...
2 weeks ago
12
2 weeks ago
Go is the most hated programming language. Compared to other languages, it provides 80% of utility with 20% of complexity. The hate comes from people who want 81% of utility, or 85% or 97%. As Rob Pike said, no one denies that 87% of utility provides more utility than 80%. The...
Krzysztof Kowalczyk...
2025-06-25 Wed: Automatic Chrome Dev Tools workspace setup In Chrome Dev Tools you can setup a mapping between the files web server sends to the browser and...
2 weeks ago
9
2 weeks ago
In Chrome Dev Tools you can setup a mapping between the files web server sends to the browser and files on disk. This allows editing files in dev tools and having those changes saved to a file, which is handy. Early in 2025 they’ve added a way to automatically configure this...
Krzysztof Kowalczyk...
Automatic Chrome Dev Tools workspace setup In Chrome Dev Tools you can setup a mapping between the files web server sends to the browser and...
2 weeks ago
10
2 weeks ago
In Chrome Dev Tools you can setup a mapping between the files web server sends to the browser and files on disk. This allows editing files in dev tools and having those changes saved to a file, which is handy. Early in 2025 they’ve added a way to automatically configure this...
Krzysztof Kowalczyk...
How I made SumatraPDF crash less You don’t want your software to crash, do you? This post describes my experiences in making...
2 weeks ago
13
2 weeks ago
You don’t want your software to crash, do you? This post describes my experiences in making SumatraPDF crash less. SumatraPDF is a Windows desktop app. It’s a fast viewer for PDF, ePub, comic books etc.. It’s small and yet full of features. Know thy crashes The most...
Krzysztof Kowalczyk...
2025-06-23 Mon: activity More Edna porting.
2 weeks ago
Krzysztof Kowalczyk...
2025-06-23 activity More Edna porting.
2 weeks ago
Krzysztof Kowalczyk...
2025-06-22 Sun: Ban std::string The use of std::string should be banned in C++ code bases. I’m sure this statement sounds like...
2 weeks ago
9
2 weeks ago
The use of std::string should be banned in C++ code bases. I’m sure this statement sounds like heresy and you want to burn me at stake. But is it really controversial? Java, C#, Go, JavaScript, Python, Ruby, PHP: they all have immutable strings that are basically 2 machine words:...
Krzysztof Kowalczyk...
Compressing for the browser in Go Comparing gzip, brotli and zstd compression in Go. When a modern browser sends a HTTP...
2 weeks ago
11
2 weeks ago
Comparing gzip, brotli and zstd compression in Go. When a modern browser sends a HTTP request to a web server, it includes the following header: Accept-Encoding: gzip, deflate, br, zstd This tells the server that the response can be compressed using one of the...
Krzysztof Kowalczyk...
Ban std::string The use of std::string should be banned in C++ code bases. I’m sure this statement sounds like...
2 weeks ago
5
2 weeks ago
The use of std::string should be banned in C++ code bases. I’m sure this statement sounds like heresy and you want to burn me at stake. But is it really controversial? Java, C#, Go, JavaScript, Python, Ruby, PHP: they all have immutable strings that are basically 2 machine words:...
Krzysztof Kowalczyk...
2025-06-21 Sat: Thoughts on C/C++ killer There are several programming languages that are “better C/C++”: zig, odin, jai, D. The problem is...
3 weeks ago
12
3 weeks ago
There are several programming languages that are “better C/C++”: zig, odin, jai, D. The problem is adoption: it’s hard to break from all the code already written in C/C++. It’s too expensive to rewrite large code bases in new language. My idea on how to improve adoption: perfect...
Krzysztof Kowalczyk...
Thoughts on C/C++ killer There are several programming languages that are “better C/C++”: zig, odin, jai, D. The problem is...
3 weeks ago
4
3 weeks ago
There are several programming languages that are “better C/C++”: zig, odin, jai, D. The problem is adoption: it’s hard to break from all the code already written in C/C++. It’s too expensive to rewrite large code bases in new language. My idea on how to improve adoption: perfect...
Krzysztof Kowalczyk...
Implementing nested context menu in Svelte 5 I was working on Edna, my open source note taking application that is a cross between Obsidian and...
3 weeks ago
10
3 weeks ago
I was working on Edna, my open source note taking application that is a cross between Obsidian and Notational Velocity. It’s written in Svelte 5. While it runs in the browser, it’s more like a desktop app than a web page. A useful UI element for desktop-like apps is a nested...
Krzysztof Kowalczyk...
2025-06-20 Fri: Idea for code editors Added a daily notes section to the blog. It’s the one you’re reading right now. Data stored in...
3 weeks ago
10
3 weeks ago
Added a daily notes section to the blog. It’s the one you’re reading right now. Data stored in \daily_notes.md file. Trying Obsidian for editing markdown files I’m always looking for that perfect note taking / markdown editor. I’m even writing one (but it’s web based so not...
Krzysztof Kowalczyk...
Idea for code editors Added a daily notes section to the blog. It’s the one you’re reading right now. Data stored in...
3 weeks ago
4
3 weeks ago
Added a daily notes section to the blog. It’s the one you’re reading right now. Data stored in \daily_notes.md file. Trying Obsidian for editing markdown files I’m always looking for that perfect note taking / markdown editor. I’m even writing one (but it’s web based so not...
Krzysztof Kowalczyk...
Optimizing calling Windows DLL functions in Go Go team wrote golang.org/x/sys/windows package to call functions in a Windows DLL. Their way is...
3 weeks ago
14
3 weeks ago
Go team wrote golang.org/x/sys/windows package to call functions in a Windows DLL. Their way is inefficient and this article describes a better way. The sys/windows way To call a function in a DLL, let’s say kernel32.dll, we must: load the dll into memory with...
Krzysztof Kowalczyk...
Simplest C++ callback, from SumatraPDF SumatraPDF is a Windows GUI application for viewing PDF, ePub and comic books written in C++. A...
3 weeks ago
19
3 weeks ago
SumatraPDF is a Windows GUI application for viewing PDF, ePub and comic books written in C++. A common need in GUI programs is a callback. E.g. when a button is clicked we need to call a function with some data identifying which button was clicked. Callback is therefore a combo...
Krzysztof Kowalczyk...
Why Go iterators are ugly, clever and elegant Go 1.23 adds iterators. An iterator is a way to provide values that can be used in for x := range...
a month ago
15
a month ago
Go 1.23 adds iterators. An iterator is a way to provide values that can be used in for x := range iter loops. People are happy the iterators were added to the language. Not everyone is happy about HOW they were implemented. This person opined that they demonstrate “typical Go...
Krzysztof Kowalczyk...
Showing UI on mouse move, in Svelte 5 In my note taking application Edna I’ve implemented unorthodox UI feature: in the editor a top left...
a month ago
19
a month ago
In my note taking application Edna I’ve implemented unorthodox UI feature: in the editor a top left navigation element is only visible when you’re moving the mouse or when mouse is over the element. Here’s UI hidden: Here’s UI visible: The thinking is: when writing, you want...
Krzysztof Kowalczyk...
Man vs. AI: optimizing JavaScript (Claude, Cursor) How AI beat me at code optimization game. When I started writing this article I did not...
10 months ago
77
10 months ago
How AI beat me at code optimization game. When I started writing this article I did not expect AI to beat me at optimizing JavaScript code. But it did. I’m really passionate about optimizing JavaScript. Some say it’s a mental illness but I like my code to go balls to...
Krzysztof Kowalczyk...
Implementing Notion-like table of contents in JavaScript Notion-like table of contents in JavaScript Long web pages benefit from having a table...
10 months ago
84
10 months ago
Notion-like table of contents in JavaScript Long web pages benefit from having a table of contents. Especially technical, reference documentation. As a reader you want a way to quickly navigate to a specific part of the documentation. This article describes how I...
Krzysztof Kowalczyk...
Porting a medium-sized Vue application to Svelte 5 Porting a medium-sized Vue application to Svelte 5 The short version: porting from Vue...
a year ago
77
a year ago
Porting a medium-sized Vue application to Svelte 5 The short version: porting from Vue to Svelte is pretty straightforward and Svelte 5 is nice upgrade to Svelte 4. Why port? I’m working on Edna, a note taking application for developers. It started as a...
Krzysztof Kowalczyk...
Changing font size in Windows dialog in C++ How to dynamically change font size in a Windows dialog Windows’s win32 API is old and...
a year ago
76
a year ago
How to dynamically change font size in a Windows dialog Windows’s win32 API is old and crufty. Many things that are trivial to do in HTML are difficult in win32. One of those things is changing size of font used by your native, desktop app. I encountered this in...
Krzysztof Kowalczyk...
How I implemented wc in the browser in 3 days Building wc in the browser From time to time I like to run wc -l on my source code to...
over a year ago
28
over a year ago
Building wc in the browser From time to time I like to run wc -l on my source code to see how much code I wrote. For those not in the know: wc -l shows number of lines in files. Actually, what I have to do is more like find -name "*.go" | xargs wc -l because wc isn’t...
Krzysztof Kowalczyk...
Ideas for replit bounties Apparently replit asks all Pro users about their thoughts. As it happens, I have a lot of thoughts...
over a year ago
25
over a year ago
Apparently replit asks all Pro users about their thoughts. As it happens, I have a lot of thoughts about how to improve Replit bounties. Lower transaction costs Currently the process is: I post a bounty one or more people apply I select an applicant they do the work I...
Krzysztof Kowalczyk...
Advanced markdown processing in Go Using gomarkdown/markdown library This article describes an advanced markdown processing...
over a year ago
25
over a year ago
Using gomarkdown/markdown library This article describes an advanced markdown processing in Go using gomarkdown/markdown library. All the code examples are available at https://github.com/gomarkdown/markdown/tree/master/examples Basics first Here’s a good...
Krzysztof Kowalczyk...
Persisted Svelte store using IndexedDB I’m working on notepad2 for web and I need a history of opened files that persists across browser...
over a year ago
27
over a year ago
I’m working on notepad2 for web and I need a history of opened files that persists across browser session. Since I’m using Svelte, having it available as a store makes sense. This article describes how to implement a Svelte store whose values are persisted in IndexedDB. What is...
Krzysztof Kowalczyk...
Find programming work by increasing luck surface area Antonio asked on HN: How do I earn a small amount of money to sustain myself as a developer? I wrote...
over a year ago
24
over a year ago
Antonio asked on HN: How do I earn a small amount of money to sustain myself as a developer? I wrote a response centered around increasing luck surface area. This essay expands on it because I’ve seen this a few times now: good developers asking how to find work while botching...
Krzysztof Kowalczyk...
Extreme #include discipline for C++ code C++ takes long to compile There is more than one reason for it but one of the reasons is excessive...
over a year ago
27
over a year ago
C++ takes long to compile There is more than one reason for it but one of the reasons is excessive re-parsing of the same .h header files. In SumatraPDF I’m using an extreme #include discipline to keep compilation times in check. The rule is simple: a .h file cannot #include...
Krzysztof Kowalczyk...
@levelsio and survivorship bias Pieter Levels is a prolific maker of software. He’s also very successful maker of software: he’s...
over a year ago
32
over a year ago
Pieter Levels is a prolific maker of software. He’s also very successful maker of software: he’s close to making $1.5 million a year from his business, almost all of it profit. Almost all of it is his profit since for most of the time he was a sole developer / marketer / copy...
Krzysztof Kowalczyk...
Lessons learned from 15 years of SumatraPDF, an open source Windows app I released first version of SumatraPDF in 2006. That’s 15 years ago which seems like a good time for...
over a year ago
40
over a year ago
I released first version of SumatraPDF in 2006. That’s 15 years ago which seems like a good time for a retrospective. The app SumatraPDF is a multi-format (PDF, ePub, Mobi, comic book, DjVu, XPS, CHM) viewer for Windows and currently looks like this: The...
Krzysztof Kowalczyk...
How I use Roam Research I take lots of notes and I’m always looking for that perfect note taking app. Because I take a lot...
over a year ago
25
over a year ago
I take lots of notes and I’m always looking for that perfect note taking app. Because I take a lot of notes, mobile-first note taking apps (e.g. Google’s Keep) are of no interest to me. To me most important thing is: lowest possible friction in adding new notes fast way of...
Krzysztof Kowalczyk...
The things we do to ship desktop software I wrote a small utility for Windows. It indexes a hard-drive and allows to find a file by name in...
over a year ago
26
over a year ago
I wrote a small utility for Windows. It indexes a hard-drive and allows to find a file by name in under a second. It might surprise you that I spent more time on things that are not related to core functionality. Let’s call it a tax of shipping desktop software. Here are some of...
Krzysztof Kowalczyk...
Lessons learned porting 50k loc from Java to Go I was contracted to port a large Java code base to Go. The code in question is a Java client for...
over a year ago
27
over a year ago
I was contracted to port a large Java code base to Go. The code in question is a Java client for RavenDB, a NoSQL JSON document database. Code with tests was around 50 thousand lines. The result of the port is a Go client. This article describes what I’ve learn in the...
Krzysztof Kowalczyk...
Trade offs in designing versatile log format This article shows that when designing software even seemingly simple things are complicated and...
over a year ago
26
over a year ago
This article shows that when designing software even seemingly simple things are complicated and trade offs abound. I wanted to log events to a file. I had several requirements for my design: it should be simple and therefore easy to implement it should be human-readable it...
Krzysztof Kowalczyk...
How I implemented Oembed Proxy for GitHub Why Oembed Proxy for GitHub I’m writing a programming book Essential Go in Notion and I...
over a year ago
25
over a year ago
Why Oembed Proxy for GitHub I’m writing a programming book Essential Go in Notion and I need to include code snippets. Notion has support for code blocks but it’s not good enough for my use case. I want to make sure the code compiles so I write small programs and...
Krzysztof Kowalczyk...
Powering a blog with Notion and Netlify The last iteration of this blog was a Go program running on Digital Ocean’s cheapest VM...
over a year ago
25
over a year ago
The last iteration of this blog was a Go program running on Digital Ocean’s cheapest VM ($5/month). Recently I’ve made 2 big changes: I converted it to a static site hosted on Netlify I used Notion for writing the posts instead of writing markdown files in a text editor Moving to...
Krzysztof Kowalczyk...
How I reverse engineered Notion API Notion is a great tool for writing but the content is trapped inside the web app. The company is...
over a year ago
24
over a year ago
Notion is a great tool for writing but the content is trapped inside the web app. The company is working on an official API but I’m impatient. This article describes how I reverse engineered their API and created a Go library notionapi. It all began with a failure. My...
Krzysztof Kowalczyk...
Advanced web spidering with Puppeteer Puppeteer is a node.js library that makes it easy to do advanced web scraping and spidering. Older...
over a year ago
27
over a year ago
Puppeteer is a node.js library that makes it easy to do advanced web scraping and spidering. Older generation of web scraping and spidering tools would grab and analyze HTML pages as returned by a web server. It doesn’t work well anymore because less and less website are static...
Krzysztof Kowalczyk...
57 MicroConf videos for self-funded software businesses MicroConf is a conference for small/indie/self-funded software businesses. Many of their talks are...
over a year ago
30
over a year ago
MicroConf is a conference for small/indie/self-funded software businesses. Many of their talks are available on Vimeo but not well indexed. They have a better index (and another here) on their website, but also not great. This is a list of videos and a bit of info about each...
Krzysztof Kowalczyk...
Guide to predefined macros in C++ compilers (gcc, clang, msvc etc.) When writing portable C++ code you need to write conditional code that depends on compiler used or...
over a year ago
31
over a year ago
When writing portable C++ code you need to write conditional code that depends on compiler used or the OS for which the code is written. Here’s a typical case: #if defined (_MSC_VER) // code specific to Visual Studio compiler #endif To perform those checks you need to check...
Krzysztof Kowalczyk...
Tutorial for github.com/kjk/flex Go package (implementation of CSS flexbox algorithm) Package github.com/kjk/flex implements CSS flexbox layout algorithm in Go. It’s a pure Go port of...
over a year ago
23
over a year ago
Package github.com/kjk/flex implements CSS flexbox layout algorithm in Go. It’s a pure Go port of Facebook’s Yoga C library. High-level API overview Despite implementing CSS flexbox spec, it isn’t tied to CSS/HTML in any way. Yoga, for example, can be integrated with...
Krzysztof Kowalczyk...
Solo founders with profitable businesses, collected stories People sometimes wonder: can I have a successful business as a single founder? The answer is:...
over a year ago
25
over a year ago
People sometimes wonder: can I have a successful business as a single founder? The answer is: yes. This is a collection of solo-preneur success stories (with occasional 2 people bands). I only include businesses generating significant revenues. In this context it’s around $5k/mo...
Krzysztof Kowalczyk...
Analyzing browserify bundles to minimize JavaScript bundle size When building web apps, it’s important to keep the size of JavaScript code delivered to the browser...
over a year ago
26
over a year ago
When building web apps, it’s important to keep the size of JavaScript code delivered to the browser as small as possible. I write in ES6 or TypeScript then use browserify to combine all JavaScript code into a single bundle file. For production builds I use uglify to make the...
Krzysztof Kowalczyk...
Optimizing JavaScript by using arrays instead of objects Best optimizations are achievied by thinking about a problem holistically. In this article I...
over a year ago
26
over a year ago
Best optimizations are achievied by thinking about a problem holistically. In this article I describe an optimization that uses arrays instead of classes while providing a class API for accessing data. Imagine you’re building a web-based note taking application. It uses modern,...
Krzysztof Kowalczyk...
Go package for better guid generation The need to generate a globally unique identifier comes up often. The way described in RFC 4122 is...
over a year ago
23
over a year ago
The need to generate a globally unique identifier comes up often. The way described in RFC 4122 is popular but it can be done better. I wrote betterguid Go package that does it better. Unique id generated by this package: is a 20 character string, safe to include in urls (no need...
Krzysztof Kowalczyk...
Tip for per-test verbose logging in Go One way to narrow down a problem when debugging a test is to add logging with e.g. fmt.Printf(). The...
over a year ago
21
over a year ago
One way to narrow down a problem when debugging a test is to add logging with e.g. fmt.Printf(). The problem with this approach is lack of selectivity: imagine you have 100 tests and only 1 test fails. For debugging the issue you only need to see logs when executing that 1 test...
Krzysztof Kowalczyk...
SumatraPDF 3.0 released We, the SumatraPDF developers have released a version 3.0 of Sumatra, a multi-format reader (PDF,...
over a year ago
24
over a year ago
We, the SumatraPDF developers have released a version 3.0 of Sumatra, a multi-format reader (PDF, epub and mobi ebooks, comic books, etc.) for Windows. You can download it from official SumatraPDF website The biggest change in this version is addition of tabs, contributed by...
Krzysztof Kowalczyk...
SumatraPDF 2.5.2 released We, the SumatraPDF developers have released a version 2.5.2 of Sumatra, a PDF and ebook reader for...
over a year ago
24
over a year ago
We, the SumatraPDF developers have released a version 2.5.2 of Sumatra, a PDF and ebook reader for Windows. Changes in this release: 2 page view for ebooks new keybindings: Ctrl+PgDn, Ctrl+Right : go to next page Ctrl+PgUp, Ctrl+Left : go to previous page 10x faster ebook...