diff --git a/pascal/neralie.pas b/pascal/neralie.pas index 426987c..0a3774a 100644 --- a/pascal/neralie.pas +++ b/pascal/neralie.pas @@ -1,60 +1,158 @@ program Neralie; - const - BASE_RES_ID = 400; - SLEEP = 60; - WNE_TRAP_NUM = $60; - UNIMPL_TRAP_NUM = $9F; - QUIT_ITEM = 1; - ABOUT_ITEM = 1; - APPLE_MENU_ID = BASE_RES_ID; - FILE_MENU_ID = BASE_RES_ID + 1; - EDIT_MENU_ID = BASE_RES_ID + 2; - VIEW_MENU_ID = BASE_RES_ID + 3; - ABOUT_ALERT = 400; - PAD = 20; + baseRes = 128; + pad = 20; + defWidth = 300; + defHeight = 225; + + appleMenuID = baseRes; + fileMenuID = baseRes + 1; + viewMenuID = baseRes + 2; + + aboutItem = 1; + closeItem = 1; + quitItem = 2; + lightItem = 1; + darkItem = 2; var - gClockWindow: WindowPtr; - gDone, gWNEimplemented: BOOLEAN; - gCurrentTime, gOldTime: LONGINT; - gTheEvent: EventRecord; + clockWindow: WindowPtr; + r, display, bounds, minMaxSizeRect: Rect; + curPulses: Longint; + res, last: longInt; + altMap, tempBits: BitMap; + lightMode, quitting: Boolean; - r, display, bounds, inbounds: Rect; - dtr: DateTimeRec; - inverted: BOOLEAN; + procedure UpdateLightDarkMarks; + var + handle: MenuHandle; + lightMark, darkMark: Char; + begin + handle := GetMHandle(viewMenuID); + if handle = nil then + Exit(UpdateLightDarkMarks); + CheckItem(handle, lightItem, lightMode); + CheckItem(handle, darkItem, not lightMode); + end; -{>>} - function ToNeralie (dtr: DateTimeRec): Longint; + procedure GetClockWindowSize (var width, height: Integer); + var + bbox: Rect; + begin + bbox := WindowPeek(clockWindow)^.contRgn^^.rgnBBox; + width := bbox.right - bbox.left; + height := bbox.bottom - bbox.top; + end; + + function GetContentRect: Rect; + var + r: Rect; + begin + r.left := 0; + r.top := 0; + GetClockWindowSize(r.right, r.bottom); + GetContentRect := r; + end; + + function GetFaceRect: Rect; + var + r: rect; + width, height: Integer; + begin + GetClockWindowSize(width, height); + SetRect(r, pad, pad, width - pad, height - pad); + if (r.right < r.left) or (r.bottom < r.top) then + SetRect(r, 0, 0, 0, 0); + GetFaceRect := r; + end; + + function NeralieOf (dtr: DateTimeRec): Longint; var mins, a: Longint; begin mins := Longint(dtr.hour * 60 + dtr.minute) * 100; a := mins mod 144 * 60 * 100 + Longint(dtr.second) * 10000; - toNeralie := mins div 144 * 1000 + a div 864; + NeralieOf := mins div 144 * 1000 + a div 864; end; -{>>} - procedure UpdateFrame; + procedure CheckAltMapBufferSize; + var + width, height: Integer; + newRowBytes: Longint; begin - if inverted = true then - PenPat(white) + GetClockWindowSize(width, height); + width := width - pad * 2; + height := height - pad * 2; + if width < 0 then + width := 0; + if height < 0 then + height := 0; + if (altMap.bounds.right = width) and (altMap.bounds.bottom = height) then + Exit(CheckAltMapBufferSize); + altMap.bounds.right := width; + altMap.bounds.bottom := height; + newRowBytes := (width + 15) div 16 * 2; + if altMap.baseAddr <> nil then + DisposePtr(altMap.baseAddr); + altMap.rowBytes := newRowBytes; + if altMap.rowBytes < 1 then + begin + altMap.rowBytes := 0; + altMap.baseAddr := nil; + Exit(CheckAltMapBufferSize); + end; + altMap.rowBytes := newRowBytes; + altMap.baseAddr := NewPtr(altMap.rowBytes * Longint(height)); + if altMap.baseAddr = nil then + altMap.rowBytes := 0; + curPulses := -1; {Kinda hacky} + end; + + function GetPulses: Longint; + var + dtr: DateTimeRec; + begin + GetTime(dtr); + GetPulses := NeralieOf(dtr); + end; + + function GetFg: Pattern; + begin + if lightMode then + GetFg := black else - PenPat(black); - PaintRect(display); - if inverted = true then - PenPat(black) + GetFg := white; + end; + function GetBg: Pattern; + begin + if lightMode then + GetBg := white else - PenPat(white); - FrameRect(bounds); + GetBg := black; end; -{>>} - procedure Draw (bounds: rect; a, b, c, d, e, f: real); + procedure PaintEmptyAreas; + var + r: Rect; + width, height: Integer; + begin + PenPat(GetBg); + GetClockWindowSize(width, height); + SetRect(r, 0, 0, width, pad); + PaintRect(r); + SetRect(r, 0, pad, pad, height - pad); + PaintRect(r); + SetRect(r, width - pad, pad, width, height - pad); + PaintRect(r); + SetRect(r, 0, height - pad, width, height); + PaintRect(r); + end; + + procedure DrawNeedles (bounds: rect; a, b, c, d, e, f: real); var x, y: integer; begin - y := PAD; + y := pad; x := bounds.left; y := round(a * (bounds.bottom - y) + y); drawLine(x, y, bounds.right - 1, y); @@ -70,217 +168,213 @@ drawLine(x, y, x, bounds.bottom - 1); end; -{>>} - procedure UpdateNeedles; + procedure CopyAltBuffer; var - res: longInt; + r: Rect; begin - GetTime(dtr); - if inverted = true then - PenPat(white) - else - PenPat(black); - PaintRect(inbounds); - if inverted = true then - PenPat(black) - else - PenPat(white); - res := toNeralie(dtr); - writeln(res); - Draw(bounds, res / 1000000, (res mod 100000) / 100000, (res mod 10000) / 10000, (res mod 1000) / 1000, (res mod 100) / 100, (res mod 10) / 10); + r := GetFaceRect; + CopyBits(altMap, thePort^.portBits, altMap.bounds, r, srcCopy, nil); end; -{>>} - procedure Invert; + procedure Draw; + var + newPulses: Longint; begin - if inverted = true then - inverted := false - else - inverted := true; - UpdateFrame; - UpdateNeedles; + CheckAltMapBufferSize; + newPulses := GetPulses; + if curPulses <> newPulses then + begin + curPulses := newPulses; + tempBits := thePort^.portBits; + SetPortBits(altMap); + PenPat(GetBg); + PaintRect(altMap.bounds); + PenPat(GetFg); + FrameRect(altMap.bounds); + DrawNeedles(altMap.bounds, curPulses / 1000000, (curPulses mod 100000) / 100000, (curPulses mod 10000) / 10000, (curPulses mod 1000) / 1000, (curPulses mod 100) / 100, (curPulses mod 10) / 10); + SetPortBits(tempBits); + end; + CopyAltBuffer; end; -{>>} - procedure Expand; + procedure Redraw; begin -{TODO} + PaintEmptyAreas; + Draw; end; -{>>} - procedure HandleAppleChoice (theItem: INTEGER); + procedure ScheduleFullRedraw; var - accName: Str255; - accNumber, itemNumber, dummy: INTEGER; - appleMenu: MenuHandle; + r: Rect; begin - case theItem of - ABOUT_ITEM: - dummy := NoteAlert(ABOUT_ALERT, nil); - otherwise - begin - appleMenu := GetMHandle(APPLE_MENU_ID); - GetItem(appleMenu, theItem, accName); - accNumber := OpenDeskAcc(accName); - end; - end; + r := GetContentRect; + curPulses := -1; {Kinda hacky} + InvalRect(r); end; -{>>} - procedure HandleFileChoice (theItem: INTEGER); + procedure SetLightMode (newLightMode: Boolean); begin - case theItem of - QUIT_ITEM: - gDone := TRUE; - end; + if newLightMode = lightMode then + Exit(SetLightMode); + lightMode := newLightMode; + ScheduleFullRedraw; + UpdateLightDarkMarks; end; -{>>} - procedure HandleViewChoice (theItem: INTEGER); + procedure OnMenuChoice (menuChoice: Longint); var - fontNumber: INTEGER; - fontName: Str255; - fontMenu: MenuHandle; + dummy: Longint; + itemChoice: Integer; + appleMenuH: MenuHandle; + itemName: Str255; begin - if theItem = 1 then - Invert; - end; - -{>>} - procedure HandleMenuChoice (menuChoice: LONGINT); - var - theMenu, theItem: INTEGER; - begin - if menuChoice <> 0 then - begin - theMenu := HiWord(menuChoice); - theItem := LoWord(menuChoice); - case theMenu of - APPLE_MENU_ID: - HandleAppleChoice(theItem); - FILE_MENU_ID: - HandleFileChoice(theItem); - VIEW_MENU_ID: - HandleViewChoice(theItem); + if menuChoice = 0 then + Exit(OnMenuChoice); + itemChoice := LoWord(menuChoice); + case HiWord(menuChoice) of + appleMenuID: + case itemChoice of + aboutItem: + dummy := Alert(baseRes, nil); + otherwise + begin + appleMenuH := GetMHandle(appleMenuID); + GetItem(appleMenuH, itemChoice, itemName); + dummy := OpenDeskAcc(itemName); + end; end; - HiliteMenu(0); - end; + fileMenuID: + case itemChoice of + closeItem, quitItem: + quitting := True; + otherwise + ; + end; + viewMenuID: + case itemChoice of + lightItem: + SetLightMode(True); + darkItem: + SetLightMode(False); + otherwise + ; + end; + otherwise + ; + end; + HiliteMenu(0); end; - -{>>} - procedure HandleMouseDown; + procedure OnMouseDown (event: EventRecord); var - whichWindow: WindowPtr; - thePart: INTEGER; - menuChoice, windSize: LONGINT; + someWindow: WindowPtr; + partOfWindow: Integer; + tmp: Longint; + r: Rect; begin - thePart := FindWindow(gTheEvent.where, whichWindow); - case thePart of + partOfWindow := FindWindow(event.where, someWindow); + case partOfWindow of inMenuBar: + OnMenuChoice(MenuSelect(event.where)); + inSysWindow: + SystemClick(event, someWindow); + inContent: begin - menuChoice := MenuSelect(gTheEvent.where); - HandleMenuChoice(menuChoice); + SelectWindow(someWindow); + if someWindow = clockWindow then + begin + Redraw; + tmp := GrowWindow(clockWindow, event.where, minMaxSizeRect); + if tmp <> 0 then + begin + SizeWindow(clockWindow, LoWord(tmp), HiWord(tmp), False); + curPulses := -1; {Kinda hacky} + SetRect(r, 0, 0, LoWord(tmp), HiWord(tmp)); + InvalRect(r); + end + end; end; - inSysWindow: - SystemClick(gTheEvent, whichWindow); inDrag: - DragWindow(whichWindow, gTheEvent.where, screenBits.bounds); + begin + SelectWindow(someWindow); + Redraw; + DragWindow(someWindow, event.where, screenBits.bounds); + end; inGoAway: - gDone := TRUE; + if TrackGoAway(someWindow, event.where) then + quitting := quitting or (someWindow = clockWindow); + otherwise + ; end; end; -{>>} - procedure HandleNull; - begin - GetDateTime(gCurrentTime); - if gCurrentTime <> gOldTime then - UpdateNeedles; - end; - -{>>} - procedure HandleEvent; + procedure DispatchEvent; var - theChar: CHAR; - dummy: BOOLEAN; + theChar: Char; + dummy: Boolean; + theEvent: EventRecord; begin - if gWNEimplemented then - dummy := WaitNextEvent(everyEvent, gTheEvent, SLEEP, nil) - else - begin - SystemTask; - dummy := GetNextEvent(everyEvent, gTheEvent); - end; - case gTheEvent.what of + dummy := WaitNextEvent(everyEvent, theEvent, 10, nil); + case theEvent.what of nullEvent: - HandleNull; + if curPulses <> GetPulses then + InvalRect(GetFaceRect); mouseDown: - HandleMouseDown; + OnMouseDown(theEvent); keyDown, autoKey: begin - theChar := CHR(BitAnd(gTheEvent.message, charCodeMask)); - if (BitAnd(gTheEvent.modifiers, cmdKey) <> 0) then - HandleMenuChoice(MenuKey(theChar)); + theChar := CHR(BitAnd(theEvent.message, charCodeMask)); + if BitAnd(theEvent.modifiers, cmdKey) <> 0 then + OnMenuChoice(MenuKey(theChar)); end; + activateEvt: + ScheduleFullRedraw; updateEvt: - begin - BeginUpdate(WindowPtr(gTheEvent.message)); - EndUpdate(WindowPtr(gTheEvent.message)); - end; + if WindowPtr(theEvent.message) = clockWindow then + begin + BeginUpdate(clockWindow); + Redraw; + EndUpdate(clockWindow); + end; + otherwise + ; end; end; -{>>} - procedure MainLoop; - begin - gDone := FALSE; - gWNEimplemented := (NGetTrapAddress(WNE_TRAP_NUM, ToolTrap) <> NGetTrapAddress(UNIMPL_TRAP_NUM, ToolTrap)); - while (gDone = FALSE) do - HandleEvent; - end; - -{>>} procedure MenuBarInit; var - myMenuBar: Handle; - aMenu: MenuHandle; + bar: Handle; + menu: MenuHandle; begin - myMenuBar := GetNewMBar(BASE_RES_ID); - SetMenuBar(myMenuBar); - DisposHandle(myMenuBar); - aMenu := GetMHandle(APPLE_MENU_ID); - AddResMenu(aMenu, 'DRVR'); + bar := GetNewMBAR(baseRes); + if bar = nil then + Exit(MenuBarInit); + SetMenuBar(bar); + DisposeHandle(bar); + AppendMenu(GetMenu(appleMenuID), 'DRVR'); DrawMenuBar; end; -{>>} - procedure Windowinit; - begin - SetRect(r, 150, 125, 450, 350); - gClockWindow := NewWindow(nil, r, 'Neralie', true, noGrowDocProc, WindowPtr(-1), true, 0); - SetPort(gClockWindow); - ShowWindow(gClockWindow); - - SetDrawingRect(r); - SetRect(display, 0, 0, r.right - r.left, r.bottom - r.top); - SetRect(bounds, PAD, PAD, display.right - PAD, display.bottom - PAD); - SetRect(inbounds, bounds.left + 1, bounds.top + 1, bounds.right - 1, bounds.bottom - 1); - end; - begin - WindowInit; MenuBarInit; - - UpdateFrame; - UpdateNeedles; - MainLoop; - + SetRect(r, 150, 125, 150 + defWidth, 125 + defHeight); + curPulses := -1; + quitting := False; + altMap.rowBytes := 0; + lightMode := True; + SetRect(minMaxSizeRect, pad * 3, pad * 3, 5000, 5000); + SetRect(altMap.bounds, 0, 0, 0, 0); + altMap.baseAddr := nil; + clockWindow := NewWindow(nil, r, 'Neralie', True, noGrowDocProc, WindowPtr(-1), True, 0); + SetPort(clockWindow); + SetRect(display, 0, 0, r.right - r.left, r.bottom - r.top); + SetRect(bounds, pad, pad, display.right - pad, display.bottom - pad); + ScheduleFullRedraw; + UpdateLightDarkMarks; + SetCursor(arrow); + while not quitting do + DispatchEvent; + if altMap.baseAddr <> nil then + DisposePtr(altMap.baseAddr); + end. - -{ Resources needed: } -{ 1x WIND #400 } -{ 1x MBAR #400 4 options} -{ 1x MENU #400 -> Apple#400[about] File#401[quit] Edit#402[undo, cut, copy, paste, clear] View#403[invert, expand] } -{ 1x ALRT #400 } -{ 1x DITL #400 } \ No newline at end of file