bigtinker 0.97 → 0.98

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. data/code/01rwdcore/01rwdcore.rb +6 -6
  2. data/code/01rwdcore/02helptexthashbegin.rb +13 -11
  3. data/code/01rwdcore/jumplinkcommand.rb +14 -4
  4. data/code/01rwdcore/openhelpwindow.rb +7 -0
  5. data/code/01rwdcore/runhelpabout.rb +6 -1
  6. data/code/01rwdcore/runtab.rb +15 -0
  7. data/code/01rwdcore/selectiontab.rb +2 -0
  8. data/code/01rwdcore/setuphelpaboutoptions.rb +2 -0
  9. data/code/01rwdcore/setuptinkerdocuments.rb +1 -0
  10. data/code/01rwdcore/test_cases.rb +100 -51
  11. data/code/01rwdcore/test_harness.rb +8 -1
  12. data/code/01rwdcore/uploadreturns.rb +3 -0
  13. data/code/dd0viewphoto/dd0viewphoto.rb +2 -0
  14. data/code/superant.com.rwdcalendar/gh9calendar.rb +40 -0
  15. data/code/superant.com.rwdcalendar/helptexthashrwdschedule.rb +14 -0
  16. data/code/superant.com.rwdcalendar/openhelpwindowrwdschedule.rb +17 -0
  17. data/code/superant.com.rwdtinkerbackwindow/changelocale.rb +84 -0
  18. data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +0 -1
  19. data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +2 -0
  20. data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +2 -0
  21. data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +3 -1
  22. data/code/superant.com.rwdtinkerbackwindow/listzips.rb +4 -0
  23. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +3 -1
  24. data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +3 -1
  25. data/code/superant.com.rwdtinkerbackwindow/showlocaleoptions.rb +9 -0
  26. data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +1 -0
  27. data/code/superant.com.rwdtinkerbackwindow/viewlogfile.rb +8 -5
  28. data/code/superant.com.schedule/0uninstallapplet.rb +24 -0
  29. data/code/superant.com.schedule/archiveevent.rb +14 -0
  30. data/code/superant.com.schedule/archiveicsevent.rb +14 -0
  31. data/code/superant.com.schedule/cleareventscreendisplay.rb +19 -0
  32. data/code/superant.com.schedule/deleteeventrecord.rb +19 -0
  33. data/code/superant.com.schedule/deleteicseventrecord.rb +19 -0
  34. data/code/superant.com.schedule/deleterwdscheduleupdatefiles.rb +20 -0
  35. data/code/superant.com.schedule/downloadrwdschedulefiles.rb +37 -0
  36. data/code/superant.com.schedule/exporticseventrecord.rb +97 -0
  37. data/code/{superant.com.foldeditor → superant.com.schedule}/helptexthashload.rb +2 -2
  38. data/code/superant.com.schedule/listeventdates.rb +19 -0
  39. data/code/superant.com.schedule/listicseventdates.rb +19 -0
  40. data/code/{superant.com.foldeditor → superant.com.schedule}/loadconfigurationrecord.rb +4 -4
  41. data/code/superant.com.schedule/loadconfigurationvariables.rb +14 -0
  42. data/code/superant.com.schedule/loadeventrecord.rb +38 -0
  43. data/code/superant.com.schedule/loadicseventrecord.rb +30 -0
  44. data/code/superant.com.schedule/openhelpwindowrwdschedule.rb +43 -0
  45. data/code/superant.com.schedule/renameeventdata.rb +14 -0
  46. data/code/superant.com.schedule/renameicseventdata.rb +17 -0
  47. data/code/{superant.com.foldeditor/runrwdapplet.rb → superant.com.schedule/returntomain.rb} +3 -3
  48. data/code/superant.com.schedule/runrwdscheduleicsbackwindow.rb +10 -0
  49. data/code/superant.com.schedule/runrwdschedulemenu1.rb +34 -0
  50. data/code/superant.com.schedule/runrwdschedulesyncbackwindow.rb +10 -0
  51. data/code/{superant.com.foldeditor/rwdtinkerversion.rb → superant.com.schedule/rwdversion.rb} +2 -2
  52. data/code/{superant.com.foldeditor → superant.com.schedule}/saveconfigurationrecord.rb +5 -6
  53. data/code/superant.com.schedule/saveeventrecord.rb +25 -0
  54. data/code/superant.com.schedule/saveicseventrecord.rb +98 -0
  55. data/code/superant.com.schedule/syncrwdschedule.rb +30 -0
  56. data/code/superant.com.schedule/test_cases.rb +45 -0
  57. data/code/superant.com.schedule/uploadrwdschedulefiles.rb +30 -0
  58. data/code/superant.com.schedule/viewevent.rb +20 -0
  59. data/code/superant.com.schedule/viewicsevent.rb +20 -0
  60. data/code/superant.com.schedule/viewrwdschedulesconfiguration.rb +21 -0
  61. data/code/zz0applicationend/zz0end.rb +2 -1
  62. data/configuration/bigtinker.dist +5 -2
  63. data/configuration/rwdtinker.dist +3 -3
  64. data/configuration/rwdwschedule.dist +28 -0
  65. data/configuration/tinkerwin2variables.dist +1 -1
  66. data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/1appname.rwd +5 -0
  67. data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/20downloadftp.rwd +45 -0
  68. data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/67viewconfiguration.rwd +29 -0
  69. data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/70rwddiagnostics.rwd +16 -0
  70. data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/m01menubegin.rwd +18 -0
  71. data/gui/tinkerbackwindows/{superant.com.foldeditor/9end.rwd → superant.com.rwdschedulebackwindow/zvbackend.rwd} +6 -6
  72. data/gui/tinkerbackwindows/superant.com.rwdschedules/1appname.rwd +5 -0
  73. data/gui/tinkerbackwindows/superant.com.rwdschedules/gg0viewevent.rwd +27 -0
  74. data/gui/tinkerbackwindows/superant.com.rwdschedules/gl6editrecord.rwd +56 -0
  75. data/gui/tinkerbackwindows/superant.com.rwdschedules/gl8contactutilities.rwd +25 -0
  76. data/gui/tinkerbackwindows/superant.com.rwdschedules/hl9calendar.rwd +27 -0
  77. data/gui/tinkerbackwindows/superant.com.rwdschedules/m01menubegin.rwd +18 -0
  78. data/gui/tinkerbackwindows/{superant.com.slideshow/9end.rwd → superant.com.rwdschedules/zvbackend.rwd} +6 -6
  79. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/1appname.rwd +5 -0
  80. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/30viewevent.rwd +27 -0
  81. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/40editrecord.rwd +49 -0
  82. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/60eventicsutilities.rwd +25 -0
  83. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/m01menubegin.rwd +18 -0
  84. data/gui/tinkerbackwindows/superant.com.rwdschedulesback/zvbackend.rwd +6 -0
  85. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +1 -1
  86. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/80localechanger.rwd +17 -0
  87. data/init.rb +7 -1
  88. data/installed/rwdscheduledate2.inf +6 -0
  89. data/installed/rwdwschedule.inf +20 -0
  90. data/lang/en/rwdcalendar/en.po +32 -0
  91. data/lang/en/rwdcore/en.po +31 -0
  92. data/lang/es/rwdcalendar/es.po +10 -0
  93. data/lang/es/rwdcore/es.po +27 -15
  94. data/lang/fr/rwdcalendar/fr.po +11 -0
  95. data/lang/fr/rwdcore/fr.po +4 -1
  96. data/lang/hi/rwdcalendar/hi.po +11 -0
  97. data/lang/hi/rwdcore/hi.po +39 -36
  98. data/lang/ja/rwdcalendar/ja.po +11 -0
  99. data/lang/ja/rwdcore/ja.po +3 -0
  100. data/lang/nl/rwdcalendar/nl.po +12 -0
  101. data/lang/nl/rwdcore/nl.po +4 -1
  102. data/lib/cal.rb +158 -0
  103. data/lib/icalendar.rb +18 -0
  104. data/lib/icalendar/base.rb +17 -0
  105. data/lib/icalendar/calendar.rb +44 -0
  106. data/lib/icalendar/calendar_parser.rb +237 -0
  107. data/lib/icalendar/component.rb +91 -0
  108. data/lib/icalendar/component/alarm.rb +16 -0
  109. data/lib/icalendar/component/event.rb +25 -0
  110. data/lib/icalendar/component/freebusy.rb +12 -0
  111. data/lib/icalendar/component/journal.rb +25 -0
  112. data/lib/icalendar/component/timezone.rb +26 -0
  113. data/lib/icalendar/component/todo.rb +21 -0
  114. data/lib/icalendar/helpers.rb +103 -0
  115. data/lib/icalendar/parameter.rb +25 -0
  116. data/lib/zip/ioextras.rb +43 -2
  117. data/lib/zip/stdrubyext.rb +5 -5
  118. data/lib/zip/tempfile_bugfixed.rb +2 -2
  119. data/lib/zip/zip.rb +618 -149
  120. data/lib/zip/zipfilesystem.rb +59 -8
  121. data/lib/zip/ziprequire.rb +32 -3
  122. data/rwd_files/HowTo_BigTinker.txt +15 -3
  123. data/rwd_files/HowTo_Schedule.txt +265 -0
  124. data/rwd_files/HowTo_Tinker.txt +14 -0
  125. data/rwd_files/Tinkerhelptexthash.txt +5 -2
  126. data/rwd_files/rwdapplications.html +23 -1
  127. data/rwd_files/rwdschedulehelpfiles.txt +19 -0
  128. data/rwd_files/schedules/20050120T09.ics +9 -0
  129. data/rwd_files/schedules/200505may02a.sch +4 -0
  130. data/rwd_files/schedules/Enterprise.ics +411 -0
  131. data/rwd_files/schedules/US Holidays.ics +575 -0
  132. data/rwd_files/schedules/archive/sample.archive +1 -0
  133. data/rwd_files/schedules/testics05.ics +11 -0
  134. data/rwdconfig.dist +4 -2
  135. data/{bigtinker.rb → rwdtinker.rb} +0 -0
  136. data/tests/{makedist-rwdwfoldeditor.rb → makedist-rwdwhypernote.rb} +4 -8
  137. data/tests/makedist.rb +1 -1
  138. data/updates/temp.rb +1 -0
  139. data/zips/rwdwfoldeditor-0.07.zip +0 -0
  140. data/zips/rwdwhypernote-0.16.zip +0 -0
  141. data/zips/rwdwschedule-1.07.zip +0 -0
  142. data/zips/tinkerbellw-0.04.zip +0 -0
  143. metadata +102 -54
  144. data/code/superant.com.foldeditor/0uninstallapplet.rb +0 -17
  145. data/code/superant.com.foldeditor/changehypernotename.rb +0 -21
  146. data/code/superant.com.foldeditor/chooselinkfile.rb +0 -6
  147. data/code/superant.com.foldeditor/choosenotefile.rb +0 -6
  148. data/code/superant.com.foldeditor/clearnotescreen.rb +0 -7
  149. data/code/superant.com.foldeditor/createnewnotehtml.rb +0 -31
  150. data/code/superant.com.foldeditor/hyperlinkcreatelinkfile.rb +0 -19
  151. data/code/superant.com.foldeditor/launchfoldeditorurl.rb +0 -19
  152. data/code/superant.com.foldeditor/listfoldeditorfiles.rb +0 -7
  153. data/code/superant.com.foldeditor/loadconfigurationvariables.rb +0 -14
  154. data/code/superant.com.foldeditor/loadfolddocument.rb +0 -18
  155. data/code/superant.com.foldeditor/loadnextnote.rb +0 -32
  156. data/code/superant.com.foldeditor/loadprevnote.rb +0 -32
  157. data/code/superant.com.foldeditor/loadrwdfoldeditlinkfile.rb +0 -19
  158. data/code/superant.com.foldeditor/openhelpwindowrwdhyernote.rb +0 -30
  159. data/code/superant.com.foldeditor/rwddisplayfoldlinks.rb +0 -41
  160. data/code/superant.com.foldeditor/savefoldlinkfile.rb +0 -20
  161. data/code/superant.com.foldeditor/savehtmlhypernoterecord.rb +0 -20
  162. data/configuration/rwdwfoldeditor.dist +0 -16
  163. data/gui/tinkerbackwindows/superant.com.foldeditor/10appletbegin.rwd +0 -4
  164. data/gui/tinkerbackwindows/superant.com.foldeditor/10aviewnote.rwd +0 -36
  165. data/gui/tinkerbackwindows/superant.com.foldeditor/15htmlview.rwd +0 -43
  166. data/gui/tinkerbackwindows/superant.com.foldeditor/56viewfold.rwd +0 -43
  167. data/gui/tinkerbackwindows/superant.com.foldeditor/67viewconfiguration.rwd +0 -27
  168. data/gui/tinkerbackwindows/superant.com.foldeditor/81jumplinkcommands.rwd +0 -17
  169. data/gui/tinkerbackwindows/superant.com.slideshow/10appletbegin.rwd +0 -4
  170. data/gui/tinkerbackwindows/superant.com.slideshow/11viewnamedata.rwd +0 -19
  171. data/gui/tinkerbackwindows/superant.com.slideshow/13listnamerecordfiles.rwd +0 -21
  172. data/gui/tinkerbackwindows/superant.com.slideshow/16editrecord.rwd +0 -39
  173. data/gui/tinkerbackwindows/superant.com.slideshow/17viewvcardrecord.rwd +0 -32
  174. data/gui/tinkerbackwindows/superant.com.slideshow/18contactutilities.rwd +0 -34
  175. data/gui/tinkerbackwindows/superant.com.slideshow/81jumplinkcommands.rwd +0 -17
  176. data/installed/rwdwfoldeditor.inf +0 -11
  177. data/rwd_files/HowTo_FoldEditor.txt +0 -131
  178. data/rwd_files/default.fld +0 -9
  179. data/rwd_files/rubylinks.fld +0 -6
  180. data/rwd_files/rwdfoldeditorhelpfiles.txt +0 -42
  181. data/rwd_files/rwdhypernote-0.13.fld +0 -202
  182. data/zips/rwdwfoldeditor-0.06.zip +0 -0
  183. data/zips/rwdwschedule-1.05.zip +0 -0
  184. data/zips/tinkerbellw-0.03.zip +0 -0
