rwdgutenberg 0.12 → 0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/code/01rwdcore/01rwdcore.rb +6 -6
  2. data/code/01rwdcore/02helptexthashbegin.rb +14 -2
  3. data/code/01rwdcore/03helptexthash.rb +18 -20
  4. data/code/01rwdcore/jumplinkcommand.rb +14 -4
  5. data/code/01rwdcore/openhelpwindow.rb +7 -0
  6. data/code/01rwdcore/runhelpabout.rb +6 -1
  7. data/code/01rwdcore/runtab.rb +15 -0
  8. data/code/01rwdcore/selectiontab.rb +2 -0
  9. data/code/01rwdcore/setuphelpaboutoptions.rb +2 -0
  10. data/code/01rwdcore/setuptinkerdocuments.rb +1 -0
  11. data/code/01rwdcore/test_cases.rb +100 -51
  12. data/code/01rwdcore/test_harness.rb +8 -1
  13. data/code/01rwdcore/uploadreturns.rb +3 -0
  14. data/code/dd0viewphoto/dd0viewphoto.rb +2 -0
  15. data/code/superant.com.gutenberg/0uninstallapplet.rb +2 -0
  16. data/code/superant.com.gutenberg/changegutenbergname.rb +0 -0
  17. data/code/superant.com.gutenberg/clearbookscreendisplay.rb +0 -0
  18. data/code/superant.com.gutenberg/cleargutenbergfiles.rb +0 -0
  19. data/code/superant.com.gutenberg/cleargutrecordfiles.rb +0 -0
  20. data/code/superant.com.gutenberg/copyfilename.rb +0 -0
  21. data/code/superant.com.gutenberg/createnewnote.rb +1 -1
  22. data/code/superant.com.gutenberg/deletegutenbergrecord.rb +0 -0
  23. data/code/superant.com.gutenberg/gutenbergcreatefile.rb +0 -0
  24. data/code/superant.com.gutenberg/helptexthashload.rb +0 -0
  25. data/code/superant.com.gutenberg/listnamerecord.rb +0 -0
  26. data/code/superant.com.gutenberg/listtextfilesgutenberg.rb +0 -0
  27. data/code/superant.com.gutenberg/loadbookrecord.rb +0 -0
  28. data/code/superant.com.gutenberg/loadconfigurationrecord.rb +0 -0
  29. data/code/superant.com.gutenberg/loadconfigurationvariables.rb +0 -0
  30. data/code/superant.com.gutenberg/openhelpwindow.rb +41 -0
  31. data/code/superant.com.gutenberg/runbackwindow.rb +0 -0
  32. data/code/superant.com.gutenberg/rungutenbergwindow.rb +0 -0
  33. data/code/superant.com.gutenberg/rwdgutenbergbackward.rb +0 -0
  34. data/code/superant.com.gutenberg/rwdtinkerversion.rb +0 -0
  35. data/code/superant.com.gutenberg/saveconfigurationrecord.rb +0 -0
  36. data/code/superant.com.gutenberg/savegutenbergrecord.rb +0 -0
  37. data/code/superant.com.library/marcsearch.rb +30 -0
  38. data/code/superant.com.rwdtinkerbackwindow/changelocale.rb +84 -0
  39. data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +30 -102
  40. data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +2 -0
  41. data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +2 -0
  42. data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +3 -1
  43. data/code/superant.com.rwdtinkerbackwindow/listzips.rb +4 -0
  44. data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +3 -1
  45. data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +3 -1
  46. data/code/superant.com.rwdtinkerbackwindow/showlocaleoptions.rb +9 -0
  47. data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +1 -0
  48. data/code/superant.com.rwdtinkerbackwindow/viewlogfile.rb +8 -5
  49. data/code/zz0applicationend/zz0end.rb +2 -1
  50. data/configuration/rwdtinker.dist +3 -2
  51. data/configuration/rwdwgutenberg.dist +3 -3
  52. data/configuration/tinkerwin2variables.dist +4 -8
  53. data/gui/tinkerbackwindows/superant.com.backgutenberg/30booklistutilities.rwd +1 -1
  54. data/gui/tinkerbackwindows/superant.com.backgutenberg/40marctab.rwd +26 -0
  55. data/gui/tinkerbackwindows/superant.com.backgutenberg/67viewconfiguration.rwd +1 -1
  56. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +1 -1
  57. data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/80localechanger.rwd +17 -0
  58. data/init.rb +53 -156
  59. data/installed/rwdwgutenberg.inf +0 -1
  60. data/lang/en/rwdcore/en.po +197 -0
  61. data/lang/es/rwdcore/es.po +184 -0
  62. data/lang/fr/rwdcore/fr.po +169 -0
  63. data/lang/hi/rwdcore/hi.po +173 -0
  64. data/lang/ja/rwdcore/ja.po +171 -0
  65. data/lang/nl/rwdcore/nl.po +169 -0
  66. data/lib/marc.rb +38 -0
  67. data/lib/marc/constants.rb +14 -0
  68. data/lib/marc/controlfield.rb +47 -0
  69. data/lib/marc/datafield.rb +163 -0
  70. data/lib/marc/dublincore.rb +79 -0
  71. data/lib/marc/exception.rb +9 -0
  72. data/lib/marc/reader.rb +186 -0
  73. data/lib/marc/record.rb +147 -0
  74. data/lib/marc/subfield.rb +31 -0
  75. data/lib/marc/writer.rb +87 -0
  76. data/lib/marc/xmlreader.rb +103 -0
  77. data/lib/marc/xmlwriter.rb +155 -0
  78. data/lib/rwdtinker/rwdcodedir.rb +56 -0
  79. data/lib/rwdtinker/rwdguidir.rb +57 -0
  80. data/lib/rwdtinker/rwdlangdir.rb +60 -0
  81. data/lib/rwdtinker/rwdtinkertools.rb +2 -1
  82. data/lib/zip/ioextras.rb +43 -2
  83. data/lib/zip/stdrubyext.rb +5 -5
  84. data/lib/zip/tempfile_bugfixed.rb +2 -2
  85. data/lib/zip/zip.rb +618 -149
  86. data/lib/zip/zipfilesystem.rb +59 -8
  87. data/lib/zip/ziprequire.rb +32 -3
  88. data/lib/zmarc.rb +140 -0
  89. data/lib/zoom.so +0 -0
  90. data/rwd_files/HowTo_Gutenberg.txt +8 -1
  91. data/rwd_files/HowTo_Tinker.txt +29 -6
  92. data/rwd_files/Tinkerhelptexthash.txt +84 -0
  93. data/rwd_files/log/rwdtinker.log +0 -2080
  94. data/rwd_files/rwdapplications.html +23 -1
  95. data/rwd_files/rwdgutenberghelpfiles.txt +11 -4
  96. data/rwdconfig.dist +4 -2
  97. data/tests/makedist-rwdwgutenberg.rb +1 -1
  98. data/tests/makedist.rb +1 -1
  99. data/zips/rwdwfoldeditor-0.07.zip +0 -0
  100. data/zips/{rwdwgutenberg-0.12.zip → rwdwgutenberg-0.13.zip} +0 -0
  101. data/zips/rwdwhypernote-0.16.zip +0 -0
  102. data/zips/rwdwmovies-0.98.zip +0 -0
  103. data/zips/tinkerbellw-0.04.zip +0 -0
  104. data/zips/{wrubyslippers-1.07.zip → wrubyslippers-1.08.zip} +0 -0
  105. metadata +39 -14
  106. data/code/01rwdcore/04helptextend.rb +0 -6
  107. data/code/superant.com.gutenberg/openhelpwindowgutenberg.rb +0 -35
  108. data/code/superant.com.rwdtinkerbackwindow/helptexthashtinkerwin2.rb +0 -61
  109. data/lang/en/rwdcore/languagefile.rb +0 -59
  110. data/lang/es/rwdcore/languagefile-es.rb +0 -63
  111. data/lang/fr/rwdcore/languagefile.rb +0 -65
  112. data/lang/jp/rwdcore/languagefile.rb +0 -73
  113. data/lang/nl/rwdcore/languagefile.rb +0 -76
  114. data/rwdgutenberg.rb +0 -1
  115. data/zips/rwdwfoldeditor-0.05.zip +0 -0
