From 5a18c94e415ce232a7092c15fe0ffbbba61861c3 Mon Sep 17 00:00:00 2001 From: Toyoyo Toyo Date: Wed, 13 Jul 2022 15:45:46 +0200 Subject: [PATCH] Initial version --- Makefile | 13 +++ README.md | 17 +++ copying.txt | 14 +++ res/icon.ico | Bin 0 -> 2238 bytes w3bat.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++ w3bat.ini | 5 + w3bat.rc | 25 +++++ 7 files changed, 383 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 copying.txt create mode 100644 res/icon.ico create mode 100644 w3bat.c create mode 100644 w3bat.ini create mode 100644 w3bat.rc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a72e2fe --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +WRC=wrc +CC=wcl +CFLAGS=-l=windows -bt=windows -fe=w3bat.exe -ot +LIBS=ole2.lib + +all: + $(WRC) -q -zm -bt=nt -r -fo=w3bat.res w3bat.rc + $(CC) $(CFLAGS) $(LIBS) w3bat.c w3bat.res + +clean: + rm -f w3bat.exe + rm -f w3bat.o + rm -f w3bat.res diff --git a/README.md b/README.md new file mode 100644 index 0000000..915eb39 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# W3Bat +An APM 1.0+ Battery charge monitor for windows 3.1 + +## Building +To build this, you need the following: +* GNU make +* OpenWatcom (tested on 2.0 beta) + +## Prerequistes +* Windows 3.1 +* Also works in any later version, provided win16 compatibility and APM BIOS + +## w3bat.ini settings +* font: font name to use. fixed-width font assumed. +* size: font size +* x: window's horizontal position +* y: window's vertical position diff --git a/copying.txt b/copying.txt new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/copying.txt @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/res/icon.ico b/res/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..83b7b56a2464abe8f7adc1107028ddd4902adc0f GIT binary patch literal 2238 zcmchWc~sQb6~{kmT4PO2Oq-gf8)`ICtb~|qV<9RML_k)D5y1@*g`kLlC?NZ=j}X=o z8DL*a|~gfR<3 zMR<98u`pcBB8fHn5gS=7v1f7227LT{u?lnHz#%_$;>0YIT5>Sp5c*Ovx``WEkzh|? za3H2f90&>xW>dT?>pt7gQkjU*h%l^Eors8%V4S|2$e1WhGMxD^%aOJ6?KsFj#URTG zqpTgoO5<3Sc>ojTR-}nXu*lxWT7?hG3%6md^dKoUnfFUvuqYDVl6QdZc?U5m-bG4! zDxxBHtV&!-JDQGJnL8g>?8d&tmz{-&F+R1I&1IfgRJxKOKZaeU2aXl{aXcA;JSPk1 zvLM8jzL-^eU{>YL&hki>*Lq`H_3-EaCe5+^V3uwg%Cq7%ckY*wPnGLVGshopQpv((&s$ zMo@PKv7NcZc4ZROm4m!PNz(aTynC{-QAOk5o6ebrdTa&~*gSBA(C$J~x|M|WW|44F zK}>HRF+D{zv^3(^FDIfe2fINjX&3Ve?$5(&D3PoS6>J(z#r3KT*~L;;4@*h9tR!S0 zi^wZ^_z&dJa;_C=e?G~5CA7A;VK|yV^nj9ZRX%=SXVZSZ1BQthKPGYOhBz(At0#!Zc6Egh9 z3b=5ohr(+$II9%|kCtLLk&VS21>WitT zR|lxP*^EMchT5C$6sViHHZ;ifksCDKzQFL!5nAr{GJg9Os)xgj-@C{CM-R9=d7np5 z9&>MUk|+O~juV@x%8HO}Z+)>4DGtkx3dP~5s&6=snb;XIQJAc2fc;?sDp8t+e z^13DuNI2Dc<*S~;W724e=dMl0E0)Zgr^&ObyZW!)7#=YQOyTmzS@ePCB3J_`&a|_{-Xa1_S5XTUuIfo($cxdRqVV zlD4ky{)-jmg49jHQkON0exvC>a-u;fXv)jY&aS*Y;xBRecq)&U)zvgKev$lHQu4R= z?|N+b^LuaqTGKB{tE#K1DUOWr_rLYG6MH^CZ26}t{e9!}3kphd4({9MQP;b3v-L-d ze>KJL8+ANCzd*KUx3hC#>1Hd74;M}6a(PBZ%=WDg4qFe|h%&uC`QtRdT%HmiX1~$g z+{_=O<{>3zYT%M8=WWC+bHp!`=Jne!EqF z)qLNBNB&HKX@s_Wz9s#qTe)ntZOf z=(_N~L&Ph!wcgRynLqp0pHG>O`A*Hk0FMjvp|em+Pgh%*v{{<|Wqzs&fh&A$4OZ$I t8X9Q*^36G#{D*UAeWH)pKu`O5^5V=>LH~h}?_l+h8Bg!M@$BlS{{`O|%sT)8 literal 0 HcmV?d00001 diff --git a/w3bat.c b/w3bat.c new file mode 100644 index 0000000..e4b2b0f --- /dev/null +++ b/w3bat.c @@ -0,0 +1,309 @@ +/* W3Battery + * Copyright (c) 2022 Toyoyo + * + * This program is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What the Fuck You Want + * to Public License, Version 2, as published by Sam Hocevar. See + * http://www.wtfpl.net/ for more details. +*/ + +#include +#include +#include +#include + +#define W3BATVERSION "0.1.0" + +/* Global variable, since I'm lazy */ +HINSTANCE g_hInstance = NULL; +HBRUSH hBrushMain; +HBRUSH hBrushGreen; +HBRUSH hBrushBlack; +HBRUSH hBrushYellow; +HBRUSH hBrushRed; +HPEN hPenWhite; +HPEN hPenBlack; +HWND hWnd; +HWND hACStatus; +HFONT s_hFont; +char sTitle[5]; +char sACStatus[13]; +int iCharge=0; +int iStatus=0; +int iCharging=0; +static const char MainWndClass[] = "W3Bat"; + +/* Function declarations */ + +/* AH=53h AL=00h BX=0000h -> INT15h + * 16-bit real-mode call + * AH: APM Major version + * AL: APM Minor version */ +void APMVersion(int* major, int* minor) { + union REGS r; + + r.h.ah = 0x53; + r.h.al = 0x00; + r.w.bx = 0x0000; + int86(0x15, &r, &r); + *major = r.h.ah; + *minor = r.h.al; + + if(r.w.cflag & INTR_CF) *minor=0; +} + +/* AH=53h AL=0Ah BX=0001h -> INT15h + * 16-bit real-mode call * + * BX=80XXh could be used for multiple batteries + * BH: AC line status + * CL: Remaining battery life (percent) + * CH: Battery flag, charging state is bit 3 */ +void GetBattery(int* Charge, int* ACStatus, int* Charging) { + union REGS r; + unsigned mask; + + r.h.ah = 0x53; + r.h.al = 0x0A; + r.w.bx = 0x0001; + int86(0x15, &r, &r); + + *Charging = r.h.ch; + *Charge = r.h.cl; + *ACStatus = r.h.bh; + + if(*Charge > 100) *Charge=100; +} + +void ClientResize(HWND hWnd, int nWidth, int nHeight) +{ + /* Thanks, random reddit post */ + RECT rcClient, rcWind; + POINT ptDiff; + GetClientRect(hWnd, &rcClient); + GetWindowRect(hWnd, &rcWind); + ptDiff.x = (rcWind.right - rcWind.left) - rcClient.right; + ptDiff.y = (rcWind.bottom - rcWind.top) - rcClient.bottom; + MoveWindow(hWnd,rcWind.left, rcWind.top, nWidth + ptDiff.x, nHeight + ptDiff.y, TRUE); +} + +void UpdateStatus() { + GetBattery(&iCharge, &iStatus, &iCharging); +} + +/* Actual battery indicator drawing + * Also, title update with percentage */ +void UpdateWin() { + HDC hdc; + int lCharge; + + lCharge=(iCharging >> 3) & 1; + + snprintf(&sTitle, 5, "%d%%", iCharge); + if(iStatus==1) { + if(lCharge==1) { + snprintf(&sACStatus, 13, "AC: Charging"); + } else { + snprintf(&sACStatus, 7, "AC: On"); + } + } else { + snprintf(&sACStatus, 8, "AC: Off"); + } + + SetWindowText(hWnd, sTitle); + + if(!IsIconic(hWnd)) { + SetWindowText(hACStatus, sACStatus); + hdc = GetDC(hWnd); + + SelectObject(hdc, hBrushMain); + SelectObject(hdc, hPenWhite); + Rectangle(hdc, -1, -1, 200, 18); + + SelectObject(hdc, hBrushBlack); + SelectObject(hdc, hPenBlack); + Rectangle(hdc, 1, 1, 100, 16); + + SelectObject(hdc, hBrushGreen); + if(iCharge < 50) SelectObject(hdc, hBrushYellow); + if(iCharge < 25) SelectObject(hdc, hBrushRed); + Rectangle(hdc, 1, 1, iCharge, 16); + ReleaseDC(hWnd, hdc); + } +} + +void ShowAboutDlg() { + char sAboutMsg[256]; + int iMajor; + int iMinor; + + APMVersion(&iMajor, &iMinor); + snprintf(&sAboutMsg, 255, "W3Battery %s\r\n(c) 2022 Toyoyo\r\n\r\nBIOS APM Version: %d.%d", W3BATVERSION, iMajor, iMinor); + MessageBox(NULL, sAboutMsg, "About", MB_OK|MB_ICONINFORMATION|MB_TASKMODAL); +} + +/* APM BIOS Call only on time event */ +void CALLBACK Timer0Proc(HWND hWnd, unsigned int msg, unsigned int idTimer, DWORD dwTime) +{ + UpdateStatus(); + UpdateWin(); +} + +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: + { + hACStatus = CreateWindowEx(0,"Static","AC: ???", WS_CHILD|WS_VISIBLE, 0, 18, 110, 16, hWnd,(HMENU)5000,g_hInstance,0); + SendMessage(hACStatus, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0)); + UpdateStatus(); + return 0; + } + + case WM_COMMAND: + { + return DefWindowProc(hWnd, msg, wParam, lParam); + } + case WM_SIZE: + { + if(LOWORD(wParam) == 0) { + UpdateWin(); + } + } + + case WM_ERASEBKGND: + { + UpdateWin(); + return 0; + } + case WM_KEYUP: + { + if(LOWORD(wParam) == 0x70) ShowAboutDlg(); + } + + case WM_CTLCOLOR: + { + int param=lParam; + if(param == hACStatus) { + return (HBRUSH)hBrushMain; + } + + SetBkMode((HDC)wParam,TRANSPARENT); + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + case WM_DESTROY: + { + KillTimer(hWnd, 1001); + PostQuitMessage(0); + } + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} + +/* Register a class for our main window */ +BOOL RegisterMainWindowClass() +{ + WNDCLASS wc = {0}; + + wc.lpfnWndProc = &MainWndProc; + wc.hInstance = g_hInstance; + wc.lpszClassName = MainWndClass; + wc.hbrBackground = hBrushMain; + wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(1)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + + return (RegisterClass(&wc)) ? TRUE : FALSE; +} + +/* Create an instance of our main window */ +HWND CreateMainWindow() +{ + int iXPos = GetPrivateProfileInt("W3Bat", "x", 0, ".\\w3bat.ini"); + int iYPos = GetPrivateProfileInt("W3Bat", "y", 0, ".\\w3bat.ini"); + + hWnd = CreateWindowEx(0, MainWndClass, "???%", WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, iXPos, iYPos, + 103, 60, NULL, NULL, g_hInstance, NULL); + ClientResize(hWnd, 101, 32); + + return hWnd; +} + +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + int iMajor; + int iMinor; + int CfgFontSize; + char CfgFont[1024]; + + HWND hWnd; + MSG msg; + + hBrushMain = CreateSolidBrush(RGB(255,255,255)); + hBrushGreen = CreateSolidBrush(RGB(0,205,0)); + hBrushBlack = CreateSolidBrush(RGB(0,0,0)); + hBrushYellow = CreateSolidBrush(RGB(205,205,0)); + hBrushRed = CreateSolidBrush(RGB(205,0,0)); + hPenWhite = CreatePen(PS_SOLID, 0, RGB(255,255,255)); + hPenBlack = CreatePen(PS_SOLID, 0, RGB(0,0,0)); + + GetPrivateProfileString("W3Bat", "font", "Courier", CfgFont, 1023, ".\\w3bat.ini"); + CfgFontSize = GetPrivateProfileInt("W3Bat", "size", 10, ".\\w3bat.ini"); + s_hFont = CreateFont(CfgFontSize, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CfgFont); + + g_hInstance = hInstance; + + /* z3dc compatibility */ + OleInitialize(NULL); + + APMVersion(&iMajor, &iMinor); + if(iMajor == 0) { + MessageBox(NULL, "APM Not supported.", "Error", MB_ICONHAND | MB_OK); + goto cleanup; + } + + /* Register our main window class */ + if (!hPrevInstance) + { + if (!RegisterMainWindowClass()) + { + MessageBox(NULL, "Error registering main window class.", "Error", MB_ICONHAND | MB_OK); + return 0; + } + } + + /* Create our main window */ + if (!(hWnd = CreateMainWindow())) + { + MessageBox(NULL, "Error creating main window.", "Error", MB_ICONHAND | MB_OK); + return 0; + } + + SetTimer(hWnd, 1001, 1000, (TIMERPROC) Timer0Proc); + + /* Sh!ow main window and force a paint */ + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + while(GetMessage(&msg, NULL, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + +cleanup: + DeleteObject(hBrushMain); + DeleteObject(hBrushGreen); + DeleteObject(hBrushBlack); + DeleteObject(hBrushYellow); + DeleteObject(hBrushRed); + DeleteObject(hPenWhite); + DeleteObject(hPenBlack); + DeleteObject(s_hFont); + UnregisterClass("W3Bat", g_hInstance); + + return(0); +} diff --git a/w3bat.ini b/w3bat.ini new file mode 100644 index 0000000..8993150 --- /dev/null +++ b/w3bat.ini @@ -0,0 +1,5 @@ +[W3Bat] +font=Courier +size=10 +x=0 +y=0 diff --git a/w3bat.rc b/w3bat.rc new file mode 100644 index 0000000..0f183cd --- /dev/null +++ b/w3bat.rc @@ -0,0 +1,25 @@ +1 VERSIONINFO +FILEVERSION 0,1,6,0 +PRODUCTVERSION 0,1,6,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", "W3Bat" + VALUE "FileVersion", "0.1.0" + VALUE "InternalName", "W3Bat" + VALUE "LegalCopyright", "Toyoyo - toyoyo@wirefull.org" + VALUE "OriginalFilename", "w3bat.exe" + VALUE "ProductName", "W3Bat" + VALUE "ProductVersion", "0.1.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +0 ICON "res/icon.ico" +1 ICON DISCARDABLE "res/icon.ico"