MODULE WMCalendar;
IMPORT
Dates, Strings, Modules, Kernel, XML,
WMRectangles, Raster, WMRasterScale, WMGraphics, WMGraphicUtilities, WMMessages, WMWindowManager, WMRestorable,
WMEvents, WMProperties, WMComponents, WMStandardComponents, WMPopups;
CONST
Monday* = 1;
Tuesday* = 2;
Wednesday* = 3;
Thursday* = 4;
Friday* = 5;
Saturday* = 6;
Sunday* = 7;
January* = 1;
February* = 2;
March* = 3;
April* = 4;
May* = 5;
June* = 6;
July* = 7;
August* = 8;
September* = 9;
October* = 10;
November* = 11;
December* = 12;
MinCellWidth = 5;
MinCellHeight = 5;
NofColumns = 7;
NofRows = 7;
WindowWidth = 200;
WindowHeight = 200;
TYPE
SelectionWrapper* = OBJECT
VAR
year-, month-, day-,
week-, weekDay- : LONGINT;
PROCEDURE &Init(year, month, day, week, weekDay : LONGINT);
BEGIN
SELF.year := year; SELF.month := month; SELF.day := day;
SELF.week := week; SELF.weekDay := weekDay;
END Init;
END SelectionWrapper;
TYPE
Calendar* = OBJECT(WMComponents.VisualComponent)
VAR
onSelect- : WMEvents.EventSource;
allowSelection- : WMProperties.BooleanProperty;
year-, month- : WMProperties.Int32Property;
firstDayOfWeek- : WMProperties.Int32Property;
clText-, clTextTitle-, clTextWeekend-, clTextOtherMonths-,
clTextCurrentDay-, clMouseOver- : WMProperties.ColorProperty;
currentDayImageName- : WMProperties.StringProperty;
currentDayImage : WMGraphics.Image;
backgroundImageName- : WMProperties.StringProperty;
backgroundImage : WMGraphics.Image;
mouseOverColumn, mouseOverRow : LONGINT;
selected : BOOLEAN;
currentDate : Dates.DateTime;
date0 : Dates.DateTime;
cellWidth, cellHeight : LONGINT;
fixWidth, fixHeight : LONGINT;
state : LONGINT;
timer : Kernel.Timer;
PROCEDURE &Init*;
BEGIN
Init^;
SetNameAsString(StrCalendar);
NEW(onSelect, SELF, StrOnSelect, StrOnSelectInfo, NIL); events.Add(onSelect);
NEW(allowSelection, PrototypeAllowSelection, NIL, NIL); properties.Add(allowSelection);
NEW(year, PrototypeYear, NIL, NIL); properties.Add(year);
NEW(month, PrototypeMonth, NIL, NIL); properties.Add(month);
NEW(firstDayOfWeek, PrototypeFirstDayOfWeek, NIL, NIL); properties.Add(firstDayOfWeek);
NEW(clText, PrototypeClText, NIL, NIL); properties.Add(clText);
NEW(clTextTitle, PrototypeClTextTitle, NIL, NIL); properties.Add(clTextTitle);
NEW(clTextWeekend, PrototypeClTextWeekend, NIL, NIL); properties.Add(clTextWeekend);
NEW(clTextOtherMonths, PrototypeClTextOtherMonths, NIL, NIL); properties.Add(clTextOtherMonths);
NEW(clTextCurrentDay, PrototypeClTextCurrentDay, NIL, NIL); properties.Add(clTextCurrentDay);
NEW(clMouseOver, PrototypeClMouseOver, NIL, NIL); properties.Add(clMouseOver);
NEW(currentDayImageName, PrototypeCurrentDayImageName, NIL, NIL); properties.Add(currentDayImageName);
NEW(backgroundImageName, PrototypeBackgroundImageName, NIL, NIL); properties.Add(backgroundImageName);
mouseOverColumn := -1; mouseOverRow := -1;
selected := FALSE;
currentDate := Dates.Now();
date0 := currentDate;
state := NotInitialized;
NEW(timer);
END Init;
PROCEDURE Initialize;
BEGIN
Initialize^;
BEGIN {EXCLUSIVE} state := Running; END;
END Initialize;
PROCEDURE PropertyChanged(sender, property : ANY);
BEGIN
RecacheProperties;
PropertyChanged^(sender, property);
END PropertyChanged;
PROCEDURE RecacheProperties;
VAR dt : Dates.DateTime; ignore, weekDay : LONGINT; string : Strings.String;
PROCEDURE GetResizedImage(name : WMProperties.StringProperty; width, height : LONGINT) : WMGraphics.Image;
VAR newImage, resizedImage : WMGraphics.Image;
BEGIN
newImage := NIL;
string := name.Get();
IF (string # NIL) THEN
newImage := WMGraphics.LoadImage(string^, TRUE);
IF (newImage # NIL) THEN
IF (width # newImage.width) OR (height # newImage.height) THEN
NEW(resizedImage);
Raster.Create(resizedImage, width, height, Raster.BGRA8888);
WMRasterScale.Scale(
newImage, WMRectangles.MakeRect(0, 0, newImage.width, newImage.height),
resizedImage, WMRectangles.MakeRect(0, 0, resizedImage.width, resizedImage.height),
WMRectangles.MakeRect(0, 0, resizedImage.width, resizedImage.height),
WMRasterScale.ModeCopy, WMRasterScale.ScaleBilinear);
newImage := resizedImage;
END;
END;
END;
RETURN newImage;
END GetResizedImage;
BEGIN
RecacheProperties^;
cellWidth := bounds.GetWidth() DIV NofColumns;
IF (cellWidth < MinCellWidth) THEN
cellWidth := MinCellWidth;
fixWidth := 0;
ELSE
fixWidth := bounds.GetWidth() MOD NofColumns;
END;
cellHeight := bounds.GetHeight() DIV NofRows;
IF (cellHeight < MinCellHeight) THEN
cellHeight := MinCellHeight;
fixHeight := 0;
ELSE
fixHeight := bounds.GetHeight() MOD NofRows;
END;
dt.year := year.Get(); dt.month := month.Get();
dt.day := 1; dt.hour := 0; dt.minute := 0; dt.second := 0;
Dates.WeekDate(dt, ignore, ignore, weekDay);
Dates.AddDays(dt, firstDayOfWeek.Get() - weekDay);
date0.day := dt.day; date0.month := dt.month; date0.year := dt.year;
currentDayImage := GetResizedImage(currentDayImageName, cellWidth, cellHeight);
backgroundImage := GetResizedImage(backgroundImageName, bounds.GetWidth(), bounds.GetHeight());
Invalidate;
END RecacheProperties;
PROCEDURE NextMonth*;
BEGIN
Acquire;
ChangeMonth(1);
Release;
END NextMonth;
PROCEDURE PreviousMonth*;
BEGIN
Acquire;
ChangeMonth(-1);
Release;
END PreviousMonth;
PROCEDURE ChangeMonth(delta : LONGINT);
VAR dt : Dates.DateTime;
BEGIN
dt.year := year.Get(); dt.month := month.Get(); dt.day := 1;
dt.hour := 1; dt.minute := 1; dt.day := 1;
Dates.AddMonths(dt, delta);
year.Set(dt.year);
month.Set(dt.month);
END ChangeMonth;
PROCEDURE PointerDown(x, y : LONGINT; keys : SET);
BEGIN
PointerDown^(x, y, keys);
IF (0 IN keys) THEN selected := TRUE; END;
END PointerDown;
PROCEDURE PointerUp(x, y : LONGINT; keys : SET);
VAR
selection : SelectionWrapper; dt : Dates.DateTime;
year, week, weekDay : LONGINT;
BEGIN
PointerUp^(x, y, keys);
IF selected & ~(0 IN keys) & allowSelection.Get() THEN
selected := FALSE;
IF GetDateXY(x, y, dt) THEN
Dates.WeekDate(dt, year, week, weekDay);
NEW(selection, dt.year, dt.month, dt.day, week, weekDay);
onSelect.Call(selection);
END;
END;
END PointerUp;
PROCEDURE PointerMove(x, y : LONGINT; keys : SET);
VAR column, row : LONGINT;
BEGIN
PointerMove^(x, y, keys);
GetCell(x, y, column, row);
IF (column # mouseOverColumn) OR (row # mouseOverRow) THEN
mouseOverColumn := column; mouseOverRow := row;
Invalidate;
END;
END PointerMove;
PROCEDURE PointerLeave;
BEGIN
PointerLeave^;
mouseOverColumn := -1; mouseOverRow := -1;
Invalidate;
END PointerLeave;
PROCEDURE GetDateXY(x, y : LONGINT; VAR dt : Dates.DateTime) : BOOLEAN;
VAR column, row : LONGINT;
BEGIN
GetCell(x, y, column, row);
IF (column # -1) & (row > 0) THEN
dt := date0;
Dates.AddDays(dt, (row - 1) * NofColumns + column);
RETURN TRUE;
ELSE
RETURN FALSE;
END;
END GetDateXY;
PROCEDURE GetCell(x, y : LONGINT; VAR column, row : LONGINT);
BEGIN
column := -1; row := -1;
IF WMRectangles.PointInRect(x, y, GetClientRect()) THEN
column := x DIV cellWidth;
row := y DIV cellHeight;
END;
END GetCell;
PROCEDURE DrawBackground(canvas : WMGraphics.Canvas);
VAR
rect : WMRectangles.Rectangle;
dt : Dates.DateTime;
string : ARRAY 16 OF CHAR;
column, row, color, temp : LONGINT;
PROCEDURE DrawStringInRect(rect : WMRectangles.Rectangle; CONST string : ARRAY OF CHAR);
BEGIN
WMGraphics.DrawStringInRect(canvas, rect, FALSE, WMGraphics.AlignCenter, WMGraphics.AlignCenter, string);
END DrawStringInRect;
BEGIN
dt := date0;
DrawBackground^(canvas);
IF (backgroundImage # NIL) THEN
canvas.DrawImage(0, 0, backgroundImage, WMGraphics.ModeSrcOverDst);
END;
FOR row := 0 TO NofRows - 1 DO
FOR column := 0 TO NofColumns - 1 DO
rect := WMRectangles.MakeRect(column * cellWidth, row * cellHeight, (column + 1) * cellWidth, (row + 1) * cellHeight);
IF (column = NofColumns - 1) THEN rect.r := rect.r + fixWidth; END;
IF (row = NofRows - 1) THEN rect.b := rect.b + fixHeight; END;
IF (row = 0) THEN
temp := firstDayOfWeek.Get() + column;
IF (temp DIV 8 >=1) THEN temp := (temp MOD 8) + 1; ELSE temp := (temp MOD 8); END;
COPY(WeekDay[temp], string);
color := clTextTitle.Get();
ELSE
IF (column = mouseOverColumn) & (row = mouseOverRow) & allowSelection.Get() THEN
temp := clMouseOver.Get();
canvas.Fill(rect, temp, WMGraphics.ModeSrcOverDst);
temp := temp - (temp MOD 100H) + 0FFH;
WMGraphicUtilities.DrawRect(canvas, rect, temp, WMGraphics.ModeCopy);
END;
Strings.IntToStr(dt.day, string);
IF (dt.month = month.Get()) THEN
IF SameDay(dt, currentDate) THEN
color := clTextCurrentDay.Get();
ELSE
color := clText.Get();
END;
ELSE
color := clTextOtherMonths.Get();
END;
Dates.AddDays(dt, 1);
END;
canvas.SetColor(color);
DrawStringInRect(rect, string);
END;
END;
END DrawBackground;
PROCEDURE Finalize;
BEGIN
Finalize^;
BEGIN {EXCLUSIVE} state := Terminating END;
timer.Wakeup;
BEGIN {EXCLUSIVE} AWAIT(state = Terminated); END;
END Finalize;
PROCEDURE UpdateCurrentDate;
VAR currentDate : Dates.DateTime;
BEGIN
currentDate := Dates.Now();
IF ~SameDay(currentDate, SELF.currentDate) THEN
Acquire;
SELF.currentDate := currentDate;
Release;
Invalidate;
END;
END UpdateCurrentDate;
BEGIN {ACTIVE}
BEGIN {EXCLUSIVE} AWAIT(state > NotInitialized); END;
WHILE (state = Running) DO
UpdateCurrentDate;
timer.Sleep(5000);
END;
BEGIN {EXCLUSIVE} state := Terminated; END;
END Calendar;
CONST
NotInitialized = 0;
Running = 1;
Terminating = 2;
Terminated = 3;
TYPE
CalendarController* = OBJECT(WMComponents.VisualComponent)
VAR
calendar : Calendar;
prevBtn, nextBtn : WMStandardComponents.Button;
dateLabel : WMStandardComponents.Label;
state : LONGINT;
timer : Kernel.Timer;
PROCEDURE &Init*;
BEGIN
Init^;
SetNameAsString(StrCalendarController);
calendar := NIL;
state := NotInitialized;
NEW(timer);
NEW(prevBtn); prevBtn.alignment.Set(WMComponents.AlignLeft);
prevBtn.bounds.SetWidth(15);
prevBtn.caption.SetAOC("<");
prevBtn.onClick.Add(ButtonHandler);
AddContent(prevBtn);
NEW(nextBtn); nextBtn.alignment.Set(WMComponents.AlignRight);
nextBtn.bounds.SetWidth(15);
nextBtn.caption.SetAOC(">");
nextBtn.onClick.Add(ButtonHandler);
AddContent(nextBtn);
NEW(dateLabel); dateLabel.alignment.Set(WMComponents.AlignClient);
dateLabel.alignV.Set(WMGraphics.AlignCenter);
dateLabel.alignH.Set(WMGraphics.AlignCenter);
dateLabel.textColor.Set(WMGraphics.Black);
AddContent(dateLabel);
END Init;
PROCEDURE ButtonHandler(sender, data : ANY);
BEGIN
IF (sender = prevBtn) THEN
calendar.PreviousMonth;
ELSIF (sender = nextBtn) THEN
calendar.NextMonth;
END;
UpdateDateLabel;
END ButtonHandler;
PROCEDURE UpdateDateLabel;
VAR dt : Dates.DateTime; caption : ARRAY 128 OF CHAR;
BEGIN
dt.year := calendar.year.Get();
dt.month := calendar.month.Get();
dt.day := 1; dt.hour := 1; dt.minute := 1; dt.second := 1;
Strings.FormatDateTime("mmmm yyyy", dt, caption);
dateLabel.caption.SetAOC(caption);
END UpdateDateLabel;
PROCEDURE SetCalendar*(calendar : Calendar);
VAR dt : Dates.DateTime;
BEGIN {EXCLUSIVE}
SELF.calendar := calendar;
dt := Dates.Now();
calendar.year.Set(dt.year);
calendar.month.Set(dt.month);
UpdateDateLabel;
END SetCalendar;
END CalendarController;
TYPE
KillerMsg = OBJECT
END KillerMsg;
Window = OBJECT(WMComponents.FormWindow);
VAR
calendar : Calendar;
control : CalendarController;
colorScheme : LONGINT;
contextMenu : WMPopups.Popup;
dragging, resizing : BOOLEAN;
lastX, lastY : LONGINT;
PROCEDURE &New*(context : WMRestorable.Context);
VAR panel : WMStandardComponents.Panel; configuration : WMRestorable.XmlElement;
BEGIN
IncCount;
IF (context # NIL) THEN
Init(context.r - context.l, context.b - context.t, TRUE);
ELSE
Init(WindowWidth, WindowHeight, TRUE);
END;
NEW(panel); panel.alignment.Set(WMComponents.AlignClient);
NEW(control); control.alignment.Set(WMComponents.AlignTop);
control.bounds.SetHeight(20);
control.nextBtn.useBgBitmaps.Set(FALSE);
control.nextBtn.clDefault.Set(0);
control.nextBtn.effect3D.Set(0);
control.prevBtn.useBgBitmaps.Set(FALSE);
control.prevBtn.clDefault.Set(0);
control.prevBtn.effect3D.Set(0);
panel.AddContent(control);
NEW(calendar);
calendar.alignment.Set(WMComponents.AlignClient);
calendar.allowSelection.Set(FALSE);
panel.AddContent(calendar);
control.SetCalendar(calendar);
SetContent(panel);
SetTitle(Strings.NewString("Calendar"));
colorScheme := 0;
IF (context # NIL) THEN
configuration := WMRestorable.GetElement(context, "Configuration");
IF (configuration # NIL) THEN
WMRestorable.LoadLongint(configuration, "ColorScheme", colorScheme);
END;
SetColorScheme(colorScheme);
WMRestorable.AddByContext(SELF, context);
ELSE
SetColorScheme(0);
WMWindowManager.ExtAddWindow(SELF, 50, 50, {WMWindowManager.FlagHidden})
END;
END New;
PROCEDURE SetColorScheme(scheme : LONGINT);
BEGIN
IF (scheme = 0) THEN
calendar.clText.Set(WMGraphics.White);
calendar.clTextTitle.Set(WMGraphics.White);
calendar.clTextOtherMonths.Set(0FFFFFF80H);
calendar.clTextWeekend.Set(WMGraphics.White);
control.dateLabel.textColor.Set(WMGraphics.White);
control.prevBtn.clTextDefault.Set(WMGraphics.White);
control.nextBtn.clTextDefault.Set(WMGraphics.White);
ELSE
calendar.clText.Set(WMGraphics.Black);
calendar.clTextTitle.Set(WMGraphics.Black);
calendar.clTextOtherMonths.Set(080H);
calendar.clTextWeekend.Set(WMGraphics.Black);
control.dateLabel.textColor.Set(WMGraphics.Black);
control.prevBtn.clTextDefault.Set(WMGraphics.Black);
control.nextBtn.clTextDefault.Set(WMGraphics.Black);
END;
END SetColorScheme;
PROCEDURE Close;
BEGIN
Close^;
DecCount;
END Close;
PROCEDURE PointerDown(x, y:LONGINT; keys:SET);
BEGIN
lastX := bounds.l + x; lastY:=bounds.t + y;
IF keys = {0} THEN
dragging := TRUE
ELSIF keys = {1,2} THEN
dragging := FALSE;
resizing := TRUE;
ELSIF keys = {2} THEN
NEW(contextMenu);
contextMenu.Add("Close", HandleClose);
contextMenu.Add("CurrentDay", HandleCurrentDay);
contextMenu.Add("ToggleColor", HandleToggleColor);
contextMenu.Popup(bounds.l + x, bounds.t + y)
END
END PointerDown;
PROCEDURE HandleClose(sender, par: ANY);
VAR manager : WMWindowManager.WindowManager;
BEGIN
manager := WMWindowManager.GetDefaultManager();
manager.SetFocus(SELF);
Close;
END HandleClose;
PROCEDURE HandleCurrentDay(sender, data: ANY);
VAR dt : Dates.DateTime;
BEGIN
dt := Dates.Now();
calendar.year.Set(dt.year);
calendar.month.Set(dt.month);
control.UpdateDateLabel;
END HandleCurrentDay;
PROCEDURE HandleToggleColor(sender, data : ANY);
BEGIN
colorScheme := (colorScheme + 1) MOD 2;
SetColorScheme(colorScheme);
END HandleToggleColor;
PROCEDURE PointerMove(x,y:LONGINT; keys:SET);
VAR dx, dy, width, height : LONGINT;
BEGIN
IF dragging OR resizing THEN
x := bounds.l + x; y := bounds.t + y; dx := x - lastX; dy := y - lastY;
lastX := lastX + dx; lastY := lastY + dy;
IF (dx # 0) OR (dy # 0) THEN
IF dragging THEN
manager.SetWindowPos(SELF, bounds.l + dx, bounds.t + dy);
ELSE
width := GetWidth();
height := GetHeight();
width := Strings.Max(10, width + dx);
height := Strings.Max(10, height + dy);
manager.SetWindowSize(SELF, width, height);
END;
END;
END;
END PointerMove;
PROCEDURE PointerUp(x, y:LONGINT; keys:SET);
BEGIN
PointerUp^(x, y, keys);
dragging := FALSE;
IF (keys # {1,2}) THEN
IF resizing THEN
resizing := FALSE;
Resized(GetWidth(), GetHeight());
END;
END;
END PointerUp;
PROCEDURE Handle(VAR x: WMMessages.Message);
VAR configuration : WMRestorable.XmlElement;
BEGIN
IF (x.msgType = WMMessages.MsgExt) & (x.ext # NIL) THEN
IF (x.ext IS KillerMsg) THEN
Close;
ELSIF (x.ext IS WMRestorable.Storage) THEN
NEW(configuration); configuration.SetName("Configuration");
WMRestorable.StoreLongint(configuration, "ColorScheme", colorScheme);
x.ext(WMRestorable.Storage).Add("WMCalendar", "WMCalendar.Restore", SELF, configuration);
ELSE Handle^(x)
END
ELSE Handle^(x)
END
END Handle;
END Window;
VAR
WeekDay : ARRAY 8 OF ARRAY 16 OF CHAR;
nofWindows : LONGINT;
StrCalendar, StrCalendarController, StrOnSelect, StrOnSelectInfo : Strings.String;
PrototypeAllowSelection : WMProperties.BooleanProperty;
PrototypeYear, PrototypeMonth, PrototypeFirstDayOfWeek : WMProperties.Int32Property;
PrototypeClText, PrototypeClTextTitle, PrototypeClTextWeekend, PrototypeClTextOtherMonths, PrototypeClTextCurrentDay,
PrototypeClMouseOver : WMProperties.ColorProperty;
PrototypeCurrentDayImageName, PrototypeBackgroundImageName : WMProperties.StringProperty;
PROCEDURE Open*;
VAR window : Window;
BEGIN
NEW(window, NIL);
END Open;
PROCEDURE Restore*(context : WMRestorable.Context);
VAR window : Window;
BEGIN
NEW(window, context);
END Restore;
PROCEDURE GenCalendar*() : XML.Element;
VAR calendar : Calendar;
BEGIN
NEW(calendar); RETURN calendar;
END GenCalendar;
PROCEDURE SameDay(dt1, dt2 : Dates.DateTime) : BOOLEAN;
BEGIN
RETURN (dt1.year = dt2.year) & (dt1.month = dt2.month) & (dt1.day = dt2.day);
END SameDay;
PROCEDURE InitStrings;
BEGIN
StrCalendar := Strings.NewString("Calendar");
StrCalendarController := Strings.NewString("CalendarController");
StrOnSelect := Strings.NewString("OnSelect");
StrOnSelectInfo := Strings.NewString("Event generated when the user selects a day");
END InitStrings;
PROCEDURE InitPrototypes;
BEGIN
NEW(PrototypeAllowSelection, NIL, Strings.NewString("AllowSelection"), Strings.NewString("Left click generates onSelect event"));
PrototypeAllowSelection.Set(TRUE);
NEW(PrototypeYear, NIL, Strings.NewString("Year"), Strings.NewString("Currently displayed year"));
PrototypeYear.Set(2000);
PrototypeYear.SetBounds(1, MAX(LONGINT));
NEW(PrototypeMonth, NIL, Strings.NewString("Month"), Strings.NewString("Currently displayed month"));
PrototypeMonth.Set(1);
PrototypeMonth.SetBounds(January, December);
NEW(PrototypeFirstDayOfWeek, NIL, Strings.NewString("FirstDayOfWeek"), Strings.NewString("First day of week (0 = Monday)"));
PrototypeFirstDayOfWeek.Set(Monday);
PrototypeFirstDayOfWeek.SetBounds(Monday, Sunday);
NEW(PrototypeClText, NIL, Strings.NewString("ClText"), Strings.NewString("Default text color"));
PrototypeClText.Set(0A0A0AFFH);
NEW(PrototypeClTextTitle, NIL, Strings.NewString("ClTextTitle"), Strings.NewString("Text color of title row"));
PrototypeClTextTitle.Set(WMGraphics.Black);
NEW(PrototypeClTextWeekend, NIL, Strings.NewString("ClTextWeekend"), Strings.NewString("Text color of weekend days"));
PrototypeClTextWeekend.Set(WMGraphics.Black);
NEW(PrototypeClTextCurrentDay, NIL, Strings.NewString("ClTextCurrentDay"), Strings.NewString("Text color of current day"));
PrototypeClTextCurrentDay.Set(WMGraphics.Red);
NEW(PrototypeClTextOtherMonths, NIL, Strings.NewString("ClTextOtherMonths"), Strings.NewString("Text color of other months displayed"));
PrototypeClTextOtherMonths.Set(0CCCCCCFFH);
NEW(PrototypeClMouseOver, NIL, Strings.NewString("ClMouseOver"), Strings.NewString("Background color of mouse over cell"));
PrototypeClMouseOver.Set(0FFFF0060H);
NEW(PrototypeCurrentDayImageName, NIL, Strings.NewString("CurrentDayImageName"), Strings.NewString("Filename of current day image"));
PrototypeCurrentDayImageName.Set(NIL);
NEW(PrototypeBackgroundImageName, NIL, Strings.NewString("BackgroundImageName"), Strings.NewString("Filename of background image"));
PrototypeBackgroundImageName.Set(NIL);
END InitPrototypes;
PROCEDURE IncCount;
BEGIN {EXCLUSIVE}
INC(nofWindows)
END IncCount;
PROCEDURE DecCount;
BEGIN {EXCLUSIVE}
DEC(nofWindows)
END DecCount;
PROCEDURE Cleanup;
VAR die : KillerMsg;
msg : WMMessages.Message;
m : WMWindowManager.WindowManager;
BEGIN {EXCLUSIVE}
NEW(die);
msg.ext := die;
msg.msgType := WMMessages.MsgExt;
m := WMWindowManager.GetDefaultManager();
m.Broadcast(msg);
AWAIT(nofWindows = 0)
END Cleanup;
BEGIN
nofWindows := 0;
InitStrings;
InitPrototypes;
Modules.InstallTermHandler(Cleanup);
WeekDay[0] := "ERROR";
WeekDay[Monday] := "Mo";
WeekDay[Tuesday] := "Tu";
WeekDay[Wednesday] := "We";
WeekDay[Thursday] := "Th";
WeekDay[Friday] := "Fr";
WeekDay[Saturday] := "Sa";
WeekDay[Sunday] := "Su";
END WMCalendar.
WMCalendar.Open ~
SystemTools.Free WMCalendar ~