@@ -0,0 +1,79 @@
1
+ module MARC
2
+
3
+ # A class for mapping MARC records to Dublin Core
4
+
5
+ class DublinCore
6
+
7
+ def self.map(record)
8
+ dc_hash = Hash.new
9
+ dc_hash['title'] = get_field_value(record['245']['a'])
10
+
11
+ # Creator
12
+ [100, 110, 111, 700, 710, 711, 720].each do |field|
13
+ dc_hash['creator'] ||= []
14
+ dc_hash['creator'] << get_field_value(record[field.to_s])
15
+ end
16
+
17
+ # Subject
18
+ [600, 610, 611, 630, 650, 653].each do |field|
19
+ dc_hash['subject'] ||= []
20
+ dc_hash['subject'] << get_field_value(record[field.to_s])
21
+ end
22
+
23
+ # Description
24
+ [500..599].each do |field|
25
+ next if [506, 530, 540, 546].include?(field)
26
+ dc_hash['description'] ||= []
27
+ dc_hash['description'] << get_field_value(record[field.to_s])
28
+ end
29
+
30
+ dc_hash['publisher'] = get_field_value(record['260']['a']['b']) rescue nil
31
+ dc_hash['date'] = get_field_value(record['260']['c']) rescue nil
32
+ dc_hash['type'] = get_field_value(record['655'])
33
+ dc_hash['format'] = get_field_value(record['856']['q']) rescue nil
34
+ dc_hash['identifier'] = get_field_value(record['856']['u']) rescue nil
35
+ dc_hash['source'] = get_field_value(record['786']['o']['t']) rescue nil
36
+ dc_hash['language'] = get_field_value(record['546'])
37
+
38
+ dc_hash['relation'] = []
39
+ dc_hash['relation'] << get_field_value(record['530'])
40
+ [760..787].each do |field|
41
+ dc_hash['relation'] << get_field_value(record[field.to_s]['o']['t']) rescue nil
42
+ end
43
+
44
+ [651, 752].each do |field|
45
+ dc_hash['coverage'] ||= []
46
+ dc_hash['coverage'] << get_field_value(record[field.to_s])
47
+ end
48
+
49
+ [506, 540].each do |field|
50
+ dc_hash['rights'] ||= []
51
+ dc_hash['rights'] << get_field_value(record[field.to_s])
52
+ end
53
+
54
+ dc_hash.keys.each do |key|
55
+ dc_hash[key].flatten! if dc_hash[key].respond_to?(:flatten!)
56
+ dc_hash[key].compact! if dc_hash[key].respond_to?(:compact!)
57
+ end
58
+
59
+ dc_hash
60
+ end
61
+
62
+ def self.get_field_value(field)
63
+ return if field.nil?
64
+
65
+ if !field.kind_of?(String) && field.respond_to?(:each)
66
+ values = []
67
+ field.each do |element|
68
+ values << get_field_value(element)
69
+ end
70
+ values
71
+ else
72
+ return field if field.kind_of?(String)
73
+ return field.value if field.respond_to?(:value)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+
@@ -0,0 +1,9 @@
1
+ module MARC
2
+
3
+ # basic exception class for exceptions that
4
+ # can occur during MARC processing.
5
+
6
+ class Exception < RuntimeError
7
+ end
8
+
9
+ end
@@ -0,0 +1,186 @@
1
+ module MARC
2
+
3
+ class Reader
4
+ include Enumerable
5
+
6
+ # The constructor which you may pass either a path
7
+ #
8
+ # reader = MARC::Reader.new('marc.dat')
9
+ #
10
+ # or, if it's more convenient a File object:
11
+ #
12
+ # fh = File.new('marc.dat')
13
+ # reader = MARC::Reader.new(fh)
14
+ #
15
+ # or really any object that responds to read(n)
16
+ #
17
+ # # marc is a string with a bunch of records in it
18
+ # reader = MARC::Reader.new(StringIO.new(reader))
19
+
20
+ def initialize(file)
21
+ if file.class == String:
22
+ @handle = File.new(file)
23
+ elsif file.respond_to?("read", 5)
24
+ @handle = file
25
+ else
26
+ throw "must pass in path or file"
27
+ end
28
+ end
29
+
30
+ # to support iteration:
31
+ # for record in reader
32
+ # print record
33
+ # end
34
+ #
35
+ # and even searching:
36
+ # record.find { |f| f['245'] =~ /Huckleberry/ }
37
+
38
+ def each
39
+ # while there is data left in the file
40
+ while rec_length_s = @handle.read(5)
41
+ # make sure the record length looks like an integer
42
+ rec_length_i = rec_length_s.to_i
43
+ if rec_length_i == 0:
44
+ raise MARC::Exception.new("invalid record length: #{rec_length_s}")
45
+ end
46
+
47
+ # get the raw MARC21 for a record back from the file
48
+ # using the record length
49
+ raw = rec_length_s + @handle.read(rec_length_i-5)
50
+
51
+
52
+ # create a record from the data and return it
53
+ #record = MARC::Record.new_from_marc(raw)
54
+ record = MARC::Reader.decode(raw)
55
+ yield record
56
+ end
57
+ end
58
+
59
+
60
+ # A static method for turning raw MARC data in transission
61
+ # format into a MARC::Record object.
62
+
63
+ def self.decode(marc, params={})
64
+ record = Record.new()
65
+ record.leader = marc[0..LEADER_LENGTH-1]
66
+
67
+ # where the field data starts
68
+ base_address = record.leader[12..16].to_i
69
+
70
+ # get the byte offsets from the record directory
71
+ directory = marc[LEADER_LENGTH..base_address-1]
72
+
73
+ throw "invalid directory in record" if directory == nil
74
+
75
+ # the number of fields in the record corresponds to
76
+ # how many directory entries there are
77
+ num_fields = directory.length / DIRECTORY_ENTRY_LENGTH
78
+
79
+ # when operating in forgiving mode we just split on end of
80
+ # field instead of using calculated byte offsets from the
81
+ # directory
82
+ all_fields = marc[base_address..-1].split(END_OF_FIELD)
83
+
84
+ 0.upto(num_fields-1) do |field_num|
85
+
86
+ # pull the directory entry for a field out
87
+ entry_start = field_num * DIRECTORY_ENTRY_LENGTH
88
+ entry_end = entry_start + DIRECTORY_ENTRY_LENGTH
89
+ entry = directory[entry_start..entry_end]
90
+
91
+ # extract the tag
92
+ tag = entry[0..2]
93
+
94
+ # get the actual field data
95
+ # if we were told to be forgiving we just use the
96
+ # next available chuck of field data that we
97
+ # split apart based on the END_OF_FIELD
98
+ field_data = ''
99
+ if params[:forgiving]
100
+ field_data = all_fields.shift()
101
+
102
+ # otherwise we actually use the byte offsets in
103
+ # directory to figure out what field data to extract
104
+ else
105
+ length = entry[3..6].to_i
106
+ offset = entry[7..11].to_i
107
+ field_start = base_address + offset
108
+ field_end = field_start + length - 1
109
+ field_data = marc[field_start..field_end]
110
+ end
111
+
112
+ # remove end of field
113
+ field_data.delete!(END_OF_FIELD)
114
+
115
+ # add a control field or data field
116
+ if tag < '010'
117
+ record.append(MARC::ControlField.new(tag,field_data))
118
+ else
119
+ field = MARC::DataField.new(tag)
120
+
121
+ # get all subfields
122
+ subfields = field_data.split(SUBFIELD_INDICATOR)
123
+
124
+ # must have at least 2 elements (indicators, and 1 subfield)
125
+ # TODO some sort of logging?
126
+ next if subfields.length() < 2
127
+
128
+ # get indicators
129
+ indicators = subfields.shift()
130
+ field.indicator1 = indicators[0,1]
131
+ field.indicator2 = indicators[1,1]
132
+
133
+ # add each subfield to the field
134
+ subfields.each() do |data|
135
+ subfield = MARC::Subfield.new(data[0,1],data[1..-1])
136
+ field.append(subfield)
137
+ end
138
+
139
+ # add the field to the record
140
+ record.append(field)
141
+ end
142
+ end
143
+
144
+ return record
145
+ end
146
+ end
147
+
148
+
149
+ # Like Reader ForgivingReader lets you read in a batch of MARC21 records
150
+ # but it does not use record lengths and field byte offets found in the
151
+ # leader and directory. It is not unusual to run across MARC records
152
+ # which have had their offsets calcualted wrong. In situations like this
153
+ # the vanilla Reader may fail, and you can try to use ForgivingReader.
154
+
155
+ # The one downside to this is that ForgivingReader will assume that the
156
+ # order of the fields in the directory is the same as the order of fields
157
+ # in the field data. Hopefully this will be the case, but it is not
158
+ # 100% guranteed which is why the normal behavior of Reader is encouraged.
159
+
160
+ class ForgivingReader
161
+ include Enumerable
162
+
163
+ def initialize(file)
164
+ if file.class == String
165
+ @handle = File.new(file)
166
+ elsif file.respond_to?("read", 5)
167
+ @handle = file
168
+ else
169
+ throw "must pass in path or File object"
170
+ end
171
+ end
172
+
173
+
174
+ def each
175
+ @handle.each_line(END_OF_RECORD) do |raw|
176
+ begin
177
+ record = MARC::Reader.decode(raw, :forgiving => true)
178
+ yield record
179
+ rescue StandardError => e
180
+ # caught exception just keep barrelling along
181
+ # TODO add logging
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,147 @@
1
+ module MARC
2
+
3
+ # A class that represents an individual MARC record. Every record
4
+ # is made up of a collection of MARC::DataField objects.
5
+ #
6
+ # MARC::Record mixes in Enumerable to enable access to constituent
7
+ # DataFields. For example, to return a list of all subject DataFields:
8
+ #
9
+ # record.find_all {|field| field.tag =~ /^6../}
10
+ #
11
+ # The accessor 'fields' is also an Array of MARC::DataField objects which
12
+ # the client can access or modifyi if neccesary.
13
+ #
14
+ # record.fields.delete(field)
15
+ #
16
+ # Other accessor attribute: 'leader' for record leader as String
17
+
18
+ class Record
19
+ include Enumerable
20
+
21
+ # the record fields
22
+ attr_accessor :fields
23
+
24
+ # the record leader
25
+ attr_accessor :leader
26
+
27
+ def initialize
28
+ @fields = []
29
+ # leader is 24 bytes
30
+ @leader = ' ' * 24
31
+ # leader defaults:
32
+ # http://www.loc.gov/marc/bibliographic/ecbdldrd.html
33
+ @leader[10..11] = '22'
34
+ @leader[20..23] = '4500'
35
+ end
36
+
37
+ # add a field to the record
38
+ # record.append(MARC::DataField.new( '100', '2', '0', ['a', 'Fred']))
39
+
40
+ def append(field)
41
+ @fields.push(field)
42
+ end
43
+
44
+ # alias to append
45
+
46
+ def <<(field)
47
+ append(field)
48
+ end
49
+
50
+ # each() is here to support iterating and searching since MARC::Record
51
+ # mixes in Enumberable
52
+ #
53
+ # iterating through the fields in a record:
54
+ # record.each { |f| print f }
55
+ #
56
+ # getting the 245
57
+ # title = record.find {|f| f.tag == '245'}
58
+ #
59
+ # getting all subjects
60
+ # subjects = record.find_all {|f| ('600'..'699') === f.tag}
61
+
62
+ def each
63
+ for field in @fields
64
+ yield field
65
+ end
66
+ end
67
+
68
+ # You can lookup fields using this shorthand:
69
+ # title = record['245']
70
+
71
+ def [](tag)
72
+ return self.find {|f| f.tag == tag}
73
+ end
74
+
75
+ # Factory method for creating a MARC::Record from MARC21 in
76
+ # transmission format.
77
+ #
78
+ # record = MARC::Record.new_from_marc(marc21)
79
+ #
80
+ # in cases where you might be working with somewhat flawed
81
+ # MARC data you may want to use the :forgiving parameter which
82
+ # will bypass using field byte offsets and simply look for the
83
+ # end of field byte to figure out the end of fields.
84
+ #
85
+ # record = MARC::Record.new_from_marc(marc21, :forgiving => true)
86
+
87
+ def self.new_from_marc(raw, params={})
88
+ return MARC::Reader.decode(raw, params)
89
+ end
90
+
91
+
92
+ # Returns a record in MARC21 transmission format (ANSI Z39.2).
93
+ # Really this is just a wrapper around MARC::MARC21::encode
94
+ #
95
+ # marc = record.to_marc()
96
+
97
+ def to_marc
98
+ return MARC::Writer.encode(self)
99
+ end
100
+
101
+ # Handy method for returning the MARCXML serialization for a
102
+ # MARC::Record object. You'll get back a REXML::Document object.
103
+ # Really this is just a wrapper around MARC::XMLWriter::encode
104
+ #
105
+ # xml_doc = record.to_xml()
106
+
107
+ def to_xml
108
+ return MARC::XMLWriter.encode(self, :include_namespace => true)
109
+ end
110
+
111
+ # Handy method for returning a hash mapping this records values
112
+ # to the Dublin Core.
113
+ #
114
+ # dc = record.to_dublin_core()
115
+ # print dc['title']
116
+
117
+ def to_dublin_core
118
+ return MARC::DublinCore.map(self)
119
+ end
120
+
121
+ # Returns a string version of the record, suitable for printing
122
+
123
+ def to_s
124
+ str = "LEADER #{leader}\n"
125
+ for field in fields:
126
+ str += field.to_s() + "\n"
127
+ end
128
+ return str
129
+ end
130
+
131
+
132
+ # For testing if two records can be considered equal.
133
+
134
+ def ==(other)
135
+ return self.to_s == other.to_s
136
+ end
137
+
138
+
139
+ # Handy for using a record in a regex:
140
+ # if record =~ /Gravity's Rainbow/ then print "Slothrop" end
141
+
142
+ def =~(regex)
143
+ return self.to_s =~ regex
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,31 @@
1
+ module MARC
2
+
3
+ # A class that represents an individual subfield within a DataField.
4
+ # Accessor attributes include: code (letter subfield code) and value
5
+ # (the content of the subfield). Both can be empty string, but should
6
+ # not be set to nil.
7
+
8
+ class Subfield
9
+ attr_accessor :code, :value
10
+
11
+ def initialize(code='' ,value='')
12
+ # can't allow code of value to be nil
13
+ # or else it'll screw us up later on
14
+ @code = code == nil ? '' : code
15
+ @value = value == nil ? '' : value
16
+ end
17
+
18
+ def ==(other)
19
+ if @code != other.code
20
+ return false
21
+ elsif @value != other.value
22
+ return false
23
+ end
24
+ return true
25
+ end
26
+
27
+ def to_s
28
+ return "$#{code} #{value} "
29
+ end
30
+ end
31
+ end