@@ -0,0 +1,44 @@
1
+ module Icalendar
2
+ class Calendar < Component
3
+
4
+ attr_accessor :events, :todos, :journals, :freebusys, :timezones
5
+
6
+ def initialize()
7
+ super("VCALENDAR")
8
+ @properties = {}
9
+ @property_params = {}
10
+
11
+ @events = []
12
+ @todos = []
13
+ @journals = []
14
+ @freebusys = []
15
+ @timezones = []
16
+ end
17
+
18
+ def add(component)
19
+ if component.is_a? Event
20
+ @events << component
21
+ elsif component.is_a? Todo
22
+ @todos << component
23
+ elsif component.is_a? Journal
24
+ @journals << component
25
+ elsif component.is_a? Freebusy
26
+ @freebusys << component
27
+ elsif component.is_a? Timezone
28
+ @timezones << component
29
+ else
30
+ raise InvalidComponentClass
31
+ end
32
+ end
33
+
34
+ def to_s
35
+ print_string do |s|
36
+ @events.each { |event| s << event.to_s }
37
+ @todos.each { |todo| s << todo.to_s }
38
+ @journals.each { |journal| s << journal.to_s }
39
+ @freebusys.each { |freebusy| s << freebusy.to_s }
40
+ @timezones.each { |timezone| s << timezone.to_s }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,237 @@
1
+ module Icalendar
2
+ class CalendarParser < Icalendar::Base
3
+ # 1*(ALPHA / DIGIT / "=")
4
+ NAME = '[-a-z0-9]+'
5
+
6
+ # <"> <Any character except CTLs, DQUOTE> <">
7
+ QSTR = '"[^"]*"'
8
+
9
+ # *<Any character except CTLs, DQUOTE, ";", ":", ",">
10
+ PTEXT = '[^";:,]*'
11
+
12
+ # param-value = ptext / quoted-string
13
+ PVALUE = "#{PTEXT}|#{QSTR}"
14
+
15
+ # Contentline
16
+ LINE = "(#{NAME})([^:]*)\:(.*)"
17
+
18
+ # param = name "=" param-value *("," param-value)
19
+ # Note: v2.1 allows a type or encoding param-value to appear without the type=
20
+ # or the encoding=. This is hideous, but we try and support it, if there # is no "=", then $2 will be "", and we will treat it as a v2.1 param.
21
+ PARAM = ";(#{NAME})(=?)((?:#{PVALUE})(?:,#{PVALUE})*)"
22
+
23
+ # date = date-fullyear ["-"] date-month ["-"] date-mday
24
+ # date-fullyear = 4 DIGIT
25
+ # date-month = 2 DIGIT
26
+ # date-mday = 2 DIGIT
27
+ DATE = '(\d\d\d\d)-?(\d\d)-?(\d\d)'
28
+
29
+ # time = time-hour [":"] time-minute [":"] time-second [time-secfrac] [time-zone]
30
+ # time-hour = 2 DIGIT
31
+ # time-minute = 2 DIGIT
32
+ # time-second = 2 DIGIT
33
+ # time-secfrac = "," 1*DIGIT
34
+ # time-zone = "Z" / time-numzone
35
+ # time-numzome = sign time-hour [":"] time-minute
36
+ TIME = '(\d\d):?(\d\d):?(\d\d)(\.\d+)?(Z|[-+]\d\d:?\d\d)?'
37
+
38
+ def initialize(src)
39
+ @@logger.info("New Calendar Parser")
40
+
41
+ # Define the next line method different depending on whether
42
+ # this is a string or an IO object so we can be efficient about
43
+ # parsing large files...
44
+
45
+ # Just do the unfolding work in one shot if its a whole string
46
+ if src.respond_to?(:split)
47
+ unfolded = []
48
+
49
+ # Split into an array of lines, then unfold those into a new array
50
+ src.split(/\r?\n/).each do |line|
51
+
52
+ # If it's a continuation line, add it to the last.
53
+ # If it's an empty line, drop it from the input.
54
+ if( line =~ /^[ \t]/ )
55
+ unfolded << unfolded.pop + line[1, line.size-1]
56
+ elsif( line =~ /^$/ )
57
+ else
58
+ unfolded << line
59
+ end
60
+ end
61
+
62
+ @lines = unfolded
63
+ @index = 0
64
+
65
+ # Now that we are unfolded we can just iterate through the array.
66
+ # Dynamically define next line for a string.
67
+ def next_line
68
+ if @index == @lines.size
69
+ return nil
70
+ else
71
+ line = @lines[@index]
72
+ @index += 1
73
+ return line
74
+ end
75
+ end
76
+
77
+ # If its a file we need to read and unfold on the go to save from reading
78
+ # large amounts of data into memory.
79
+ elsif src.respond_to?(:gets)
80
+ @file = src
81
+ @prev_line = src.gets
82
+ if !@prev_line.nil?
83
+ @prev_line.chomp!
84
+ end
85
+
86
+ # Dynamically define next line for an IO object
87
+ def next_line
88
+ line = @prev_line
89
+
90
+ if line.nil?
91
+ return nil
92
+ end
93
+
94
+ # Loop through until we get to a non-continuation line...
95
+ loop do
96
+ nextLine = @file.gets
97
+ if !nextLine.nil?
98
+ nextLine.chomp!
99
+ end
100
+
101
+ # If it's a continuation line, add it to the last.
102
+ # If it's an empty line, drop it from the input.
103
+ if( nextLine =~ /^[ \t]/ )
104
+ line << nextLine[1, nextLine.size]
105
+ elsif( nextLine =~ /^$/ )
106
+ else
107
+ @prev_line = nextLine
108
+ break
109
+ end
110
+ end
111
+ line
112
+ end
113
+ else
114
+ raise ArgumentError, "CalendarParser.new cannot be called with a #{src.class} type!"
115
+ end
116
+ end
117
+
118
+ # Parse the calendar into an object representation
119
+ def parse
120
+ calendars = []
121
+
122
+ # Outer loop for Calendar objects
123
+ while (line = next_line)
124
+ fields = parse_line(line)
125
+
126
+ # Just iterate through until we find the beginning of a calendar object
127
+ if fields[:name] == "BEGIN" and fields[:value] == "VCALENDAR"
128
+ cal = parse_calendar
129
+ calendars << cal
130
+ end
131
+ end
132
+
133
+ calendars
134
+ end
135
+
136
+ # Parse a single VCALENDAR object
137
+ # -- This should consist of the PRODID, VERSION, option METHOD & CALSCALE,
138
+ # and then one or more calendar components: VEVENT, VTODO, VJOURNAL,
139
+ # VFREEBUSY, VTIMEZONE
140
+ def parse_calendar(component = Calendar.new)
141
+ while (line = next_line)
142
+ fields = parse_line(line)
143
+
144
+ name = fields[:name]
145
+
146
+ # Although properties are supposed to come before components, we should
147
+ # be able to handle them in any order...
148
+ if name == "END"
149
+ break
150
+ elsif name == "BEGIN" # New component
151
+ case(fields[:value])
152
+ when "VEVENT"
153
+ component.events << parse_calendar(Event.new)
154
+ when "VTODO"
155
+ component.todos << parse_calendar(Todo.new)
156
+ when "VJOURNAL"
157
+ component.journals << parse_calendar(Journal.new)
158
+ when "VFREEBUSY"
159
+ component.freebusys << parse_calendar(Freebusy.new)
160
+ when "VTIMEZONE"
161
+ component.timezones << parse_calendar(Timezone.new)
162
+ when "VALARM"
163
+ component.alarms << parse_calendar(Alarm.new)
164
+ end
165
+ else # If its not a component then it should be properties...
166
+
167
+ # Just set the properties ourselves so that the parser can still
168
+ # parse invalid files...
169
+ @@logger.debug("Setting #{name} => #{fields[:value]}")
170
+ component.properties[name] = fields[:value]
171
+ if not fields[:params].empty?
172
+ component.property_params[name] = fields[:params]
173
+ end
174
+
175
+ # This will generate the correctly formed calls to the dynamic method
176
+ # handler.
177
+ # component.send("#{name}=", fields[:value])
178
+ # component.send("#{name}_params=", fields[:params]) unless fields[:params].empty?
179
+ end
180
+ end
181
+
182
+ component
183
+ end
184
+
185
+ def parse_line(line)
186
+ unless line =~ %r{#{LINE}}i # Case insensitive match for a valid line
187
+ raise "Invalid line in calendar string!"
188
+ end
189
+
190
+ name = $1.upcase # The case insensitive part is upcased for easier comparison...
191
+ paramslist = $2
192
+ value = $3
193
+
194
+ params = {}
195
+
196
+ # Collect the params, if any.
197
+ if paramslist.size > 1
198
+
199
+ # v3.0 and v2.1 params
200
+ paramslist.scan( %r{#{PARAM}}i ) do
201
+
202
+ # param names are case-insensitive, and multi-valued
203
+ pname = $1
204
+ pvals = $3
205
+
206
+ # v2.1 pvals have no '=' sign, figure out what kind of param it
207
+ # is (either its a known encoding, or we treat it as a 'type'
208
+ # param).
209
+ if $2 == ""
210
+ pvals = $1
211
+ case $1
212
+ when /quoted-printable/i
213
+ pname = 'encoding'
214
+
215
+ when /base64/i
216
+ pname = 'encoding'
217
+
218
+ else
219
+ pname = 'type'
220
+ end
221
+ end
222
+
223
+ unless params.key? pname
224
+ params[pname] = []
225
+ end
226
+ pvals.scan( %r{(#{PVALUE})} ) do
227
+ if $1.size > 0
228
+ params[pname] << $1
229
+ end
230
+ end
231
+ end
232
+ end
233
+
234
+ {:name => name, :params => params, :value => value}
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,91 @@
1
+ module Icalendar
2
+ # The body of the iCalendar object consists of a sequence of calendar
3
+ # properties and one or more calendar components. The calendar
4
+ # properties are attributes that apply to the calendar as a whole. The
5
+ # calendar components are collections of properties that express a
6
+ # particular calendar semantic. For example, the calendar component can
7
+ # specify an event, a to-do, a journal entry, time zone information, or
8
+ # free/busy time information, or an alarm.
9
+ class Component < Icalendar::Base
10
+
11
+ attr_reader :name
12
+ attr_accessor :properties, :property_params
13
+
14
+ def initialize(name)
15
+ @name = name
16
+ @properties = {}
17
+ @property_params = {}
18
+
19
+ @@logger.info("New #{@name[1,@name.size].capitalize}...")
20
+ end
21
+
22
+ def print_string
23
+ s = ""
24
+
25
+ # Begin a new component
26
+ s << "BEGIN:#{@name.upcase}\r\n"
27
+
28
+ # Then print the properties, possible parameters and potentially
29
+ # multiple parameter values for each parameter.
30
+ @properties.each do |key,value|
31
+ # Property name
32
+ s << "#{key.upcase}"
33
+
34
+ # Possible parameters
35
+ if @property_params.has_key?(key)
36
+ params = @property_params[key]
37
+ params.each do |key,val|
38
+ s << ";#{key}"
39
+ unless val.respond_to?(:to_ary)
40
+ val = [ val ]
41
+ end
42
+
43
+ # Possible parameter values
44
+ unless val.empty?
45
+ s << "="
46
+ sep = "" # First entry comes after = sign, but then we need commas
47
+ val.each do |pval|
48
+ s << sep << pval
49
+ sep = ","
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # Property value
56
+ s << ":#{value}\r\n"
57
+ end
58
+
59
+ # Any custom body of the derived component
60
+ yield(s)
61
+
62
+ # End of this component
63
+ s << "END:#{@name.upcase}\r\n"
64
+ end
65
+
66
+ # Dynamically execute getters and setters for properties and
67
+ # property parameters. This lets us handle all the general text properties
68
+ # as well as custom app related properties in a natural way, but we don't
69
+ # have to write a million getters and setters for every possible thing we
70
+ # want to support.
71
+ def method_missing(method_id, *args)
72
+ method_name = method_id.id2name.upcase
73
+
74
+ if method_name =~ /\w+_PARAMS/ # Its a parameter request
75
+ hash = @property_params
76
+ val = args
77
+ else # Or its a property request
78
+ hash = @properties
79
+ val = args.first unless args.empty?
80
+ end
81
+
82
+ if method_name =~ /(.*)(=)/ # Its a setter
83
+ hash[$1] = val
84
+ @@logger.debug("Setting #{$1} => #{val}")
85
+ else # Or its a getter
86
+ @@logger.debug("Getting #{method_name} => #{hash[method_name]}")
87
+ return hash[method_name]
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,16 @@
1
+ module Icalendar
2
+ # An Alarm calendar component is a grouping of component
3
+ # properties that is a reminder or alarm for an event or a
4
+ # to-do. For example, it may be used to define a reminder for a
5
+ # pending Event or an overdue Todo.
6
+ class Alarm < Component
7
+ def initialize()
8
+ super("VALARM")
9
+
10
+ end
11
+
12
+ def to_s
13
+ print_string {}
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module Icalendar
2
+ # A Event calendar component is a grouping of component
3
+ # properties, and possibly including Alarm calendar components, that
4
+ # represents a scheduled amount of time on a calendar. For example, it
5
+ # can be an activity; such as a one-hour long, department meeting from
6
+ # 8:00 AM to 9:00 AM, tomorrow. Generally, an event will take up time
7
+ # on an individual calendar.
8
+ class Event < Component
9
+ include Dtstart
10
+
11
+ attr_accessor :alarms
12
+
13
+ def initialize()
14
+ super("VEVENT")
15
+
16
+ @alarms = []
17
+ end
18
+
19
+ def to_s
20
+ print_string do |s|
21
+ @alarms.each { |alarm| s << alarm.to_s }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module Icalendar
2
+ # A Freebusy calendar component is a grouping of
3
+ # component properties that represents either a request for, a reply to
4
+ # a request for free or busy time information or a published set of
5
+ # busy time information.
6
+ class Freebusy < Component
7
+
8
+ def initialize()
9
+ super("VFREEBUSY")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Icalendar
2
+ # A Journal calendar component is a grouping of
3
+ # component properties that represent one or more descriptive text
4
+ # notes associated with a particular calendar date. The "DTSTART"
5
+ # property is used to specify the calendar date that the journal entry
6
+ # is associated with. Generally, it will have a DATE value data type,
7
+ # but it can also be used to specify a DATE-TIME value data type.
8
+ # Examples of a journal entry include a daily record of a legislative
9
+ # body or a journal entry of individual telephone contacts for the day
10
+ # or an ordered list of accomplishments for the day. The Journal
11
+ # calendar component can also be used to associate a document with a
12
+ # calendar date.
13
+ class Journal < Component
14
+
15
+ def initialize()
16
+ super("VJOURNAL")
17
+ end
18
+
19
+ def to_s
20
+ print_string { }
21
+ end
22
+
23
+ end
24
+ end
25
+