18 ms·
Building a new Windows 3.1 app in 2019: A Slack Client
- devit 7y agoIf the target was just "Windows 3.1", he should have built a 32-bit app using the Win32s API [https://en.wikipedia.org/wiki/Win32s https://en.wikipedia.org/wiki/Win32s] It's also probably possible to use a current compiler, maybe clang or gcc, to compile such code (officially only up to VC++ 4.2 is supported), although it might require some hacks.
- yeokm1 7y agoI built a Win 3.1 app during a company hackathon just for fun. Here, I detail learnings and process for how a new old app can be created with the aid of modern tools and hindsight of old technologies. And perhaps what lessons can it offer us today. Without the benefit of modern libraries and languages, I had to read up and take care of many low level details, socket programming, HTTP, JSON parsing, UI design in code all under tight memory constraints. Nevertheless, it was a terrific lesson in understanding how things work under the hood. I had to do things the old-fashioned way reading books and header files due to the dearth of online documentation. I can empathise with the plight of the programmers of yesteryears who had to code without the benefit of online search engines. With this blog post, I hope you'll find it interesting to learn about developing a modern-ancient app for Win 3.1. https://github.com/yeokm1/w31slack https://github.com/yeokm1/w31slack https://github.com/yeokm1/http-to-https-proxy https://github.com/yeokm1/http-to-https-proxy
- dboreham 7y agoPrior to online search engines there were similar offline resources such as the MSDN CDs.
- yeokm1 7y agoAgreed. But such CDs are tough to locate today.
- homarp 7y agomaybe https://archive.org/details/msdncds https://archive.org/details/msdncds can help
- whoopdedo 7y agoBorland's compilers had the best documentation. They included a much of the MSDN API reference in their built-in help files.
- yeokm1 7y agoHmm. Borland and Watcom compilers came up in my research. Will look into them for help next time!
- jbverschoor 7y agoYeah Borland was great with docs
- deleted 7y ago[deleted]
- efreak 7y agoThe Eye might have these, they have a bunch of old Microsoft/msdn related stuff.
- deleted 7y ago[deleted]
- 7y ago
- yeokm1 7y agoUnsure why it goes to twitter. Here is the blog post. http://yeokhengmeng.com/2019/12/building-a-new-win-3-1-app-in-2019-part-1-slack-client/ http://yeokhengmeng.com/2019/12/building-a-new-win-3-1-app-i...
- dang 7y agoChanged now from https://twitter.com/gravislizard/status/927593460642615296 https://twitter.com/gravislizard/status/927593460642615296. Edit: oh, I see what happened now. We made a mistake, intending to set the URL for https://news.ycombinator.com/item?id=21831931 https://news.ycombinator.com/item?id=21831931. Sorry!
- ink_13 7y agoReading this article and others by the same author on his travails of getting Windows 3.11 to install and then bridging it to modern(-ish) tech was like being transported back to the 90s when I was first learning about computers. Seeing those screenshots of the unmistakable Win 3.1-style dialogs was a real nostalgia hit. What a treat. 10 points (well, an upvote, I guess) for anyone who knows why the Windows DOS-mode installer says "Press F3 to exit"
- carey 7y agoAre you asking why it’s F3 as opposed to some other key? Because that would be from the IBM CUA standard: https://en.wikipedia.org/wiki/IBM_Common_User_Access https://en.wikipedia.org/wiki/IBM_Common_User_Access.
- ink_13 7y agoYep, that's what I was thinking of. F5 for refresh is another artifact from that time.
- Iv 7y agoI seem to recall that F1 and F2 had some sort of hard wired functions (that were printed on my keyboard) but I don't remember which they were...
- boring_twenties 7y agoF1 was already Help by then I'm pretty sure
- deleted 7y ago[deleted]
- dfox 7y agoThere was never any that much hardwired functions for F1 and F2 on PC (apart for the convention that F1 is almost always help). On the other hand there is a related issue: on DEC (and some other) terminals with LK201-style keyboards (which in turn inspired the "modern" PC/AT keyboard layout with F1-F12) the keys in positions of F1-F5 had fixed functions. This is the reason why there are about four different escape sequences across vt220-compatible terminal emulators for F5. There simply was not any DEC terminal that had F5 on its keyboard (F1-F4 are almost always mapped to PF1-PF4).
- Ididntdothis 7y agoWindows 3.1 and 16 bit would be a little too painful for me. Windows 95 was quite nice with 32 bit and preemptive multitasking though. I kind of miss this or Windows 2000.
- vardump 7y agoNT4 was very nice, although no USB. Didn't crash and was smooth as butter.
- deleted 7y ago[deleted]
- 1996 7y agoI find this history so super interesting. Have you kept a nt4? Do you still use it? What do you think is the closest equivalent: win200, reactos??
- vardump 7y agoNo, I haven't used it since early 2000. Windows 2000 was the successor, also a good release. I guess both are pretty close to what NT4 was.
- cr0sh 7y agoLast time I "used" NT4 it was to set up a machine for a specific piece of software so I could test a SICK 2D LIDAR unit (one of the blue "coffee pot" units) I had purchased off Ebay; sometime around 2014/15 IIRC. Initially turned out that it had been set to RS485 mode, and I didn't have an adapter, and I didn't even know if it worked if I was able to get it into that mode. So with the help of a sympathetic engineer at SICK, he had me send to unit to them and he reset it (to RS232) and tested it. When I got it back, I tested it with the machine again and it worked perfectly. He didn't charge me anything for the service. You don't see that kind of support anymore - almost no company will say "yeah, sure, send us a unit you bought second-hand off Ebay to us and we'll take a look at it, fix it, etc - and no charge to you, either - even though you're just a hobbyist and have no support contract" - it shocked me.
- deleted 7y ago[deleted]
- asveikau 7y agoThis presents c89 as the most antiquated thing in the world, but VS didn't support mixed declarations and code in a .c file until 2015. There is still a lot of code out there that avoids this to be able to work with MS's compilers.
- deleted 7y ago[deleted]
- ygra 7y ago... in C mode, which is basically C89 (+ whatever is needed for recent C++ versions). Compiling C code in C++ mode is a common way of working around this. But MSVC is not a C compiler, it's a C++ compiler, so their unwillingness to invest in C is probably understandable.
- barrkel 7y agoCould have done it with C++, would have worked for calling WinAPI too.
- asveikau 7y agoIf there are gripes about c89 I don't want to think about how different c++ support would be relative to the late 90s or early to mid 2000s, let alone now.
- cesarb 7y agoIt's now 2019, and as far as I know, MSVC still doesn't have full support for the 20-year-old C99 standard.
- asveikau 7y agoShortly after my comment I remembered that even in c99 or c++, there are patterns where mixed declaration and code are messy. WndProc switch statements is one example. You can't jump past a declaration of the same scope, so a case label can't declare anything unless you add curly braces.
- ben174 7y agoIt’s unfortunate slack is this difficult to integrate with. Jabber or IRC clients could be spun up with zero pain.
- Tepix 7y agoShow us :-) I'm sure writing mIrc was not "zero pain" back in the day. And Jabber needs a XML parser which is more complex than a JSON parser.
- anthk 7y agoJust use Bitlbee and MIRC. Done, Jabber client for Windows 3.1. And Telegram, and whatever Bitlbee and/or Libpurple supports.
- anthk 7y agoThere are tiny XML parsers out there. Also, an IRC client is a joke, it can be compiled and built even on BSD 4.3, released in late 80's. The suckless guys created some IRC clients in few lines, and the sj client is not that difficult. Heck, you could write an IRC client with Bash and even with Netcat/ed.
- arianvanp 7y agoA streaming; normalizing XML parser doesn't sound like a lot of fun to implement in C89 to me :)
- jojo9978 7y agoOMG, this is amazing tutorials bro
- wnoise 7y agosnprintf() may not be C89, but fgets() sure is.
- yeokm1 7y agoNoted. Will update my blog post!
- mkj 7y agoAaw cheating with https. I wonder if an embeddable library like BearSSL would be hard to get working.
- xeeeeeeeeeeenu 7y agoRelated: winevdm makes running 16-bit apps on 64-bit Windows possible: https://github.com/otya128/winevdm https://github.com/otya128/winevdm
- yeokm1 7y agoOh I did not know about this! I just based my understanding from the official Microsoft documentation. Thanks!
- fsiefken 7y agothis is great, didn't know about this - now which 16 bit windows apps I want to run that haven't been ported or updated yet? i can't really remember
- efreak 7y agoUnfortunately, even this isn't perfect. For example, when running Tetris from WEP, the colors are off/weird (I'm guessing a color depth issue). It is, however, good enough to run just about any old crap I've given it.
- JordanFarmer 7y agoNice, Would have been a lot using with Visual Basic 4, but I guess easy wasn't the point.
- tluyben2 7y agoSame with Delphi. We did decades of applications going from Turbo Pascal in the 80s to Delphi in the 90s and 00s and 10s without hardly any changes (this was possible because I wrote a tooling to convert the DOS Pascal graphics code to Delphi Windows automatically so we ran 1 version of code that compiled on both) right up until the company was sold a couple of years ago.
- haecceity 7y agoThis is a lot of work to avoid using that WYSIWYG editor.
- thenewnewguy 7y agoThere's an option to disable the WYSIWYG editor now :) Unfortunately, it still doesn't work as good as before: text like `Object`s (no space between the ending ` and next text) doesn't work anymore, and according to Slack's support this is 'working as intended'.
- coryrc 7y ago> Therefore, if one wants to write an app using Windows OS standard APIs, WFW 3.11 is the oldest one can go back without putting in even more exponential effort. Hey, what's wrong with Trumpet Winsock? :-)
- userbinator 7y agoNotice the binary size of the app is only 64KiB. In the demoscene this would be a disqualification as it's 676 bytes over the limit, but in this case I'll overlook it because of the sheer awesomeness of what you've done (and I'm sure trimming off 676 bytes wouldn't be too difficult ;-) More seriously, this is an excellent proof-of-concept that a Slack client does not need to use hundreds of MB of RAM and consume most of a modern CPU core to provide its basic functionality. I'm a long-time Win32 programmer who started in the tail-end of the Win16 days and one of the things I've wanted to write if I had the time and need was a Win32 native Slack client, to show that it can be done with far less resources, but you've gone even further with Win16. Win32 has native TLS support (via SChannel library, not well-documented but examples exist) and you'd be able to even use it practically (32-bit applications will run on all current versions of Windows, both 32 and 64-bit.) Note that C89 only prevents declarations of variables in the middle of a scope; you can simply create an inner scope with new variable declarations at its start. Like so... case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); ... } Another small tip: if you make it a dialog-based application, you won't have to bother with WM_PAINT and drawing text yourself --- you can just make the "statusText" and "settingsText" edit controls, and use SetWindowText (or SetDlgItemText) to set their content. They will paint themselves automatically just like the listboxes that you used for the chat contents and userlist. At least you'll save some of those 676 bytes that way...
- tomjen3 7y agoI can't help but agree with you. Honestly I think it went to hell when we decided that it was acceptable to call an electron app native, but that may have been a symptom, not a cause.
- DaiPlusPlus 7y agoBefore Electron people had the arguments about bloated apps when it came to WPF and Qt. And Java apps, like WPF (and most Qt apps I’ve used lately) lacks true integration with native OS widgets so as a user I get an uncanny-valley feeling. At least with Electron you’re essentially forced to style everything - and ever since Windows 8 (or Windows Vista) Microsoft has been actively uglifying native widgets.
- lspears 7y agoBravo
- andraganescu 7y agoThis is so amazing, I love all you people who take the time to do these super mega awesome tinker/fun projects and then share them with to the world!
- frabert 7y agoAs a side note, since TFA mentions you can't run 16b apps on 64b Windows, I'd like to mention that otvdm/winevdm actually allows you to do it by running Win16 apps on Win32 using Wine!
- yeokm1 7y agoThanks for raising this to me!
- int_19h 7y agoI wonder how much easier this would have been in Borland C++ or Borland Pascal with OWL. Or even Delphi! Delphi 1 targeted Win16.
- amluto 7y agoYou can probably run this app using WINE on any modern Linux 64-bit system. Or maybe even Mac OS X Catalina. (The Linux x86 maintainers are semi-seriously considering deprecating the horrible machinations needed for 16-bit on 32-bit to work, but 16-bit on 64-bit Will be supported for the foreseeable future.)
- deleted 7y ago[deleted]
- jamil7 7y agoDo the public slack APIs offer enough to built a third party client?
- yeokm1 7y agoI felt it was enough for me. :) https://api.slack.com/ https://api.slack.com/
- jamil7 7y agoThanks! given the amount of complaining about slack on HN I thought someone would have produced a native open source client by now. I might look into it.
- lsferreira42 7y agoYes, it does!
- folmar 7y agoAnd weechat-slack is great.
- sneak 7y ago> Purists may not like this solution but this is the best I can do with my abilities in a reasonable amount of time. I am going to be using this line a lot in the future.
- Jaruzel 7y ago> Windows 10 [...] cannot directly talk to the ancient SMB protocol used by WFW 3.11. Not true, you can downgrade the SMB version requirement in the Windows 10 registry.
- peteri 7y agoBut then you'll have to spend the rest of your life dodging Ned Pyle of Microsoft.
- EliRivers 7y agoPetzold is Gold. I have a copy of the Fifth Edition that I bought new and I expect it to remain useful for some time yet.
- Multicomp 7y agoFwiw programming windows by Petzold through the 5th edition covers native Windows development through Windows XP. The sixth edition on words begins to use the. Net CLR and other non-native toolchains as Microsoft changed them. So, those are less valuable to me. If you want to do native Windows development, that is probably the single best book you could buy.
- mhd 7y agoI'm a bit disappointed that the code doesn't appear to use Whitesmith style...
- agumonkey 7y agoWhen I found a win95 box with tp7 on it, my first thought was to write 'modern' things on it. HTTPS, Haskell... I starter writing a lisp. Didn't finish sadly. Because i love the idea of bridging 'old' with the good parts of 'new'
- kleiba 7y agoI had to do things the old-fashioned way reading books and header files [...] O tempora o mores! I'm getting old...
- xg15 7y ago> The stack size of a 16-bit program is typically 4-6 KiB with a similar size for the heap. This is smaller than the size of the HTTP reply + JSON returned by Slack! Maybe this would be a good opportunity to stop for a moment and reflect about whether or not the industry is really moving in the right direction.
- winrid 7y agoI'm not sure slack actually uses these apis in their own app? They use websockets for a lot of the communication right? In which case the server just pushes small messages.
- robmccoll 7y agoYou could avoid the copy out of the JSON string by using a field width specifier in your printf formatting string. Those should be available in ANSI C / C89/90. currentToken = tokens[index]; tokenSize = currentToken.end - currentToken.start; if(tokenSize <= 0){ continue; } printf("Current token %.*s\n", tokenSize, startOfJson + currentToken.start);
- vardump 7y agoOne of those things usually only people who've written printf format parser know.
- yeokm1 7y agoThe printf is just for example code. In actual fact, I'll have to copy the data to a char array to be sent to display in the listbox.
- robmccoll 7y agoFair enough. I read this quite literally and thought "not exactly": > hence I need to use those values to copy out from memory to a separate char array for printing purposes. Certainly not so trivial.
- ct520 7y agoReading how he cheated with proxy. That was what I wanted to see. :( Had a client of a enterprise style company integrate into one of our products. Dude was the definition of cowboy coder so we often looked at logs. All I can say is wow - them logs for negotiating a https connection in BASIC..
- 1996 7y agoplease tell us more!
- deddo 7y agoThis is amazing, very well done. I think every programmer should from time to time build something for a very old platform and appreciate the progress achieved so far.
- Endy 7y agoBy which you mean that they'll recognize everything that's been stolen from the users, right? Win 3.1 & DOS was probably about the last time I really felt in control of my PC.
- fortran77 7y agoAnother option would have been Turbo Pascal for Windows 3.1 https://en.wikipedia.org/wiki/Turbo_Pascal#Turbo_Pascal_for_Windows https://en.wikipedia.org/wiki/Turbo_Pascal#Turbo_Pascal_for_...
- ufmace 7y agoAfter the first few paragraphs, I was most eager to see how he managed to handle modern TLS on Win3.1. Last time I wrangled with vintage stuff near that timeframe, that was the toughest part. Alas, he "cheated" for it with a proxy app. Can't say I blame him, since it's probably about as much work over again to get modern TLS 1.2 working on such an old Windows.
- yeokm1 7y agoIf someone has got a working TLS 1.2 on such an old OS, I'll like to know too. Because I certainly haven't saw any example. I think the work to get TLS 1.2 working will certainly dwarf the work on this Slack app.
- collinmanderson 7y agoYes I was curious about that too. Cheater. :) Seems to me you'd pretty much have to write a simple TLS 1.2 or 1.3 client by hand, or port an existing simple implementation. But yeah, makes sense as it would be way too much work.
- userbinator 7y agoIMHO the fact that it's hard to get TLS 1.2 (or indeed any form of "pure" cryptography) working at all on an obscure platform says a lot about the state of commonly available crypto libraries --- as those who are against regulating it like to say, it's "just math"; and math that any computer should theoretically be able to do. OpenSSL is one of the more portable ones, yet I'm not sure how it would be able to handle the 64K segmented model. It would need at least 32KB (maximum TLS record size, multiplied by both directions) and a little bit more per TLS connection. That said, a 2048-bit RSA key is "only" 256 bytes, and ECDH ones are smaller, so I think a TLS 1.2 (or even 1.3) implementation on the platform is definitely in the area of "feasible, but not trivial". A lot of IoT stuff has similar constraints (minus the segmented addressing).
- theandrewbailey 7y ago> Also, we can’t write our code directly on the Windows 2000 VM as it has limited software support for modern IDEs like Visual Studio Code not to mention security issues. I'm guessing that Visual C++ 1.52 has no code editing capabilities like Visual Studio?
- yeokm1 7y agoVC++ 1.52 has an internal text editor but nowhere near the capabilities of Visual Studio Code or any modern text editors. I also use Git and sourcetree and they won't run on Win 2K.
- breadandcrumbel 7y agoI'm pretty surprised to see slack client exists for Windows 3.1 before modern platforms
- breadandcrumbel 7y agoSo a properly native Slack client exists for Windows 3.1 before modern platforms? Whaat the hell?
- Shorel 7y agohttps://news.ycombinator.com/item?id=19617699 https://news.ycombinator.com/item?id=19617699
- deleted 7y ago[deleted]
- butz 7y agoConsidering that Windows 3.1 takes less space than Electron binary, one can actually run this program in VM and get better performance and less RAM usage than official app.
- Shorel 7y agoFor Slack without Electron there's Ripcord It runs in Windows, Mac and Linux https://news.ycombinator.com/item?id=19617699 https://news.ycombinator.com/item?id=19617699
- zzo38computer 7y agoI have DOSBOX, but Windows 3.1 runs very slowly on DOSBOX.
- anthk 7y agoI was running win 3.1 under DOSBox fastly since forever (athlon days). You may have some CPU settings wrong.
- yeokm1 7y agoI updated my blog post to include a memory and disk usage comparison :)
- nitwit005 7y agoDisappointed not to see the now deprecated WSAAsyncSelect function in use. It was their extension to make sockets play nicely with the UI event loop. They needed some way that you could be waiting for either window messages or socket data. Otherwise your window would stop responding to input or repaint itself if some socket operation blocked.
- thrower123 7y agoEveryone really should be made to code up a few Win32 apps, at least, before they are allowed to make an Electron app, just so they can get a real sense of what the trade-offs actually are, instead of relying on hearsay and FUD.
- bensherman228 7y agoCool tutorial, I read an article about ideas for mobile applications (https://mwdn.com/mobile-app-ideas-2020-how-to-create-something-new/ https://mwdn.com/mobile-app-ideas-2020-how-to-create-somethi...) and now I want to create my own, there is one idea about how to create another application from one application, I read your article and was inspired. thanks :)