Calendar - for "REAL" programmers: Difference between revisions
Content added Content deleted
m (Omit Factor since its primitive words are lower case) |
(→{{header|Visual Basic .NET}}: Added VB.NET) |
||
Line 3,466: | Line 3,466: | ||
21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28 |
21 22 23 24 25 26 27 18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28 |
||
28 29 30 31 25 26 27 28 29 30 31 29 30 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31 |
28 29 30 31 25 26 27 28 29 30 31 29 30 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31 |
||
</pre> |
|||
=={{header|Visual Basic .NET}}== |
|||
'''Compiler:''' Roslyn Visual Basic (language version >= 15.8) |
|||
{{works with|.NET Core|2.1}} |
|||
Copied from [[Calendar#Visual_Basic_.NET]] and converted to uppercase. See entry there for description. |
|||
<lang vbnet>OPTION COMPARE BINARY |
|||
OPTION EXPLICIT ON |
|||
OPTION INFER ON |
|||
OPTION STRICT ON |
|||
IMPORTS SYSTEM.GLOBALIZATION |
|||
IMPORTS SYSTEM.TEXT |
|||
IMPORTS SYSTEM.RUNTIME.INTEROPSERVICES |
|||
IMPORTS SYSTEM.RUNTIME.COMPILERSERVICES |
|||
MODULE ARGHELPER |
|||
READONLY _ARGDICT AS NEW DICTIONARY(OF STRING, STRING)() |
|||
DELEGATE FUNCTION TRYPARSE(OF T, TRESULT)(VALUE AS T, <OUT> BYREF RESULT AS TRESULT) AS BOOLEAN |
|||
SUB INITIALIZEARGUMENTS(ARGS AS STRING()) |
|||
FOR EACH ITEM IN ARGS |
|||
ITEM = ITEM.TOUPPERINVARIANT() |
|||
IF ITEM.LENGTH > 0 ANDALSO ITEM(0) <> """"C THEN |
|||
DIM COLONPOS = ITEM.INDEXOF(":"C, STRINGCOMPARISON.ORDINAL) |
|||
IF COLONPOS <> -1 THEN |
|||
' SPLIT ARGUMENTS WITH COLUMNS INTO KEY(PART BEFORE COLON) / VALUE(PART AFTER COLON) PAIRS. |
|||
_ARGDICT.ADD(ITEM.SUBSTRING(0, COLONPOS), ITEM.SUBSTRING(COLONPOS + 1, ITEM.LENGTH - COLONPOS - 1)) |
|||
END IF |
|||
END IF |
|||
NEXT |
|||
END SUB |
|||
SUB FROMARGUMENT(OF T)( |
|||
KEY AS STRING, |
|||
<OUT> BYREF VAR AS T, |
|||
GETDEFAULT AS FUNC(OF T), |
|||
TRYPARSE AS TRYPARSE(OF STRING, T), |
|||
OPTIONAL VALIDATE AS PREDICATE(OF T) = NOTHING) |
|||
DIM VALUE AS STRING = NOTHING |
|||
IF _ARGDICT.TRYGETVALUE(KEY.TOUPPERINVARIANT(), VALUE) THEN |
|||
IF NOT (TRYPARSE(VALUE, VAR) ANDALSO (VALIDATE IS NOTHING ORELSE VALIDATE(VAR))) THEN |
|||
CONSOLE.WRITELINE($"INVALID VALUE FOR {KEY}: {VALUE}") |
|||
ENVIRONMENT.EXIT(-1) |
|||
END IF |
|||
ELSE |
|||
VAR = GETDEFAULT() |
|||
END IF |
|||
END SUB |
|||
END MODULE |
|||
MODULE PROGRAM |
|||
SUB MAIN(ARGS AS STRING()) |
|||
DIM DT AS DATE |
|||
DIM COLUMNS, ROWS, MONTHSPERROW AS INTEGER |
|||
DIM VERTSTRETCH, HORIZSTRETCH, RESIZEWINDOW AS BOOLEAN |
|||
INITIALIZEARGUMENTS(ARGS) |
|||
FROMARGUMENT("DATE", DT, FUNCTION() NEW DATE(1969, 1, 1), ADDRESSOF DATE.TRYPARSE) |
|||
FROMARGUMENT("COLS", COLUMNS, FUNCTION() 80, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V >= 20) |
|||
FROMARGUMENT("ROWS", ROWS, FUNCTION() 43, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V >= 0) |
|||
FROMARGUMENT("MS/ROW", MONTHSPERROW, FUNCTION() 0, ADDRESSOF INTEGER.TRYPARSE, FUNCTION(V) V <= 12 ANDALSO V <= COLUMNS \ 20) |
|||
FROMARGUMENT("VSTRETCH", VERTSTRETCH, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE) |
|||
FROMARGUMENT("HSTRETCH", HORIZSTRETCH, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE) |
|||
FROMARGUMENT("WSIZE", RESIZEWINDOW, FUNCTION() TRUE, ADDRESSOF BOOLEAN.TRYPARSE) |
|||
' THE SCROLL BAR IN COMMAND PROMPT SEEMS TO TAKE UP PART OF THE LAST COLUMN. |
|||
IF RESIZEWINDOW THEN |
|||
CONSOLE.WINDOWWIDTH = COLUMNS + 1 |
|||
CONSOLE.WINDOWHEIGHT = ROWS |
|||
END IF |
|||
IF MONTHSPERROW < 1 THEN MONTHSPERROW = MATH.MAX(COLUMNS \ 22, 1) |
|||
FOR EACH ROW IN GETCALENDARROWS(DT:=DT, WIDTH:=COLUMNS, HEIGHT:=ROWS, MONTHSPERROW:=MONTHSPERROW, VERTSTRETCH:=VERTSTRETCH, HORIZSTRETCH:=HORIZSTRETCH) |
|||
CONSOLE.WRITE(ROW) |
|||
NEXT |
|||
END SUB |
|||
ITERATOR FUNCTION GETCALENDARROWS( |
|||
DT AS DATE, |
|||
WIDTH AS INTEGER, |
|||
HEIGHT AS INTEGER, |
|||
MONTHSPERROW AS INTEGER, |
|||
VERTSTRETCH AS BOOLEAN, |
|||
HORIZSTRETCH AS BOOLEAN) AS IENUMERABLE(OF STRING) |
|||
DIM YEAR = DT.YEAR |
|||
DIM CALENDARROWCOUNT AS INTEGER = CINT(MATH.CEILING(12 / MONTHSPERROW)) |
|||
' MAKE ROOM FOR THE THREE EMPTY LINES ON TOP. |
|||
DIM MONTHGRIDHEIGHT AS INTEGER = HEIGHT - 3 |
|||
YIELD "[SNOOPY]".PADCENTER(WIDTH) & ENVIRONMENT.NEWLINE |
|||
YIELD YEAR.TOSTRING(CULTUREINFO.INVARIANTCULTURE).PADCENTER(WIDTH) & ENVIRONMENT.NEWLINE |
|||
YIELD ENVIRONMENT.NEWLINE |
|||
DIM MONTH = 0 |
|||
DO WHILE MONTH < 12 |
|||
DIM ROWHIGHESTMONTH = MATH.MIN(MONTH + MONTHSPERROW, 12) |
|||
DIM CELLWIDTH = WIDTH \ MONTHSPERROW |
|||
DIM CELLCONTENTWIDTH = IF(MONTHSPERROW = 1, CELLWIDTH, (CELLWIDTH * 19) \ 20) |
|||
DIM CELLHEIGHT = MONTHGRIDHEIGHT \ CALENDARROWCOUNT |
|||
DIM CELLCONTENTHEIGHT = (CELLHEIGHT * 19) \ 20 |
|||
' CREATES A MONTH CELL FOR THE SPECIFIED MONTH (1-12). |
|||
DIM GETMONTHFROM = |
|||
FUNCTION(M AS INTEGER) BUILDMONTH( |
|||
DT:=NEW DATE(DT.YEAR, M, 1), |
|||
WIDTH:=CELLCONTENTWIDTH, |
|||
HEIGHT:=CELLCONTENTHEIGHT, |
|||
VERTSTRETCH:=VERTSTRETCH, |
|||
HORIZSTRETCH:=HORIZSTRETCH).SELECT(FUNCTION(X) X.PADCENTER(CELLWIDTH)) |
|||
' THE MONTHS IN THIS ROW OF THE CALENDAR. |
|||
DIM MONTHSTHISROW AS IENUMERABLE(OF IENUMERABLE(OF STRING)) = |
|||
ENUMERABLE.SELECT(ENUMERABLE.RANGE(MONTH + 1, ROWHIGHESTMONTH - MONTH), GETMONTHFROM) |
|||
DIM CALENDARROW AS IENUMERABLE(OF STRING) = |
|||
INTERLEAVED( |
|||
MONTHSTHISROW, |
|||
USEINNERSEPARATOR:=FALSE, |
|||
USEOUTERSEPARATOR:=TRUE, |
|||
OUTERSEPARATOR:=ENVIRONMENT.NEWLINE) |
|||
DIM EN = CALENDARROW.GETENUMERATOR() |
|||
DIM HASNEXT = EN.MOVENEXT() |
|||
DO WHILE HASNEXT |
|||
DIM CURRENT AS STRING = EN.CURRENT |
|||
' TO MAINTAIN THE (NOT STRICTLY NEEDED) CONTRACT OF YIELDING COMPLETE ROWS, KEEP THE NEWLINE AFTER |
|||
' THE CALENDAR ROW WITH THE LAST TERMINAL ROW OF THE ROW. |
|||
HASNEXT = EN.MOVENEXT() |
|||
YIELD IF(HASNEXT, CURRENT, CURRENT & ENVIRONMENT.NEWLINE) |
|||
LOOP |
|||
MONTH += MONTHSPERROW |
|||
LOOP |
|||
END FUNCTION |
|||
''' <SUMMARY> |
|||
''' INTERLEAVES THE ELEMENTS OF THE SPECIFIED SUB-SOURCES BY MAKING SUCCESSIVE PASSES THROUGH THE SOURCE |
|||
''' ENUMERABLE, YIELDING A SINGLE ELEMENT FROM EACH SUB-SOURCE IN SEQUENCE IN EACH PASS, OPTIONALLY INSERTING A |
|||
''' SEPARATOR BETWEEN ELEMENTS OF ADJACENT SUB-SOURCES AND OPTIONALLY A DIFFERENT SEPARATOR AT THE END OF EACH |
|||
''' PASS THROUGH ALL THE SOURCES. (I.E., BETWEEN ELEMENTS OF THE LAST AND FIRST SOURCE) |
|||
''' </SUMMARY> |
|||
''' <TYPEPARAM NAME="T">THE TYPE OF THE ELEMENTS OF THE SUB-SOURCES.</TYPEPARAM> |
|||
''' <PARAM NAME="SOURCES">A SEQUENCE OF THE SEQUENCES WHOSE ELEMENTS ARE TO BE INTERLEAVED.</PARAM> |
|||
''' <PARAM NAME="USEINNERSEPARATOR">WHETHER TO INSERT <PARAMREF NAME="USEINNERSEPARATOR"/> BETWEEN THE ELEMENTS OFADJACENT SUB-SOURCES.</PARAM> |
|||
''' <PARAM NAME="INNERSEPARATOR">THE SEPARATOR BETWEEN ELEMENTS OF ADJACENT SUB-SOURCES.</PARAM> |
|||
''' <PARAM NAME="USEOUTERSEPARATOR">WHETHER TO INSERT <PARAMREF NAME="OUTERSEPARATOR"/> BETWEEN THE ELEMENTS OF THE LAST AND FIRST SUB-SOURCES.</PARAM> |
|||
''' <PARAM NAME="OUTERSEPARATOR">THE SEPARATOR BETWEEN ELEMENTS OF THE LAST AND FIRST SUB-SOURCE.</PARAM> |
|||
''' <PARAM NAME="WHILEANY">IF <SEE LANGWORD="TRUE"/>, THE ENUMERATION CONTINUES UNTIL EVERY GIVEN SUBSOURCE IS EMPTY; |
|||
''' IF <SEE LANGWORD="FALSE"/>, THE ENUMERATION STOPS AS SOON AS ANY ENUMERABLE NO LONGER HAS AN ELEMENT TO SUPPLY FOR THE NEXT PASS.</PARAM> |
|||
ITERATOR FUNCTION INTERLEAVED(OF T)( |
|||
SOURCES AS IENUMERABLE(OF IENUMERABLE(OF T)), |
|||
OPTIONAL USEINNERSEPARATOR AS BOOLEAN = FALSE, |
|||
OPTIONAL INNERSEPARATOR AS T = NOTHING, |
|||
OPTIONAL USEOUTERSEPARATOR AS BOOLEAN = FALSE, |
|||
OPTIONAL OUTERSEPARATOR AS T = NOTHING, |
|||
OPTIONAL WHILEANY AS BOOLEAN = TRUE) AS IENUMERABLE(OF T) |
|||
DIM SOURCEENUMERATORS AS IENUMERATOR(OF T)() = NOTHING |
|||
TRY |
|||
SOURCEENUMERATORS = SOURCES.SELECT(FUNCTION(X) X.GETENUMERATOR()).TOARRAY() |
|||
DIM NUMSOURCES = SOURCEENUMERATORS.LENGTH |
|||
DIM ENUMERATORSTATES(NUMSOURCES - 1) AS BOOLEAN |
|||
DIM ANYPREVITERS AS BOOLEAN = FALSE |
|||
DO |
|||
' INDICES OF FIRST AND LAST SUB-SOURCES THAT HAVE ELEMENTS. |
|||
DIM FIRSTACTIVE = -1, LASTACTIVE = -1 |
|||
' DETERMINE WHETHER EACH SUB-SOURCE THAT STILL HAVE ELEMENTS. |
|||
FOR I = 0 TO NUMSOURCES - 1 |
|||
ENUMERATORSTATES(I) = SOURCEENUMERATORS(I).MOVENEXT() |
|||
IF ENUMERATORSTATES(I) THEN |
|||
IF FIRSTACTIVE = -1 THEN FIRSTACTIVE = I |
|||
LASTACTIVE = I |
|||
END IF |
|||
NEXT |
|||
' DETERMINE WHETHER TO YIELD ANYTHING IN THIS ITERATION BASED ON WHETHER WHILEANY IS TRUE. |
|||
' NOT YIELDING ANYTHING THIS ITERATION IMPLIES THAT THE ENUMERATION HAS ENDED. |
|||
DIM THISITERHASRESULTS AS BOOLEAN = IF(WHILEANY, FIRSTACTIVE <> -1, FIRSTACTIVE = 0 ANDALSO LASTACTIVE = NUMSOURCES - 1) |
|||
IF NOT THISITERHASRESULTS THEN EXIT DO |
|||
' DON'T INSERT A SEPARATOR ON THE FIRST PASS. |
|||
IF ANYPREVITERS THEN |
|||
IF USEOUTERSEPARATOR THEN YIELD OUTERSEPARATOR |
|||
ELSE |
|||
ANYPREVITERS = TRUE |
|||
END IF |
|||
' GO THROUGH AND YIELD FROM THE SUB-SOURCES THAT STILL HAVE ELEMENTS. |
|||
FOR I = 0 TO NUMSOURCES - 1 |
|||
IF ENUMERATORSTATES(I) THEN |
|||
' DON'T INSERT A SEPARATOR BEFORE THE FIRST ELEMENT. |
|||
IF I > FIRSTACTIVE ANDALSO USEINNERSEPARATOR THEN YIELD INNERSEPARATOR |
|||
YIELD SOURCEENUMERATORS(I).CURRENT |
|||
END IF |
|||
NEXT |
|||
LOOP |
|||
FINALLY |
|||
IF SOURCEENUMERATORS ISNOT NOTHING THEN |
|||
FOR EACH EN IN SOURCEENUMERATORS |
|||
EN.DISPOSE() |
|||
NEXT |
|||
END IF |
|||
END TRY |
|||
END FUNCTION |
|||
''' <SUMMARY> |
|||
''' RETURNS THE ROWS REPRESENTING ONE MONTH CELL WITHOUT TRAILING NEWLINES. APPROPRIATE LEADING AND TRAILING |
|||
''' WHITESPACE IS ADDED SO THAT EVERY ROW HAS THE LENGTH OF WIDTH. |
|||
''' </SUMMARY> |
|||
''' <PARAM NAME="DT">A DATE WITHIN THE MONTH TO REPRESENT.</PARAM> |
|||
''' <PARAM NAME="WIDTH">THE WIDTH OF THE CELL.</PARAM> |
|||
''' <PARAM NAME="HEIGHT">THE HEIGHT.</PARAM> |
|||
''' <PARAM NAME="VERTSTRETCH">IF <SEE LANGWORD="TRUE" />, BLANK ROWS ARE INSERTED TO FIT THE AVAILABLE HEIGHT. |
|||
''' OTHERWISE, THE CELL HAS A CONSTANT HEIGHT OF </PARAM> |
|||
''' <PARAM NAME="HORIZSTRETCH">IF <SEE LANGWORD="TRUE" />, THE SPACING BETWEEN INDIVIDUAL DAYS IS INCREASED TO |
|||
''' FIT THE AVAILABLE WIDTH. OTHERWISE, THE CELL HAS A CONSTANT WIDTH OF 20 CHARACTERS AND IS PADDED TO BE IN |
|||
''' THE CENTER OF THE EXPECTED WIDTH.</PARAM> |
|||
ITERATOR FUNCTION BUILDMONTH(DT AS DATE, WIDTH AS INTEGER, HEIGHT AS INTEGER, VERTSTRETCH AS BOOLEAN, HORIZSTRETCH AS BOOLEAN) AS IENUMERABLE(OF STRING) |
|||
CONST DAY_WDT = 2 ' WIDTH OF A DAY. |
|||
CONST ALLDAYS_WDT = DAY_WDT * 7 ' WIDTH OF AL LDAYS COMBINED. |
|||
' NORMALIZE THE DATE TO JANUARY 1. |
|||
DT = NEW DATE(DT.YEAR, DT.MONTH, 1) |
|||
' HORIZONTAL WHITESPACE BETWEEN DAYS OF THE WEEK. CONSTANT OF 6 REPRESENTS 6 SEPARATORS PER LINE. |
|||
DIM DAYSEP AS NEW STRING(" "C, MATH.MIN((WIDTH - ALLDAYS_WDT) \ 6, IF(HORIZSTRETCH, INTEGER.MAXVALUE, 1))) |
|||
' NUMBER OF BLANK LINES BETWEEN ROWS. |
|||
DIM VERTBLANKCOUNT = IF(NOT VERTSTRETCH, 0, (HEIGHT - 8) \ 7) |
|||
' WIDTH OF EACH DAY * 7 DAYS IN ONE ROW + DAY SEPARATOR LENGTH * 6 SEPARATORS PER LINE. |
|||
DIM BLOCKWIDTH = ALLDAYS_WDT + DAYSEP.LENGTH * 6 |
|||
' THE WHITESPACE AT THE BEGINNING OF EACH LINE. |
|||
DIM LEFTPAD AS NEW STRING(" "C, (WIDTH - BLOCKWIDTH) \ 2) |
|||
' THE WHITESPACE FOR BLANK LINES. |
|||
DIM FULLPAD AS NEW STRING(" "C, WIDTH) |
|||
' LINES ARE "STAGED" IN THE STRINGBUILDER. |
|||
DIM SB AS NEW STRINGBUILDER(LEFTPAD) |
|||
DIM NUMLINES = 0 |
|||
' GET THE CURRENT LINE SO FAR FORM THE STRINGBUILDER AND BEGIN A NEW LINE. |
|||
' RETURNS THE CURRENT LINE AND TRAILING BLANK LINES USED FOR VERTICAL PADDING (IF ANY). |
|||
' RETURNS EMPTY ENUMERABLE IF THE HEIGHT REQUIREMENT HAS BEEN REACHED. |
|||
DIM ENDLINE = |
|||
FUNCTION() AS IENUMERABLE(OF STRING) |
|||
DIM FINISHEDLINE AS STRING = SB.TOSTRING().PADRIGHT(WIDTH) |
|||
SB.CLEAR() |
|||
SB.APPEND(LEFTPAD) |
|||
' USE AN INNER ITERATOR TO PREVENT LAZY EXECUTION OF SIDE EFFECTS OF OUTER FUNCTION. |
|||
RETURN IF(NUMLINES >= HEIGHT, |
|||
ENUMERABLE.EMPTY(OF STRING)(), |
|||
ITERATOR FUNCTION() AS IENUMERABLE(OF STRING) |
|||
YIELD FINISHEDLINE |
|||
NUMLINES += 1 |
|||
FOR I = 1 TO VERTBLANKCOUNT |
|||
IF NUMLINES >= HEIGHT THEN RETURN |
|||
YIELD FULLPAD |
|||
NUMLINES += 1 |
|||
NEXT |
|||
END FUNCTION()) |
|||
END FUNCTION |
|||
' YIELD THE MONTH NAME. |
|||
SB.APPEND(PADCENTER(DT.TOSTRING("MMMM", CULTUREINFO.INVARIANTCULTURE), BLOCKWIDTH).TOUPPER()) |
|||
FOR EACH L IN ENDLINE() |
|||
YIELD L |
|||
NEXT |
|||
' YIELD THE HEADER OF WEEKDAY NAMES. |
|||
DIM WEEKNMABBREVS = [ENUM].GETNAMES(GETTYPE(DAYOFWEEK)).SELECT(FUNCTION(X) X.SUBSTRING(0, 2).TOUPPER()) |
|||
SB.APPEND(STRING.JOIN(DAYSEP, WEEKNMABBREVS)) |
|||
FOR EACH L IN ENDLINE() |
|||
YIELD L |
|||
NEXT |
|||
' DAY OF WEEK OF FIRST DAY OF MONTH. |
|||
DIM STARTWKDY = CINT(DT.DAYOFWEEK) |
|||
' INITIALIZE WITH EMPTY SPACE FOR THE FIRST LINE. |
|||
DIM FIRSTPAD AS NEW STRING(" "C, (DAY_WDT + DAYSEP.LENGTH) * STARTWKDY) |
|||
SB.APPEND(FIRSTPAD) |
|||
DIM D = DT |
|||
DO WHILE D.MONTH = DT.MONTH |
|||
SB.APPENDFORMAT(CULTUREINFO.INVARIANTCULTURE, $"{{0,{DAY_WDT}}}", D.DAY) |
|||
' EACH ROW ENDS ON SATURDAY. |
|||
IF D.DAYOFWEEK = DAYOFWEEK.SATURDAY THEN |
|||
FOR EACH L IN ENDLINE() |
|||
YIELD L |
|||
NEXT |
|||
ELSE |
|||
SB.APPEND(DAYSEP) |
|||
END IF |
|||
D = D.ADDDAYS(1) |
|||
LOOP |
|||
' KEEP ADDING EMPTY LINES UNTIL THE HEIGHT QUOTA IS MET. |
|||
DIM NEXTLINES AS IENUMERABLE(OF STRING) |
|||
DO |
|||
NEXTLINES = ENDLINE() |
|||
FOR EACH L IN NEXTLINES |
|||
YIELD L |
|||
NEXT |
|||
LOOP WHILE NEXTLINES.ANY() |
|||
END FUNCTION |
|||
''' <SUMMARY> |
|||
''' RETURNS A NEW STRING THAT CENTER-ALIGNS THE CHARACTERS IN THIS STRING BY PADDING TO THE LEFT AND RIGHT WITH |
|||
''' THE SPECIFIED CHARACTER TO A SPECIFIED TOTAL LENGTH. |
|||
''' </SUMMARY> |
|||
''' <PARAM NAME="S">THE STRING TO CENTER-ALIGN.</PARAM> |
|||
''' <PARAM NAME="TOTALWIDTH">THE NUMBER OF CHARACTERS IN THE RESULTING STRING.</PARAM> |
|||
''' <PARAM NAME="PADDINGCHAR">THE PADDING CHARACTER.</PARAM> |
|||
<EXTENSION()> |
|||
PRIVATE FUNCTION PADCENTER(S AS STRING, TOTALWIDTH AS INTEGER, OPTIONAL PADDINGCHAR AS CHAR = " "C) AS STRING |
|||
RETURN S.PADLEFT(((TOTALWIDTH - S.LENGTH) \ 2) + S.LENGTH, PADDINGCHAR).PADRIGHT(TOTALWIDTH, PADDINGCHAR) |
|||
END FUNCTION |
|||
END MODULE</lang> |
|||
{{out|input=COLS:132 ROWS:25 MS/ROW:6 HSTRETCH:FALSE VSTRETCH:FALSE}} |
|||
<pre> [SNOOPY] |
|||
1969 |
|||
JANUARY FEBRUARY MARCH APRIL MAY JUNE |
|||
SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA |
|||
1 2 3 4 1 1 1 2 3 4 5 1 2 3 1 2 3 4 5 6 7 |
|||
5 6 7 8 9 10 11 2 3 4 5 6 7 8 2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14 |
|||
12 13 14 15 16 17 18 9 10 11 12 13 14 15 9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21 |
|||
19 20 21 22 23 24 25 16 17 18 19 20 21 22 16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28 |
|||
26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31 29 30 |
|||
30 31 |
|||
JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER |
|||
SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA |
|||
1 2 3 4 5 1 2 1 2 3 4 5 6 1 2 3 4 1 1 2 3 4 5 6 |
|||
6 7 8 9 10 11 12 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 |
|||
13 14 15 16 17 18 19 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 |
|||
20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 |
|||
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 |
|||
31 30 |
|||
</pre> |
</pre> |
||