slithernix-cdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,770 @@
1
+ require_relative 'cdk_objs'
2
+
3
+ module CDK
4
+ class CALENDAR < CDK::CDKOBJS
5
+ attr_accessor :week_base
6
+ attr_reader :day, :month, :year
7
+
8
+ MONTHS_OF_THE_YEAR = [
9
+ 'NULL',
10
+ 'January',
11
+ 'February',
12
+ 'March',
13
+ 'April',
14
+ 'May',
15
+ 'June',
16
+ 'July',
17
+ 'August',
18
+ 'September',
19
+ 'October',
20
+ 'November',
21
+ 'December',
22
+ ]
23
+
24
+ DAYS_OF_THE_MONTH = [
25
+ -1,
26
+ 31,
27
+ 28,
28
+ 31,
29
+ 30,
30
+ 31,
31
+ 30,
32
+ 31,
33
+ 31,
34
+ 30,
35
+ 31,
36
+ 30,
37
+ 31,
38
+ ]
39
+
40
+ MAX_DAYS = 32
41
+ MAX_MONTHS = 13
42
+ MAX_YEARS = 140
43
+
44
+ CALENDAR_LIMIT = MAX_DAYS * MAX_MONTHS * MAX_YEARS
45
+
46
+ def self.CALENDAR_INDEX(d, m, y)
47
+ (y * CDK::CALENDAR::MAX_MONTHS + m) * CDK::CALENDAR::MAX_DAYS + d
48
+ end
49
+
50
+ def setCalendarCell(d, m, y, value)
51
+ @marker[CDK::CALENDAR.CALENDAR_INDEX(d, m, y)] = value
52
+ end
53
+
54
+ def getCalendarCell(d, m, y)
55
+ @marker[CDK::CALENDAR.CALENDAR_INDEX(d, m, y)]
56
+ end
57
+
58
+ def initialize(cdkscreen, xplace, yplace, title, day, month, year,
59
+ day_attrib, month_attrib, year_attrib, highlight, box, shadow)
60
+ super()
61
+ parent_width = cdkscreen.window.maxx
62
+ parent_height = cdkscreen.window.maxy
63
+ box_width = 24
64
+ box_height = 11
65
+ dayname = 'Su Mo Tu We Th Fr Sa '
66
+ bindings = {
67
+ 'T' => Curses::KEY_HOME,
68
+ 't' => Curses::KEY_HOME,
69
+ 'n' => Curses::KEY_NPAGE,
70
+ CDK::FORCHAR => Curses::KEY_NPAGE,
71
+ 'p' => Curses::KEY_PPAGE,
72
+ CDK::BACKCHAR => Curses::KEY_PPAGE,
73
+ }
74
+
75
+ self.setBox(box)
76
+
77
+ box_width = self.setTitle(title, box_width)
78
+ box_height += @title_lines
79
+
80
+ # Make sure we didn't extend beyond the dimensions of the window.
81
+ box_width = [box_width, parent_width].min
82
+ box_height = [box_height, parent_height].min
83
+
84
+ # Rejustify the x and y positions if we need to.
85
+ xtmp = [xplace]
86
+ ytmp = [yplace]
87
+ CDK.alignxy(cdkscreen.window, xtmp, ytmp, box_width, box_height)
88
+ xpos = xtmp[0]
89
+ ypos = ytmp[0]
90
+
91
+ # Create the calendar window.
92
+ @win = Curses::Window.new(box_height, box_width, ypos, xpos)
93
+
94
+ # Is the window nil?
95
+ if @win.nil?
96
+ self.destroy
97
+ return nil
98
+ end
99
+ @win.keypad(true)
100
+
101
+ # Set some variables.
102
+ @x_offset = (box_width - 20) / 2
103
+ @field_width = box_width - 2 * (1 + @border_size)
104
+
105
+ # Set months and day names
106
+ @month_name = CDK::CALENDAR::MONTHS_OF_THE_YEAR.clone
107
+ @day_name = dayname
108
+
109
+ # Set the rest of the widget values.
110
+ @screen = cdkscreen
111
+ @parent = cdkscreen.window
112
+ @shadow_win = nil
113
+ @xpos = xpos
114
+ @ypos = ypos
115
+ @box_width = box_width
116
+ @box_height = box_height
117
+ @day = day
118
+ @month = month
119
+ @year = year
120
+ @day_attrib = day_attrib
121
+ @month_attrib = month_attrib
122
+ @year_attrib = year_attrib
123
+ @highlight = highlight
124
+ @width = box_width
125
+ @accepts_focus = true
126
+ @input_window = @win
127
+ @week_base = 0
128
+ @shadow = shadow
129
+ @label_win = @win.subwin(1, @field_width,
130
+ ypos + @title_lines + 1, xpos + 1 + @border_size)
131
+ if @label_win.nil?
132
+ self.destroy
133
+ return nil
134
+ end
135
+
136
+ @field_win = @win.subwin(7, 20,
137
+ ypos + @title_lines + 3, xpos + @x_offset)
138
+ if @field_win.nil?
139
+ self.destroy
140
+ return nil
141
+ end
142
+ self.setBox(box)
143
+
144
+ @marker = [0] * CDK::CALENDAR::CALENDAR_LIMIT
145
+
146
+ # If the day/month/year values were 0, then use today's date.
147
+ if @day == 0 && @month == 0 && @year == 0
148
+ date_info = Time.new.gmtime
149
+ @day = date_info.day
150
+ @month = date_info.month
151
+ @year = date_info
152
+ end
153
+
154
+ # Verify the dates provided.
155
+ self.verifyCalendarDate
156
+
157
+ # Determine which day the month starts on.
158
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
159
+
160
+ # If a shadow was requested, then create the shadow window.
161
+ if shadow
162
+ @shadow_win = Curses::Window.new(box_height, box_width,
163
+ ypos + 1, xpos + 1)
164
+ end
165
+
166
+ # Setup the key bindings.
167
+ bindings.each do |from, to|
168
+ self.bind(:CALENDAR, from, :getc, to)
169
+ end
170
+
171
+ cdkscreen.register(:CALENDAR, self)
172
+ end
173
+
174
+ # This function lets the user play with this widget.
175
+ def activate(actions)
176
+ ret = -1
177
+ self.draw(@box)
178
+
179
+ if actions.nil? || actions.size == 0
180
+ while true
181
+ input = self.getch([])
182
+
183
+ # Inject the character into the widget.
184
+ ret = self.inject(input)
185
+ if @exit_type != :EARLY_EXIT
186
+ return ret
187
+ end
188
+ end
189
+ else
190
+ # Inject each character one at a time.
191
+ actions.each do |action|
192
+ ret = self.inject(action)
193
+ if @exit_type != :EARLY_EXIT
194
+ return ret
195
+ end
196
+ end
197
+ end
198
+ return ret
199
+ end
200
+
201
+ # This injects a single character into the widget.
202
+ def inject(input)
203
+ # Declare local variables
204
+ pp_return = 1
205
+ ret = -1
206
+ complete = false
207
+
208
+ # Set the exit type
209
+ self.setExitType(0)
210
+
211
+ # Refresh the widget field.
212
+ self.drawField
213
+
214
+ # Check if there is a pre-process function to be called.
215
+ unless @pre_process_func.nil?
216
+ pp_return = @pre_process_func.call(:CALENDAR, self,
217
+ @pre_process_data, input)
218
+ end
219
+
220
+ # Should we continue?
221
+ if pp_return != 0
222
+ # Check a predefined binding
223
+ if self.checkBind(:CALENDAR, input)
224
+ self.checkEarlyExit
225
+ complete = true
226
+ else
227
+ case input
228
+ when Curses::KEY_UP
229
+ self.decrementCalendarDay(7)
230
+ when Curses::KEY_DOWN
231
+ self.incrementCalendarDay(7)
232
+ when Curses::KEY_LEFT
233
+ self.decrementCalendarDay(1)
234
+ when Curses::KEY_RIGHT
235
+ self.incrementCalendarDay(1)
236
+ when Curses::KEY_NPAGE
237
+ self.incrementCalendarMonth(1)
238
+ when Curses::KEY_PPAGE
239
+ self.decrementCalendarMonth(1)
240
+ when 'N'
241
+ self.incrementCalendarMonth(6)
242
+ when 'P'
243
+ self.decrementCalendarMonth(6)
244
+ when '-'
245
+ self.decrementCalendarYear(1)
246
+ when '+'
247
+ self.incrementCalendarYear(1)
248
+ when Curses::KEY_HOME
249
+ self.setDate(-1, -1, -1)
250
+ when CDK::KEY_ESC
251
+ self.setExitType(input)
252
+ complete = true
253
+ when Curses::Error
254
+ self.setExitType(input)
255
+ complete = true
256
+ when CDK::KEY_TAB, CDK::KEY_RETURN, Curses::KEY_ENTER
257
+ self.setExitType(input)
258
+ ret = self.getCurrentTime
259
+ complete = true
260
+ when CDK::REFRESH
261
+ @screen.erase
262
+ @screen.refresh
263
+ end
264
+ end
265
+
266
+ # Should we do a post-process?
267
+ if !complete && !(@post_process_func.nil?)
268
+ @post_process_func.call(:CALENDAR, self, @post_process_data, input)
269
+ end
270
+ end
271
+
272
+ if !complete
273
+ self.setExitType(0)
274
+ end
275
+
276
+ @result_data = ret
277
+ return ret
278
+ end
279
+
280
+ # This moves the calendar field to the given location.
281
+ def move(xplace, yplace, relative, refresh_flag)
282
+ windows = [@win, @field_win, @label_win, @shadow_win]
283
+ self.move_specific(xplace, yplace, relative, refresh_flag,
284
+ windows, [])
285
+ end
286
+
287
+ # This draws the calendar widget.
288
+ def draw(box)
289
+ header_len = @day_name.size
290
+ col_len = (6 + header_len) / 7
291
+
292
+ # Is there a shadow?
293
+ unless @shadow_win.nil?
294
+ Draw.drawShadow(@shadow_win)
295
+ end
296
+
297
+ # Box the widget if asked.
298
+ if box
299
+ Draw.drawObjBox(@win, self)
300
+ end
301
+
302
+ self.drawTitle(@win)
303
+
304
+ # Draw in the day-of-the-week header.
305
+ (0...7).each do |col|
306
+ src = col_len * ((col + (@week_base % 7)) % 7)
307
+ dst = col_len * col
308
+ Draw.writeChar(@win, @x_offset + dst, @title_lines + 2,
309
+ @day_name[src..-1], CDK::HORIZONTAL, 0, col_len)
310
+ end
311
+
312
+ @win.refresh
313
+ self.drawField
314
+ end
315
+
316
+ # This draws the month field.
317
+ def drawField
318
+ month_name = @month_name[@month]
319
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
320
+ year_index = CDK::CALENDAR.YEAR2INDEX(@year)
321
+ year_len = 0
322
+ save_y = -1
323
+ save_x = -1
324
+
325
+ day = (1 - @week_day + (@week_base % 7))
326
+ if day > 0
327
+ day -= 7
328
+ end
329
+
330
+ (1..6).each do |row|
331
+ (0...7).each do |col|
332
+ if day >= 1 && day <= month_length
333
+ xpos = col * 3
334
+ ypos = row
335
+
336
+ marker = @day_attrib
337
+ temp = '%02d' % day
338
+
339
+ if @day == day
340
+ marker = @highlight
341
+ save_y = ypos + @field_win.begy - @input_window.begy
342
+ save_x = 1
343
+ else
344
+ marker |= self.getMarker(day, @month, year_index)
345
+ end
346
+ Draw.writeCharAttrib(@field_win, xpos, ypos, temp, marker,
347
+ CDK::HORIZONTAL, 0, 2)
348
+ end
349
+ day += 1
350
+ end
351
+ end
352
+ @field_win.refresh
353
+
354
+ # Draw the month in.
355
+ if !(@label_win.nil?)
356
+ temp = '%s %d,' % [month_name, @day]
357
+ Draw.writeChar(@label_win, 0, 0, temp, CDK::HORIZONTAL, 0, temp.size)
358
+ @label_win.clrtoeol
359
+
360
+ # Draw the year in.
361
+ temp = '%d' % [@year]
362
+ year_len = temp.size
363
+ Draw.writeChar(@label_win, @field_width - year_len, 0, temp,
364
+ CDK::HORIZONTAL, 0, year_len)
365
+
366
+ @label_win.move(0, 0)
367
+ @label_win.refresh
368
+ elsif save_y >= 0
369
+ @input_window.move(save_y, save_x)
370
+ @input_window.refresh
371
+ end
372
+ end
373
+
374
+ # This sets multiple attributes of the widget
375
+ def set(day, month, year, day_attrib, month_attrib, year_attrib,
376
+ highlight, box)
377
+ self.setDate(day, month, yar)
378
+ self.setDayAttribute(day_attrib)
379
+ self.setMonthAttribute(month_attrib)
380
+ self.setYearAttribute(year_attrib)
381
+ self.setHighlight(highlight)
382
+ self.setBox(box)
383
+ end
384
+
385
+ # This sets the date and some attributes.
386
+ def setDate(day, month, year)
387
+ # Get the current dates and set the default values for the
388
+ # day/month/year values for the calendar
389
+ date_info = Time.new.gmtime
390
+
391
+ # Set the date elements if we need to.
392
+ @day = if day == -1 then date_info.day else day end
393
+ @month = if month == -1 then date_info.month else month end
394
+ @year = if year == -1 then date_info.year else year end
395
+
396
+ # Verify the date information.
397
+ self.verifyCalendarDate
398
+
399
+ # Get the start of the current month.
400
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
401
+ end
402
+
403
+ # This returns the current date on the calendar.
404
+ def getDate(day, month, year)
405
+ day << @day
406
+ month << @month
407
+ year << @year
408
+ end
409
+
410
+ # This sets the attribute of the days in the calendar.
411
+ def setDayAttribute(attribute)
412
+ @day_attrib = attribute
413
+ end
414
+
415
+ def getDayAttribute
416
+ return @day_attrib
417
+ end
418
+
419
+ # This sets the attribute of the month names in the calendar.
420
+ def setMonthAttribute(attribute)
421
+ @month_attrib = attribute
422
+ end
423
+
424
+ def getMonthAttribute
425
+ return @month_attrib
426
+ end
427
+
428
+ # This sets the attribute of the year in the calendar.
429
+ def setYearAttribute(attribute)
430
+ @year_attrib = attribute
431
+ end
432
+
433
+ def getYearAttribute
434
+ return @year_attrib
435
+ end
436
+
437
+ # This sets the attribute of the highlight box.
438
+ def setHighlight(highlight)
439
+ @highlight = highlight
440
+ end
441
+
442
+ def getHighlight
443
+ return @highlight
444
+ end
445
+
446
+ # This sets the background attribute of the widget.
447
+ def setBKattr(attrib)
448
+ @win.wbkgd(attrib)
449
+ @field_win.wbkgd(attrib)
450
+ unless @label_win.nil?
451
+ @label_win.wbkgd(attrib)
452
+ end
453
+ end
454
+
455
+ # This erases the calendar widget.
456
+ def erase
457
+ if self.validCDKObject
458
+ CDK.eraseCursesWindow(@label_win)
459
+ CDK.eraseCursesWindow(@field_win)
460
+ CDK.eraseCursesWindow(@win)
461
+ CDK.eraseCursesWindow(@shadow_win)
462
+ end
463
+ end
464
+
465
+ # This destroys the calendar
466
+ def destroy
467
+ self.cleanTitle
468
+
469
+ CDK.deleteCursesWindow(@label_win)
470
+ CDK.deleteCursesWindow(@field_win)
471
+ CDK.deleteCursesWindow(@shadow_win)
472
+ CDK.deleteCursesWindow(@win)
473
+
474
+ # Clean the key bindings.
475
+ self.cleanBindings(:CALENDAR)
476
+
477
+ # Unregister the object.
478
+ CDK::SCREEN.unregister(:CALENDAR, self)
479
+ end
480
+
481
+ # This sets a marker on the calendar.
482
+ def setMarker(day, month, year, marker)
483
+ year_index = CDK::CALENDAR.YEAR2INDEX(year)
484
+ oldmarker = self.getMarker(day, month, year)
485
+
486
+ # Check to see if a marker has not already been set
487
+ if oldmarker != 0
488
+ self.setCalendarCell(day, month, year_index,
489
+ oldmarker | Curses::A_BLINK)
490
+ else
491
+ self.setCalendarCell(day, month, year_index, marker)
492
+ end
493
+ end
494
+
495
+ def getMarker(day, month, year)
496
+ result = 0
497
+ year = CDK::CALENDAR.YEAR2INDEX(year)
498
+ if @marker != 0
499
+ result = self.getCalendarCell(day, month, year)
500
+ end
501
+ return result
502
+ end
503
+
504
+ # This sets a marker on the calendar.
505
+ def removeMarker(day, month, year)
506
+ year_index = CDK::CALENDAR.YEAR2INDEX(year)
507
+ self.setCalendarCell(day, month, year_index, 0)
508
+ end
509
+
510
+ # THis function sets the month name.
511
+ def setMonthNames(months)
512
+ (1...[months.size, @month_name.size].min).each do |x|
513
+ @month_name[x] = months[x]
514
+ end
515
+ end
516
+
517
+ # This function sets the day's name
518
+ def setDaysNames(days)
519
+ @day_name = days.clone
520
+ end
521
+
522
+ # This makes sure that the dates provided exist.
523
+ def verifyCalendarDate
524
+ # Make sure the given year is not less than 1900.
525
+ if @year < 1900
526
+ @year = 1900
527
+ end
528
+
529
+ # Make sure the month is within range.
530
+ if @month > 12
531
+ @month = 12
532
+ end
533
+ if @month < 1
534
+ @month = 1
535
+ end
536
+
537
+ # Make sure the day given is within range of the month.
538
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
539
+ if @day < 1
540
+ @day = 1
541
+ end
542
+ if @day > month_length
543
+ @day = month_length
544
+ end
545
+ end
546
+
547
+ # This returns what day of the week the month starts on.
548
+ def self.getMonthStartWeekday(year, month)
549
+ return Time.mktime(year, month, 1, 10, 0, 0).wday
550
+ end
551
+
552
+ # This function returns a 1 if it's a leap year and 0 if not.
553
+ def self.isLeapYear(year)
554
+ result = false
555
+ if year % 4 == 0
556
+ if year % 100 == 0
557
+ if year % 400 == 0
558
+ result = true
559
+ end
560
+ else
561
+ result = true
562
+ end
563
+ end
564
+ return result
565
+ end
566
+
567
+ # This increments the current day by the given value.
568
+ def incrementCalendarDay(adjust)
569
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
570
+
571
+ # Make sure we adjust the day correctly.
572
+ if adjust + @day > month_length
573
+ # Have to increment the month by one.
574
+ @day = @day + adjust - month_length
575
+ self.incrementCalendarMonth(1)
576
+ else
577
+ @day += adjust
578
+ self.drawField
579
+ end
580
+ end
581
+
582
+ # This decrements the current day by the given value.
583
+ def decrementCalendarDay(adjust)
584
+ # Make sure we adjust the day correctly.
585
+ if @day - adjust < 1
586
+ # Set the day according to the length of the month.
587
+ if @month == 1
588
+ # make sure we aren't going past the year limit.
589
+ if @year == 1900
590
+ mesg = [
591
+ '<C></U>Error',
592
+ 'Can not go past the year 1900'
593
+ ]
594
+ CDK.Beep
595
+ @screen.popupLabel(mesg, 2)
596
+ return
597
+ end
598
+ month_length = CDK::CALENDAR.getMonthLength(@year - 1, 12)
599
+ else
600
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month - 1)
601
+ end
602
+
603
+ @day = month_length - (adjust - @day)
604
+
605
+ # Have to decrement the month by one.
606
+ self.decrementCalendarMonth(1)
607
+ else
608
+ @day -= adjust
609
+ self.drawField
610
+ end
611
+ end
612
+
613
+ # This increments the current month by the given value.
614
+ def incrementCalendarMonth(adjust)
615
+ # Are we at the end of the year.
616
+ if @month + adjust > 12
617
+ @month = @month + adjust - 12
618
+ @year += 1
619
+ else
620
+ @month += adjust
621
+ end
622
+
623
+ # Get the length of the current month.
624
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
625
+ if @day > month_length
626
+ @day = month_length
627
+ end
628
+
629
+ # Get the start of the current month.
630
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
631
+
632
+ # Redraw the calendar.
633
+ self.erase
634
+ self.draw(@box)
635
+ end
636
+
637
+ # This decrements the current month by the given value.
638
+ def decrementCalendarMonth(adjust)
639
+ # Are we at the end of the year.
640
+ if @month <= adjust
641
+ if @year == 1900
642
+ mesg = [
643
+ '<C></U>Error',
644
+ 'Can not go past the year 1900',
645
+ ]
646
+ CDK.Beep
647
+ @screen.popupLabel(mesg, 2)
648
+ return
649
+ else
650
+ @month = 13 - adjust
651
+ @year -= 1
652
+ end
653
+ else
654
+ @month -= adjust
655
+ end
656
+
657
+ # Get the length of the current month.
658
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
659
+ if @day > month_length
660
+ @day = month_length
661
+ end
662
+
663
+ # Get the start o the current month.
664
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
665
+
666
+ # Redraw the calendar.
667
+ self.erase
668
+ self.draw(@box)
669
+ end
670
+
671
+ # This increments the current year by the given value.
672
+ def incrementCalendarYear(adjust)
673
+ # Increment the year.
674
+ @year += adjust
675
+
676
+ # If we are in Feb make sure we don't trip into voidness.
677
+ if @month == 2
678
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
679
+ if @day > month_length
680
+ @day = month_length
681
+ end
682
+ end
683
+
684
+ # Get the start of the current month.
685
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
686
+
687
+ # Redraw the calendar.
688
+ self.erase
689
+ self.draw(@box)
690
+ end
691
+
692
+ # This decrements the current year by the given value.
693
+ def decrementCalendarYear(adjust)
694
+ # Make sure we don't go out o bounds.
695
+ if @year - adjust < 1900
696
+ mesg = [
697
+ '<C></U>Error',
698
+ 'Can not go past the year 1900',
699
+ ]
700
+ CDK.Beep
701
+ @screen.popupLabel(mesg, 2)
702
+ return
703
+ end
704
+
705
+ # Decrement the year.
706
+ @year -= adjust
707
+
708
+ # If we are in Feb make sure we don't trip into voidness.
709
+ if @month == 2
710
+ month_length = CDK::CALENDAR.getMonthLength(@year, @month)
711
+ if @day > month_length
712
+ @day = month_length
713
+ end
714
+ end
715
+
716
+ # Get the start of the current month.
717
+ @week_day = CDK::CALENDAR.getMonthStartWeekday(@year, @month)
718
+
719
+ # Redraw the calendar.
720
+ self.erase
721
+ self.draw(@box)
722
+ end
723
+
724
+ # This returns the length of the current month.
725
+ def self.getMonthLength(year, month)
726
+ month_length = DAYS_OF_THE_MONTH[month]
727
+
728
+ if month == 2
729
+ month_length += if CDK::CALENDAR.isLeapYear(year)
730
+ then 1
731
+ else 0
732
+ end
733
+ end
734
+
735
+ return month_length
736
+ end
737
+
738
+ # This returns what day of the week the month starts on.
739
+ def getCurrentTime
740
+ # Determine the current time and determine if we are in DST.
741
+ return Time.mktime(@year, @month, @day, 0, 0, 0).gmtime
742
+ end
743
+
744
+ def focus
745
+ # Original: drawCDKFscale(widget, ObjOf (widget)->box);
746
+ self.draw(@box)
747
+ end
748
+
749
+ def unfocus
750
+ # Original: drawCDKFscale(widget, ObjOf (widget)->box);
751
+ self.draw(@box)
752
+ end
753
+
754
+ def self.YEAR2INDEX(year)
755
+ if year >= 1900
756
+ year - 1900
757
+ else
758
+ year
759
+ end
760
+ end
761
+
762
+ def position
763
+ super(@win)
764
+ end
765
+
766
+ def object_type
767
+ :CALENDAR
768
+ end
769
+ end
770
+ end