Codebase list pspp / debian/0.7.9+git20120620-1
Import Debian changes 0.7.9+git20120620-1 pspp (0.7.9+git20120620-1) unstable; urgency=low * New upstream snapshot, fixes non-ASCII import issue (Closes: #676371). bojo42 authored 11 years ago Andreas Tille committed 5 years ago
202 changed file(s) with 35272 addition(s) and 10606 deletion(s). Raw diff Collapse all Expand all
3333
3434 - CROSSTABS has been re-implemented to fix numerous bugs.
3535
36 - EXAMINE: /MISSING=LISTWISE is now the default.
37
3638 - DO REPEAT command has been reimplemented. Now, when DO REPEAT
3739 contains an INCLUDE or INSERT command, substitutions are not
3840 applied to the included file.
39
41
4042 - HOST has been updated to use more modern syntax.
4143
42 - GET, INCLUDE, and INSERT have a new ENCODING subcommand.
44 - Most commands that work with data files now support a new
45 ENCODING subcommand.
4346
4447 - MISSING VALUES can now assign missing values to long string
4548 variables.
3333 Gnulib does not maintain a stable API or ABI, so it is possible that
3434 PSPP will not work with older or newer versions of Gnulib.
3535
36 commit 68dd9ac979d5c3afd72f3d2fb0d6dcda32b3c384
37 Author: Bruno Haible <bruno@clisp.org>
38 Date: Tue Aug 23 08:40:27 2011 +0200
36 commit ebc6ce40ac3f349d69766e3b94db034a0245f3d7
37 Author: John Darrington <john@darrington.wattle.id.au>
38 Date: Wed Jun 20 23:30:48 2012 +0200
3939
40 tmpdir: Use a good default directory on native Windows.
40 tmpfile, clean-temp: Fix invocation of GetVersionEx.
4141
4242
4343 To clone Gnulib into a directory named "gnulib" using Git, and then
7272 AM_CONDITIONAL([HAVE_GUI],
7373 [test "$with_cairo" != no && test "$with_gui" != "no"])
7474 if test "$with_cairo" != no && test "$with_gui" != "no"; then
75 PKG_CHECK_MODULES([GTHREAD], [gthread-2.0], [],
76 [PSPP_REQUIRED_PREREQ([gthread 2.0 (or use --without-gui)])])
77
7578 PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.16], [],
7679 [PSPP_REQUIRED_PREREQ([gtk+ 2.0 version 2.16 or later (or use --without-gui)])])
7780
0 pspp (0.7.9+git20120620-1) unstable; urgency=low
1
2 * New upstream snapshot, fixes non-ASCII import issue (Closes: #676371).
3
4 -- bojo42 <bojo42@gmail.com> Sun, 24 Jun 2012 23:57:16 +0200
5
06 pspp (0.7.9+git20120319-1) unstable; urgency=low
17
28 * New upstream snapshot, fix testsuite errors on Ubuntu precise i386.
00 @node Bugs
11 @chapter Bugs
22
3 PSPP does have bugs. We do our best to fix them, but our limited
4 resources mean that some may remain for a long time. Our best
5 alternative is to make you aware of PSPP's known bugs. To see a list,
6 visit PSPP's project webpage at
7 @uref{https://savannah.gnu.org/projects/pspp}. You can also submit
8 your own bug report there: click on ``Bugs,'' then on ``Submit a
9 Bug,'' and fill out the form. Alternatively, PSPP bug reports may be
10 sent by email to @email{bug-gnu-pspp@@gnu.org}.
3 @cindex bugs
4
5 Occasionally users encounter problems with @pspp{}.
6 When such problems arise we do our best to fix them, but our limited
7 resources mean that certain issues may remain for some time.
8 If you discover a bug, please first:
9 @itemize @bullet
10 @item Try an up to date version of @pspp{}; it may be that the problem
11 has recently been fixed.
12 @item If the problem persists in the up to date version; check to see
13 if it has already been reported.
14 @item If the problem exists in a recent version and it has not already
15 been reported, please file a report.
16 @end itemize
17
18 To see a list of reported bugs, visit @pspp{}'s project webpage at
19 @uref{http://savannah.gnu.org/bugs/?group=pspp}
20 Alternatively, bug reports may be sent by email
21 to @email{bug-gnu-pspp@@gnu.org}.
22
23 In your bug report please include:
24 @itemize @bullet
25 @item The version of @pspp{} which you are using.
26 @item The operating system and type of computer on which it is running.
27 @item A sample of the syntax which causes the problem or, if it is a user
28 interface problem, the sequence of steps required to reproduce it.
29 @item A description of what you think is wrong: What happened that you
30 didn't expect, and what did you expect to happen?
31 @end itemize
1132
1233 For known bugs in individual language features, see the documentation
1334 for that feature.
3939
4040 @display
4141 Per input file:
42 /FILE=@{*,'file-name'@}
43 [/RENAME=(src_names=target_names)@dots{}]
44 [/IN=var_name]
42 /FILE=@{*,'@var{file_name}'@}
43 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
44 [/IN=@var{var_name}]
4545 [/SORT]
4646
4747 Once per command:
48 /BY var_list[(@{D|A@})] [var_list[(@{D|A@}]]@dots{}
49 [/DROP=var_list]
50 [/KEEP=var_list]
51 [/FIRST=var_name]
52 [/LAST=var_name]
48 /BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@}]]@dots{}
49 [/DROP=@var{var_list}]
50 [/KEEP=@var{var_list}]
51 [/FIRST=@var{var_name}]
52 [/LAST=@var{var_name}]
5353 [/MAP]
5454 @end display
5555
6565 be read as input. For each input file, specify FILE with a system
6666 file or portable file's name as a string, a dataset (@pxref{Datasets})
6767 or file handle name, (@pxref{File Handles}), or an asterisk (@samp{*})
68 to use the active dataset as input. Use of portable files on FILE is a
69 PSPP extension.
70
71 At least two FILE subcommands must be specified. If the active dataset
68 to use the active dataset as input. Use of portable files on @subcmd{FILE} is a
69 @pspp{} extension.
70
71 At least two @subcmd{FILE} subcommands must be specified. If the active dataset
7272 is used as an input source, then @cmd{TEMPORARY} must not be in
7373 effect.
7474
75 Each FILE subcommand may be followed by any number of RENAME
75 Each @subcmd{FILE} subcommand may be followed by any number of @subcmd{RENAME}
7676 subcommands that specify a parenthesized group or groups of variable
7777 names as they appear in the input file, followed by those variables'
78 new names, separated by an equals sign (@samp{=}),
79 e.g. @samp{/RENAME=(OLD1=NEW1)(OLD2=NEW2)}. To rename a single
80 variable, the parentheses may be omitted: @samp{/RENAME=OLD=NEW}.
78 new names, separated by an equals sign (@subcmd{=}),
79 e.g. @subcmd{/RENAME=(OLD1=NEW1)(OLD2=NEW2)}. To rename a single
80 variable, the parentheses may be omitted: @subcmd{/RENAME=@var{old}=@var{new}}.
8181 Within a parenthesized group, variables are renamed simultaneously, so
82 that @samp{/RENAME=(A B=B A)} exchanges the names of variables A and
83 B. Otherwise, renaming occurs in left-to-right order.
84
85 Each FILE subcommand may optionally be followed by a single IN
82 that @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})} exchanges the
83 names of variables @var{A} and @var{B}.
84 Otherwise, renaming occurs in left-to-right order.
85
86 Each @subcmd{FILE} subcommand may optionally be followed by a single @subcmd{IN}
8687 subcommand, which creates a numeric variable with the specified name
8788 and format F1.0. The IN variable takes value 1 in an output case if
8889 the given input file contributed to that output case, and 0 otherwise.
89 The DROP, KEEP, and RENAME subcommands have no effect on IN variables.
90
91 If BY is used (see below), the SORT keyword must be specified after a
92 FILE if that input file is not already sorted on the BY variables.
93 When SORT is specified, PSPP sorts the input file's data on the BY
94 variables before it applies it to the command. When SORT is used, BY
95 is required. SORT is a PSPP extension.
96
97 PSPP merges the dictionaries of all of the input files to form the
90 The @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} subcommands have no effect on IN variables.
91
92 If @subcmd{BY} is used (see below), the @subcmd{SORT} keyword must be specified after a
93 @subcmd{FILE} if that input file is not already sorted on the @subcmd{BY} variables.
94 When @subcmd{SORT} is specified, @pspp{} sorts the input file's data on the @subcmd{BY}
95 variables before it applies it to the command. When @subcmd{SORT} is used, @subcmd{BY}
96 is required. @subcmd{SORT} is a @pspp{} extension.
97
98 @pspp{} merges the dictionaries of all of the input files to form the
9899 dictionary of the new active dataset, like so:
99100
100101 @itemize @bullet
105106 exactly that variable. When more than one input file contains a
106107 variable with a given name, those variables must all have the same
107108 type (numeric or string) and, for string variables, the same width.
108 Variables are matched after renaming with the RENAME subcommand.
109 Thus, RENAME can be used to resolve conflicts.
109 Variables are matched after renaming with the @subcmd{RENAME} subcommand.
110 Thus, @subcmd{RENAME} can be used to resolve conflicts.
110111
111112 @item
112113 The variable label for each output variable is taken from the first
115116
116117 @item
117118 The file label of the new active dataset (@pxref{FILE LABEL}) is that of the
118 first specified FILE that has a file label.
119 first specified @subcmd{FILE} that has a file label.
119120
120121 @item
121122 The documents in the new active dataset (@pxref{DOCUMENT}) are the
122123 concatenation of all the input files' documents, in the order in which
123 the FILE subcommands are specified.
124 the @subcmd{FILE} subcommands are specified.
124125
125126 @item
126127 If all of the input files are weighted on the same variable, then the
130131
131132 The remaining subcommands apply to the output file as a whole, rather
132133 than to individual input files. They must be specified at the end of
133 the command specification, following all of the FILE and related
134 subcommands. The most important of these subcommands is BY, which
134 the command specification, following all of the @subcmd{FILE} and related
135 subcommands. The most important of these subcommands is @subcmd{BY}, which
135136 specifies a set of one or more variables that may be used to find
136137 corresponding cases in each of the input files. The variables
137 specified on BY must be present in all of the input files.
138 Furthermore, if any of the input files are not sorted on the BY
139 variables, then SORT must be specified for those input files.
140
141 The variables listed on BY may include (A) or (D) annotations to
138 specified on @subcmd{BY} must be present in all of the input files.
139 Furthermore, if any of the input files are not sorted on the @subcmd{BY}
140 variables, then @subcmd{SORT} must be specified for those input files.
141
142 The variables listed on @subcmd{BY} may include (A) or (D) annotations to
142143 specify ascending or descending sort order. @xref{SORT CASES}, for
143 more details on this notation. Adding (A) or (D) to the BY subcommand
144 specification is a PSPP extension.
145
146 The DROP subcommand can be used to specify a list of variables to
147 exclude from the output. By contrast, the KEEP subcommand can be used
144 more details on this notation. Adding (A) or (D) to the @subcmd{BY} subcommand
145 specification is a @pspp{} extension.
146
147 The @subcmd{DROP} subcommand can be used to specify a list of variables to
148 exclude from the output. By contrast, the @subcmd{KEEP} subcommand can be used
148149 to specify variables to include in the output; all variables not
149 listed are dropped. DROP and KEEP are executed in left-to-right order
150 and may be repeated any number of times. DROP and KEEP do not affect
151 variables created by the IN, FIRST, and LAST subcommands, which are
150 listed are dropped. @subcmd{DROP} and @subcmd{KEEP} are executed in left-to-right order
151 and may be repeated any number of times. @subcmd{DROP} and @subcmd{KEEP} do not affect
152 variables created by the @subcmd{IN}, @subcmd{FIRST}, and @subcmd{LAST} subcommands, which are
152153 always included in the new active dataset, but they can be used to drop
153 BY variables.
154
155 The FIRST and LAST subcommands are optional. They may only be
156 specified on @cmd{MATCH FILES} and @cmd{ADD FILES}, and only when BY
157 is used. FIRST and LIST each adds a numeric variable to the new
154 @subcmd{BY} variables.
155
156 The @subcmd{FIRST} and @subcmd{LAST} subcommands are optional. They may only be
157 specified on @cmd{MATCH FILES} and @cmd{ADD FILES}, and only when @subcmd{BY}
158 is used. @subcmd{FIRST} and @subcmd{LIST} each adds a numeric variable to the new
158159 active dataset, with the name given as the subcommand's argument and F1.0
159 print and write formats. The value of the FIRST variable is 1 in the
160 first output case with a given set of values for the BY variables, and
161 0 in other cases. Similarly, the LAST variable is 1 in the last case
162 with a given of BY values, and 0 in other cases.
160 print and write formats. The value of the @subcmd{FIRST} variable is 1 in the
161 first output case with a given set of values for the @subcmd{BY} variables, and
162 0 in other cases. Similarly, the @subcmd{LAST} variable is 1 in the last case
163 with a given of @subcmd{BY} values, and 0 in other cases.
163164
164165 When any of these commands creates an output case, variables that are
165166 only in files that are not present for the current case are set to the
174175 ADD FILES
175176
176177 Per input file:
177 /FILE=@{*,'file-name'@}
178 [/RENAME=(src_names=target_names)@dots{}]
179 [/IN=var_name]
178 /FILE=@{*,'@var{file_name}'@}
179 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
180 [/IN=@var{var_name}]
180181 [/SORT]
181182
182183 Once per command:
183 [/BY var_list[(@{D|A@})] [var_list[(@{D|A@})]@dots{}]]
184 [/DROP=var_list]
185 [/KEEP=var_list]
186 [/FIRST=var_name]
187 [/LAST=var_name]
184 [/BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@})]@dots{}]]
185 [/DROP=@var{var_list}]
186 [/KEEP=@var{var_list}]
187 [/FIRST=@var{var_name}]
188 [/LAST=@var{var_name}]
188189 [/MAP]
189190 @end display
190191
192193 which replaces the active dataset, consists all of the cases in all of
193194 the input files.
194195
195 ADD FILES shares the bulk of its syntax with other PSPP commands for
196 @subcmd{ADD FILES} shares the bulk of its syntax with other @pspp{} commands for
196197 combining multiple data files. @xref{Combining Files Common Syntax},
197198 above, for an explanation of this common syntax.
198199
199 When BY is not used, the output of ADD FILES consists of all the cases
200 When @subcmd{BY} is not used, the output of @subcmd{ADD FILES} consists of all the cases
200201 from the first input file specified, followed by all the cases from
201 the second file specified, and so on. When BY is used, the output is
202 additionally sorted on the BY variables.
203
204 When ADD FILES creates an output case, variables that are not part of
202 the second file specified, and so on. When @subcmd{BY} is used, the output is
203 additionally sorted on the @subcmd{BY} variables.
204
205 When @subcmd{ADD FILES} creates an output case, variables that are not part of
205206 the input file from which the case was drawn are set to the
206207 system-missing value for numeric variables or spaces for string
207208 variables.
214215 MATCH FILES
215216
216217 Per input file:
217 /@{FILE,TABLE@}=@{*,'file-name'@}
218 [/RENAME=(src_names=target_names)@dots{}]
219 [/IN=var_name]
218 /@{FILE,TABLE@}=@{*,'@var{file_name}'@}
219 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
220 [/IN=@var{var_name}]
220221 [/SORT]
221222
222223 Once per command:
223 /BY var_list[(@{D|A@}] [var_list[(@{D|A@})]@dots{}]
224 [/DROP=var_list]
225 [/KEEP=var_list]
226 [/FIRST=var_name]
227 [/LAST=var_name]
224 /BY @var{var_list}[(@{D|A@}] [@var{var_list}[(@{D|A@})]@dots{}]
225 [/DROP=@var{var_list}]
226 [/KEEP=@var{var_list}]
227 [/FIRST=@var{var_name}]
228 [/LAST=@var{var_name}]
228229 [/MAP]
229230 @end display
230231
231232 @cmd{MATCH FILES} merges sets of corresponding cases in multiple
232233 input files into single cases in the output, combining their data.
233234
234 MATCH FILES shares the bulk of its syntax with other PSPP commands for
235 @cmd{MATCH FILES} shares the bulk of its syntax with other @pspp{} commands for
235236 combining multiple data files. @xref{Combining Files Common Syntax},
236237 above, for an explanation of this common syntax.
237238
238 How MATCH FILES matches up cases from the input files depends on
239 whether BY is specified:
239 How @cmd{MATCH FILES} matches up cases from the input files depends on
240 whether @subcmd{BY} is specified:
240241
241242 @itemize @bullet
242243 @item
243 If BY is not used, MATCH FILES combines the first case from each input
244 If @subcmd{BY} is not used, @cmd{MATCH FILES} combines the first case from each input
244245 file to produce the first output case, then the second case from each
245246 input file for the second output case, and so on. If some input files
246247 have fewer cases than others, then the shorter files do not contribute
247248 to cases output after their input has been exhausted.
248249
249250 @item
250 If BY is used, MATCH FILES combines cases from each input file that
251 have identical values for the BY variables.
252
253 When BY is used, TABLE subcommands may be used to introduce @dfn{table
254 lookup file}. TABLE has same syntax as FILE, and the RENAME, IN, and
255 SORT subcommands may follow a TABLE in the same way as a FILE.
256 Regardless of the number of TABLEs, at least one FILE must specified.
251 If @subcmd{BY} is used, @cmd{MATCH FILES} combines cases from each input file that
252 have identical values for the @subcmd{BY} variables.
253
254 When @subcmd{BY} is used, @subcmd{TABLE} subcommands may be used to introduce @dfn{table
255 lookup file}. @subcmd{TABLE} has same syntax as @subcmd{FILE}, and the @subcmd{RENAME}, @subcmd{IN}, and
256 @subcmd{SORT} subcommands may follow a @subcmd{TABLE} in the same way as @subcmd{FILE}.
257 Regardless of the number of @subcmd{TABLE}s, at least one @subcmd{FILE} must specified.
257258 Table lookup files are treated in the same way as other input files
258259 for most purposes and, in particular, table lookup files must be
259 sorted on the BY variables or the SORT subcommand must be specified
260 for that TABLE.
260 sorted on the @subcmd{BY} variables or the @subcmd{SORT} subcommand must be specified
261 for that @subcmd{TABLE}.
261262
262263 Cases in table lookup files are not consumed after they have been used
263264 once. This means that data in table lookup files can correspond to
264 any number of cases in FILE input files. Table lookup files are
265 any number of cases in @subcmd{FILE} input files. Table lookup files are
265266 analogous to lookup tables in traditional relational database systems.
266267
267268 If a table lookup file contains more than one case with a given set of
268 BY variables, only the first case is used.
269 @subcmd{BY} variables, only the first case is used.
269270 @end itemize
270271
271 When MATCH FILES creates an output case, variables that are only in
272 When @cmd{MATCH FILES} creates an output case, variables that are only in
272273 files that are not present for the current case are set to the
273274 system-missing value for numeric variables or spaces for string
274275 variables.
281282 UPDATE
282283
283284 Per input file:
284 /FILE=@{*,'file-name'@}
285 [/RENAME=(src_names=target_names)@dots{}]
286 [/IN=var_name]
285 /FILE=@{*,'@var{file_name}'@}
286 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
287 [/IN=@var{var_name}]
287288 [/SORT]
288289
289290 Once per command:
290 /BY var_list[(@{D|A@})] [var_list[(@{D|A@})]]@dots{}
291 [/DROP=var_list]
292 [/KEEP=var_list]
291 /BY @var{var_list}[(@{D|A@})] [@var{var_list}[(@{D|A@})]]@dots{}
292 [/DROP=@var{var_list}]
293 [/KEEP=@var{var_list}]
293294 [/MAP]
294295 @end display
295296
296297 @cmd{UPDATE} updates a @dfn{master file} by applying modifications
297298 from one or more @dfn{transaction files}.
298299
299 UPDATE shares the bulk of its syntax with other PSPP commands for
300 @cmd{UPDATE} shares the bulk of its syntax with other @pspp{} commands for
300301 combining multiple data files. @xref{Combining Files Common Syntax},
301302 above, for an explanation of this common syntax.
302303
303 At least two FILE subcommands must be specified. The first FILE
304 At least two @subcmd{FILE} subcommands must be specified. The first @subcmd{FILE}
304305 subcommand names the master file, and the rest name transaction files.
305306 Every input file must either be sorted on the variables named on the
306 BY subcommand, or the SORT subcommand must be used just after the FILE
307 @subcmd{BY} subcommand, or the @subcmd{SORT} subcommand must be used just after the @subcmd{FILE}
307308 subcommand for that input file.
308309
309 UPDATE uses the variables specified on the BY subcommand, which is
310 @cmd{UPDATE} uses the variables specified on the @subcmd{BY} subcommand, which is
310311 required, to attempt to match each case in a transaction file with a
311312 case in the master file:
312313
315316 When a match is found, then the values of the variables present in the
316317 transaction file replace those variable's values in the new active
317318 file. If there are matching cases in more than more transaction file,
318 PSPP applies the replacements from the first transaction file, then
319 @pspp{} applies the replacements from the first transaction file, then
319320 from the second transaction file, and so on. Similarly, if a single
320 transaction file has cases with duplicate BY values, then those are
321 transaction file has cases with duplicate @subcmd{BY} values, then those are
321322 applied in order to the master file.
322323
323324 When a variable in a transaction file has a missing value or a string
0 @c (modify-syntax-entry ?_ "w")
1 @c (modify-syntax-entry ?' "'")
2 @c (modify-syntax-entry ?@ "'")
3
4
05 @node Data Input and Output
16 @chapter Data Input and Output
27 @cindex input
510 @cindex cases
611 @cindex observations
712
8 Data are the focus of the PSPP language.
13 Data are the focus of the @pspp{} language.
914 Each datum belongs to a @dfn{case} (also called an @dfn{observation}).
1015 Each case represents an individual or ``experimental unit''.
1116 For example, in the results of a survey, the names of the respondents,
1217 their sex, age, etc.@: and their responses are all data and the data
1318 pertaining to single respondent is a case.
1419 This chapter examines
15 the PSPP commands for defining variables and reading and writing data.
20 the @pspp{} commands for defining variables and reading and writing data.
1621 There are alternative commands to read data from predefined sources
1722 such as system files or databases (@xref{GET, GET DATA}.)
1823
1924 @quotation Note
20 These commands tell PSPP how to read data, but the data will not
25 These commands tell @pspp{} how to read data, but the data will not
2126 actually be read until a procedure is executed.
2227 @end quotation
2328
5560 @end display
5661
5762 @cmd{BEGIN DATA} and @cmd{END DATA} can be used to embed raw ASCII
58 data in a PSPP syntax file. @cmd{DATA LIST} or another input
63 data in a @pspp{} syntax file. @cmd{DATA LIST} or another input
5964 procedure must be used before @cmd{BEGIN DATA} (@pxref{DATA LIST}).
6065 @cmd{BEGIN DATA} and @cmd{END DATA} must be used together. @cmd{END
6166 DATA} must appear by itself on a single line, with no leading
7075 @section CLOSE FILE HANDLE
7176
7277 @display
73 CLOSE FILE HANDLE handle_name.
78 CLOSE FILE HANDLE @var{handle_name}.
7479 @end display
7580
7681 @cmd{CLOSE FILE HANDLE} disassociates the name of a file handle with a
8287 DATA} and @cmd{END DATA}, cannot be closed. Attempts to close it with
8388 @cmd{CLOSE FILE HANDLE} have no effect.
8489
85 @cmd{CLOSE FILE HANDLE} is a PSPP extension.
90 @cmd{CLOSE FILE HANDLE} is a @pspp{} extension.
8691
8792 @node DATAFILE ATTRIBUTE
8893 @section DATAFILE ATTRIBUTE
9095
9196 @display
9297 DATAFILE ATTRIBUTE
93 ATTRIBUTE=name('value') [name('value')]@dots{}
94 ATTRIBUTE=name@b{[}index@b{]}('value') [name@b{[}index@b{]}('value')]@dots{}
95 DELETE=name [name]@dots{}
96 DELETE=name@b{[}index@b{]} [name@b{[}index@b{]}]@dots{}
98 ATTRIBUTE=@var{name}('@var{value}') [@var{name}('@var{value}')]@dots{}
99 ATTRIBUTE=@var{name}@b{[}@var{index}@b{]}('@var{value}') [@var{name}@b{[}@var{index}@b{]}('@var{value}')]@dots{}
100 DELETE=@var{name} [@var{name}]@dots{}
101 DELETE=@var{name}@b{[}@var{index}@b{]} [@var{name}@b{[}@var{index}@b{]}]@dots{}
97102 @end display
98103
99104 @cmd{DATAFILE ATTRIBUTE} adds, modifies, or removes user-defined
100105 attributes associated with the active dataset. Custom data file
101 attributes are not interpreted by PSPP, but they are saved as part of
106 attributes are not interpreted by @pspp{}, but they are saved as part of
102107 system files and may be used by other software that reads them.
103108
104 Use the ATTRIBUTE subcommand to add or modify a custom data file
109 Use the @subcmd{ATTRIBUTE} subcommand to add or modify a custom data file
105110 attribute. Specify the name of the attribute as an identifier
106111 (@pxref{Tokens}), followed by the desired value, in parentheses, as a
107112 quoted string. Attribute names that begin with @code{$} are reserved
108 for PSPP's internal use, and attribute names that begin with @code{@@}
109 or @code{$@@} are not displayed by most PSPP commands that display
113 for @pspp{}'s internal use, and attribute names that begin with @code{@@}
114 or @code{$@@} are not displayed by most @pspp{} commands that display
110115 other attributes. Other attribute names are not treated specially.
111116
112117 Attributes may also be organized into arrays. To assign to an array
115120 indexes start at 1, not 0. An attribute array that has a single
116121 element (number 1) is not distinguished from a non-array attribute.
117122
118 Use the DELETE subcommand to delete an attribute. Specify an
123 Use the @subcmd{DELETE} subcommand to delete an attribute. Specify an
119124 attribute name by itself to delete an entire attribute, including all
120125 array elements for attribute arrays. Specify an attribute name
121126 followed by an array index in square brackets to delete a single
136141 @vindex DATASET
137142
138143 @display
139 DATASET NAME name [WINDOW=@{ASIS,FRONT@}].
140 DATASET ACTIVATE name [WINDOW=@{ASIS,FRONT@}].
141 DATASET COPY name [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}].
142 DATASET DECLARE name [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}].
143 DATASET CLOSE @{name,*,ALL@}.
144 DATASET NAME @var{name} [WINDOW=@{ASIS,FRONT@}].
145 DATASET ACTIVATE @var{name} [WINDOW=@{ASIS,FRONT@}].
146 DATASET COPY @var{name} [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}].
147 DATASET DECLARE @var{name} [WINDOW=@{MINIMIZED,HIDDEN,FRONT@}].
148 DATASET CLOSE @{@var{name},*,ALL@}.
144149 DATASET DISPLAY.
145150 @end display
146151
147152 The @cmd{DATASET} commands simplify use of multiple datasets within a
148 PSPP session. They allow datasets to be created and destroyed. At
149 any given time, most PSPP commands work with a single dataset, called
153 @pspp{} session. They allow datasets to be created and destroyed. At
154 any given time, most @pspp{} commands work with a single dataset, called
150155 the active dataset.
151156
152157 @vindex DATASET NAME
186191 @vindex DATASET DISPLAY
187192 The DATASET DISPLAY command lists all the currently defined datasets.
188193
189 Many DATASET commands accept an optional WINDOW subcommand. In the
190 PSPPIRE GUI, the value given for this subcommand influences how the
191 dataset's window is displayed. Outside the GUI, the WINDOW subcommand
194 Many DATASET commands accept an optional @subcmd{WINDOW} subcommand. In the
195 @pspp{}IRE GUI, the value given for this subcommand influences how the
196 dataset's window is displayed. Outside the GUI, the @subcmd{WINDOW} subcommand
192197 has no effect. The valid values are:
193198
194199 @table @asis
221226 fundamental data-reading command. Even the more sophisticated input
222227 methods use @cmd{DATA LIST} commands as a building block.
223228 Understanding @cmd{DATA LIST} is important to understanding how to use
224 PSPP to read your data files.
229 @pspp{} to read your data files.
225230
226231 There are two major variants of @cmd{DATA LIST}, which are fixed
227232 format and free format. In addition, free format has a minor variant,
251256 @display
252257 DATA LIST [FIXED]
253258 @{TABLE,NOTABLE@}
254 [FILE='file-name' [ENCODING='encoding']]
255 [RECORDS=record_count]
256 [END=end_var]
257 [SKIP=record_count]
258 /[line_no] var_spec@dots{}
259
260 where each var_spec takes one of the forms
261 var_list start-end [type_spec]
262 var_list (fortran_spec)
259 [FILE='@var{file_name}' [ENCODING='@var{encoding}']]
260 [RECORDS=@var{record_count}]
261 [END=@var{end_var}]
262 [SKIP=@var{record_count}]
263 /[line_no] @var{var_spec}@dots{}
264
265 where each @var{var_spec} takes one of the forms
266 @var{var_list} @var{start}-@var{end} [@var{type_spec}]
267 @var{var_list} (@var{fortran_spec})
263268 @end display
264269
265270 @cmd{DATA LIST FIXED} is used to read data files that have values at fixed
266271 positions on each line of single-line or multiline records. The
267272 keyword FIXED is optional.
268273
269 The FILE subcommand must be used if input is to be taken from an
274 The @subcmd{FILE} subcommand must be used if input is to be taken from an
270275 external file. It may be used to specify a file name as a string or a
271 file handle (@pxref{File Handles}). If the FILE subcommand is not used,
276 file handle (@pxref{File Handles}). If the @subcmd{FILE} subcommand is not used,
272277 then input is assumed to be specified within the command file using
273278 @cmd{BEGIN DATA}@dots{}@cmd{END DATA} (@pxref{BEGIN DATA}).
274 The ENCODING subcommand may only be used if the FILE subcommand is also used.
275 It specifies the character encoding of the file.
276
277 The optional RECORDS subcommand, which takes a single integer as an
278 argument, is used to specify the number of lines per record. If RECORDS
279 The @subcmd{ENCODING} subcommand may only be used if the @subcmd{FILE}
280 subcommand is also used. It specifies the character encoding of the
281 file. @xref{INSERT}, for information on supported encodings.
282
283 The optional @subcmd{RECORDS} subcommand, which takes a single integer as an
284 argument, is used to specify the number of lines per record.
285 If @subcmd{RECORDS}
279286 is not specified, then the number of lines per record is calculated from
280287 the list of variable specifications later in @cmd{DATA LIST}.
281288
282 The END subcommand is only useful in conjunction with @cmd{INPUT
289 The @subcmd{END} subcommand is only useful in conjunction with @cmd{INPUT
283290 PROGRAM}. @xref{INPUT PROGRAM}, for details.
284291
285 The optional SKIP subcommand specifies a number of records to skip at
292 The optional @subcmd{SKIP} subcommand specifies a number of records to skip at
286293 the beginning of an input file. It can be used to skip over a row
287294 that contains variable names, for example.
288295
289296 @cmd{DATA LIST} can optionally output a table describing how the data file
290 will be read. The TABLE subcommand enables this output, and NOTABLE
291 disables it. The default is to output the table.
297 will be read. The @subcmd{TABLE} subcommand enables this output, and
298 @subcmd{NOTABLE} disables it. The default is to output the table.
292299
293300 The list of variables to be read from the data list must come last.
294301 Each line in the data record is introduced by a slash (@samp{/}).
297304
298305 Each variable specification consists of a list of variable names
299306 followed by a description of their location on the input line. Sets of
300 variables may be specified using the @code{DATA LIST} TO convention
307 variables may be specified using the @cmd{DATA LIST} @subcmd{TO} convention
301308 (@pxref{Sets of
302309 Variables}). There are two ways to specify the location of the variable
303310 on the line: columnar style and FORTRAN style.
414421 3 Bill Yates 9 18 6
415422 @end example
416423
417 The @code{TABLE} keyword causes PSPP to print out a table
424 The @code{TABLE} keyword causes @pspp{} to print out a table
418425 describing the four variables defined.
419426
420427 @item
464471
465472 @display
466473 DATA LIST FREE
467 [(@{TAB,'c'@}, @dots{})]
474 [(@{TAB,'@var{c}'@}, @dots{})]
468475 [@{NOTABLE,TABLE@}]
469 [FILE='file-name' [ENCODING='encoding']]
470 [SKIP=record_cnt]
471 /var_spec@dots{}
472
473 where each var_spec takes one of the forms
474 var_list [(type_spec)]
475 var_list *
476 [FILE='@var{file_name}' [ENCODING='@var{encoding}']]
477 [SKIP=@var{record_cnt}]
478 /@var{var_spec}@dots{}
479
480 where each @var{var_spec} takes one of the forms
481 @var{var_list} [(@var{type_spec})]
482 @var{var_list} *
476483 @end display
477484
478485 In free format, the input data is, by default, structured as a series
493500 not trimmed, consecutive delimiters define empty fields, and no form
494501 of quoting is allowed.
495502
496 The NOTABLE and TABLE subcommands are as in @cmd{DATA LIST FIXED} above.
497 NOTABLE is the default.
498
499 The FILE and SKIP subcommands are as in @cmd{DATA LIST FIXED} above.
503 The @subcmd{NOTABLE} and @subcmd{TABLE} subcommands are as in @cmd{DATA LIST FIXED} above.
504 @subcmd{NOTABLE} is the default.
505
506 The @subcmd{FILE}, @subcmd{SKIP}, and @subcmd{ENCODING} subcommands
507 are as in @cmd{DATA LIST FIXED} above.
500508
501509 The variables to be parsed are given as a single list of variable names.
502510 This list must be introduced by a single slash (@samp{/}). The set of
516524
517525 @display
518526 DATA LIST LIST
519 [(@{TAB,'c'@}, @dots{})]
527 [(@{TAB,'@var{c}'@}, @dots{})]
520528 [@{NOTABLE,TABLE@}]
521 [FILE='file-name' [ENCODING='encoding']]
522 [SKIP=record_count]
523 /var_spec@dots{}
524
525 where each var_spec takes one of the forms
526 var_list [(type_spec)]
527 var_list *
529 [FILE='@var{file_name}' [ENCODING='@var{encoding}']]
530 [SKIP=@var{record_count}]
531 /@var{var_spec}@dots{}
532
533 where each @var{var_spec} takes one of the forms
534 @var{var_list} [(@var{type_spec})]
535 @var{var_list} *
528536 @end display
529537
530538 With one exception, @cmd{DATA LIST LIST} is syntactically and
561569
562570 @display
563571 For text files:
564 FILE HANDLE handle_name
565 /NAME='file-name'
572 FILE HANDLE @var{handle_name}
573 /NAME='@var{file_name}
566574 [/MODE=CHARACTER]
567 /TABWIDTH=tab_width
575 /TABWIDTH=@var{tab_width}
576 [ENCODING='@var{encoding}']
568577
569578 For binary files in native encoding with fixed-length records:
570 FILE HANDLE handle_name
571 /NAME='file-name'
579 FILE HANDLE @var{handle_name}
580 /NAME='@var{file_name}'
572581 /MODE=IMAGE
573 [/LRECL=rec_len]
582 [/LRECL=@var{rec_len}]
583 [ENCODING='@var{encoding}']
574584
575585 For binary files in native encoding with variable-length records:
576 FILE HANDLE handle_name
577 /NAME='file-name'
586 FILE HANDLE @var{handle_name}
587 /NAME='@var{file_name}'
578588 /MODE=BINARY
579 [/LRECL=rec_len]
589 [/LRECL=@var{rec_len}]
590 [ENCODING='@var{encoding}']
580591
581592 For binary files encoded in EBCDIC:
582 FILE HANDLE handle_name
583 /NAME='file-name'
593 FILE HANDLE @var{handle_name}
594 /NAME='@var{file_name}'
584595 /MODE=360
585596 /RECFORM=@{FIXED,VARIABLE,SPANNED@}
586 [/LRECL=rec_len]
597 [/LRECL=@var{rec_len}]
598 [ENCODING='@var{encoding}']
587599 @end display
588600
589601 Use @cmd{FILE HANDLE} to associate a file handle name with a file and
602614 invocation of @cmd{FILE HANDLE}, unless it has been closed by an
603615 intervening command (@pxref{CLOSE FILE HANDLE}).
604616
605 The effect and syntax of FILE HANDLE depends on the selected MODE:
617 The effect and syntax of @cmd{FILE HANDLE} depends on the selected MODE:
606618
607619 @itemize
608620 @item
612624
613625 In CHARACTER mode only, tabs are expanded to spaces by input programs,
614626 except by @cmd{DATA LIST FREE} with explicitly specified delimiters.
615 Each tab is 4 characters wide by default, but TABWIDTH (a PSPP
627 Each tab is 4 characters wide by default, but TABWIDTH (a @pspp{}
616628 extension) may be used to specify an alternate width. Use a TABWIDTH
617629 of 0 to suppress tab expansion.
618630
630642 is ignored. The data for each record is both preceded and followed by
631643 a 32-bit signed integer in little-endian byte order that specifies the
632644 length of the record. (This redundancy permits records in these
633 files to be efficiently read in reverse order, although PSPP always
645 files to be efficiently read in reverse order, although @pspp{} always
634646 reads them in forward order.) The length does not include either
635647 integer.
636648
641653 information, see @cite{OS/400 Tape and Diskette Device Programming},
642654 available on IBM's website.
643655
644 Alphanumeric data in mode 360 files are encoded in EBCDIC. PSPP
656 Alphanumeric data in mode 360 files are encoded in EBCDIC. @pspp{}
645657 translates EBCDIC to or from the host's native format as necessary on
646658 input or output, using an ASCII/EBCDIC translation that is one-to-one,
647659 so that a ``round trip'' from ASCII to EBCDIC back to ASCII, or vice
648660 versa, always yields exactly the original data.
649661
650 The RECFORM subcommand is required in mode 360. The precise file
662 The @subcmd{RECFORM} subcommand is required in mode 360. The precise file
651663 format depends on its setting:
652664
653665 @table @asis
700712 SCC.
701713
702714 The maximum length of a logical record in VARIABLE mode is limited
703 only by memory available to PSPP. Segments are limited to 65,527
715 only by memory available to @pspp{}. Segments are limited to 65,527
704716 bytes, as in VARIABLE mode.
705717
706718 This format is similar to what IBM documentation call @code{*VS}
715727 wart is implemented for compatibility.
716728 @end itemize
717729
718 The NAME subcommand specifies the name of the file associated with the
730 The @subcmd{NAME} subcommand specifies the name of the file associated with the
719731 handle. It is required in all modes but SCRATCH mode, in which its
720732 use is forbidden.
733
734 The ENCODING subcommand specifies the encoding of text in the file.
735 For reading text files in CHARACTER mode, all of the forms described
736 for ENCODING on the INSERT command are supported (@pxref{INSERT}).
737 For reading in other file-based modes, encoding autodetection is not
738 supported; if the specified encoding requests autodetection then the
739 default encoding will be used. This is also true when a file handle
740 is used for writing a file in any mode.
721741
722742 @node INPUT PROGRAM
723743 @section INPUT PROGRAM
731751
732752 @cmd{INPUT PROGRAM}@dots{}@cmd{END INPUT PROGRAM} specifies a
733753 complex input program. By placing data input commands within @cmd{INPUT
734 PROGRAM}, PSPP programs can take advantage of more complex file
754 PROGRAM}, @pspp{} programs can take advantage of more complex file
735755 structures than available with only @cmd{DATA LIST}.
736756
737757 The first sort of extended input program is to simply put multiple @cmd{DATA
747767
748768 To prevent @cmd{INPUT PROGRAM} from terminating at the first end of
749769 file, use
750 the END subcommand on @cmd{DATA LIST}. This subcommand takes a
770 the @subcmd{END} subcommand on @cmd{DATA LIST}. This subcommand takes a
751771 variable name,
752772 which should be a numeric scratch variable (@pxref{Scratch Variables}).
753773 (It need not be a scratch variable but otherwise the results can be
761781 when cases are output. When @cmd{END CASE} is used, looping from the end of
762782 @cmd{INPUT PROGRAM} to the beginning does not cause a case to be output.
763783
764 @cmd{END FILE} is the second. When the END subcommand is used on @cmd{DATA
784 @cmd{END FILE} is the second. When the @subcmd{END} subcommand is used on @cmd{DATA
765785 LIST}, there is no way for the @cmd{INPUT PROGRAM} construct to stop
766786 looping,
767787 so an infinite loop results. @cmd{END FILE}, when executed,
886906
887907 @display
888908 LIST
889 /VARIABLES=var_list
890 /CASES=FROM start_index TO end_index BY incr_index
909 /VARIABLES=@var{var_list}
910 /CASES=FROM @var{start_index} TO @var{end_index} BY @var{incr_index}
891911 /FORMAT=@{UNNUMBERED,NUMBERED@} @{WRAP,SINGLE@}
892912 @end display
893913
894914 The @cmd{LIST} procedure prints the values of specified variables to the
895915 listing file.
896916
897 The VARIABLES subcommand specifies the variables whose values are to be
898 printed. Keyword VARIABLES is optional. If VARIABLES subcommand is not
917 The @subcmd{VARIABLES} subcommand specifies the variables whose values are to be
918 printed. Keyword VARIABLES is optional. If @subcmd{VARIABLES} subcommand is not
899919 specified then all variables in the active dataset are printed.
900920
901 The CASES subcommand can be used to specify a subset of cases to be
902 printed. Specify FROM and the case number of the first case to print,
903 TO and the case number of the last case to print, and BY and the number
921 The @subcmd{CASES} subcommand can be used to specify a subset of cases to be
922 printed. Specify @subcmd{FROM} and the case number of the first case to print,
923 @subcmd{TO} and the case number of the last case to print, and @subcmd{BY} and the number
904924 of cases to advance between printing cases, or any subset of those
905 settings. If CASES is not specified then all cases are printed.
906
907 The FORMAT subcommand can be used to change the output format. NUMBERED
908 will print case numbers along with each case; UNNUMBERED, the default,
909 causes the case numbers to be omitted. The WRAP and SINGLE settings are
925 settings. If @subcmd{CASES} is not specified then all cases are printed.
926
927 The @subcmd{FORMAT} subcommand can be used to change the output format. @subcmd{NUMBERED}
928 will print case numbers along with each case; @subcmd{UNNUMBERED}, the default,
929 causes the case numbers to be omitted. The @subcmd{WRAP} and @subcmd{SINGLE} settings are
910930 currently not used.
911931
912932 Case numbers start from 1. They are counted after all transformations
935955
936956 @display
937957 PRINT
938 OUTFILE='file-name'
939 RECORDS=n_lines
940 @{NOTABLE,TABLE@}
941 [/[line_no] arg@dots{}]
942
943 arg takes one of the following forms:
944 'string' [start-end]
945 var_list start-end [type_spec]
946 var_list (fortran_spec)
947 var_list *
958 [OUTFILE='@var{file_name}']
959 [RECORDS=@var{n_lines}]
960 [@{NOTABLE,TABLE@}]
961 [ENCODING='@var{encoding}']
962 [/[@var{line_no}] @var{arg}@dots{}]
963
964 @var{arg} takes one of the following forms:
965 '@var{string}' [@var{start}-@var{end}]
966 @var{var_list} @var{start}-@var{end} [@var{type_spec}]
967 @var{var_list} (@var{fortran_spec})
968 @var{var_list} *
948969 @end display
949970
950971 The @cmd{PRINT} transformation writes variable data to the listing
953974 print variable data without invoking a procedure (@pxref{EXECUTE}).
954975
955976 All @cmd{PRINT} subcommands are optional. If no strings or variables
956 are specified, PRINT outputs a single blank line.
957
958 The OUTFILE subcommand specifies the file to receive the output. The
977 are specified, @cmd{PRINT} outputs a single blank line.
978
979 The @subcmd{OUTFILE} subcommand specifies the file to receive the output. The
959980 file may be a file name as a string or a file handle (@pxref{File
960 Handles}). If OUTFILE is not present then output will be sent to
961 PSPP's output listing file. When OUTFILE is present, a space is
981 Handles}). If @subcmd{OUTFILE} is not present then output will be sent to
982 @pspp{}'s output listing file. When @subcmd{OUTFILE} is present, a space is
962983 inserted at beginning of each output line, even lines that otherwise
963984 would be blank.
964985
965 The RECORDS subcommand specifies the number of lines to be output. The
986 The @subcmd{ENCODING} subcommand may only be used if the
987 @subcmd{OUTFILE} subcommand is also used. It specifies the character
988 encoding of the file. @xref{INSERT}, for information on supported
989 encodings.
990
991 The @subcmd{RECORDS} subcommand specifies the number of lines to be output. The
966992 number of lines may optionally be surrounded by parentheses.
967993
968 TABLE will cause the PRINT command to output a table to the listing file
969 that describes what it will print to the output file. NOTABLE, the
994 @subcmd{TABLE} will cause the @cmd{PRINT} command to output a table to the listing file
995 that describes what it will print to the output file. @subcmd{NOTABLE}, the
970996 default, suppresses this output table.
971997
972998 Introduce the strings and variables to be printed with a slash
10011027
10021028 @display
10031029 PRINT EJECT
1004 OUTFILE='file-name'
1005 RECORDS=n_lines
1030 OUTFILE='@var{file_name}'
1031 RECORDS=@var{n_lines}
10061032 @{NOTABLE,TABLE@}
1007 /[line_no] arg@dots{}
1008
1009 arg takes one of the following forms:
1010 'string' [start-end]
1011 var_list start-end [type_spec]
1012 var_list (fortran_spec)
1013 var_list *
1033 /[@var{line_no}] @var{arg}@dots{}
1034
1035 @var{arg} takes one of the following forms:
1036 '@var{string}' [@var{start}-@var{end}]
1037 @var{var_list} @var{start}-@var{end} [@var{type_spec}]
1038 @var{var_list} (@var{fortran_spec})
1039 @var{var_list} *
10141040 @end display
10151041
10161042 @cmd{PRINT EJECT} advances to the beginning of a new output page in
10191045
10201046 All @cmd{PRINT EJECT} subcommands are optional.
10211047
1022 Without OUTFILE, PRINT EJECT ejects the current page in
1048 Without @subcmd{OUTFILE}, @cmd{PRINT EJECT} ejects the current page in
10231049 the listing file, then it produces other output, if any is specified.
10241050
1025 With OUTFILE, PRINT EJECT writes its output to the specified file.
1051 With @subcmd{OUTFILE}, @cmd{PRINT EJECT} writes its output to the specified file.
10261052 The first line of output is written with @samp{1} inserted in the
10271053 first column. Commonly, this is the only line of output. If
10281054 additional lines of output are specified, these additional lines are
1029 written with a space inserted in the first column, as with PRINT.
1055 written with a space inserted in the first column, as with @subcmd{PRINT}.
10301056
10311057 @xref{PRINT}, for more information on syntax and usage.
10321058
10351061 @vindex PRINT SPACE
10361062
10371063 @display
1038 PRINT SPACE OUTFILE='file-name' n_lines.
1064 PRINT SPACE [OUTFILE='file_name'] [ENCODING='@var{encoding}'] [n_lines].
10391065 @end display
10401066
10411067 @cmd{PRINT SPACE} prints one or more blank lines to an output file.
10421068
1043 The OUTFILE subcommand is optional. It may be used to direct output to
1069 The @subcmd{OUTFILE} subcommand is optional. It may be used to direct output to
10441070 a file specified by file name as a string or file handle (@pxref{File
10451071 Handles}). If OUTFILE is not specified then output will be directed to
10461072 the listing file.
10471073
1074 The @subcmd{ENCODING} subcommand may only be used if @subcmd{OUTFILE}
1075 is also used. It specifies the character encoding of the file.
1076 @xref{INSERT}, for information on supported encodings.
1077
10481078 n_lines is also optional. If present, it is an expression
10491079 (@pxref{Expressions}) specifying the number of blank lines to be
10501080 printed. The expression must evaluate to a nonnegative value.
10541084 @vindex REREAD
10551085
10561086 @display
1057 REREAD FILE=handle COLUMN=column.
1087 REREAD [FILE=handle] [COLUMN=column] [ENCODING='@var{encoding}'].
10581088 @end display
10591089
10601090 The @cmd{REREAD} transformation allows the previous input line in a
10621092 already processed by @cmd{DATA LIST} or another input command to be re-read
10631093 for further processing.
10641094
1065 The FILE subcommand, which is optional, is used to specify the file to
1095 The @subcmd{FILE} subcommand, which is optional, is used to specify the file to
10661096 have its line re-read. The file must be specified as the name of a file
10671097 handle (@pxref{File Handles}). If FILE is not specified then the last
10681098 file specified on @cmd{DATA LIST} will be assumed (last file specified
10691099 lexically, not in terms of flow-of-control).
10701100
10711101 By default, the line re-read is re-read in its entirety. With the
1072 COLUMN subcommand, a prefix of the line can be exempted from
1102 @subcmd{COLUMN} subcommand, a prefix of the line can be exempted from
10731103 re-reading. Specify an expression (@pxref{Expressions}) evaluating to
10741104 the first column that should be included in the re-read line. Columns
10751105 are numbered from 1 at the left margin.
10761106
1107 The @subcmd{ENCODING} subcommand may only be used if the @subcmd{FILE}
1108 subcommand is also used. It specifies the character encoding of the
1109 file. @xref{INSERT}, for information on supported encodings.
1110
10771111 Issuing @code{REREAD} multiple times will not back up in the data
10781112 file. Instead, it will re-read the same line multiple times.
10791113
10831117
10841118 @display
10851119 REPEATING DATA
1086 /STARTS=start-end
1087 /OCCURS=n_occurs
1088 /FILE='file-name'
1089 /LENGTH=length
1090 /CONTINUED[=cont_start-cont_end]
1091 /ID=id_start-id_end=id_var
1120 /STARTS=@var{start}-@var{end}
1121 /OCCURS=@var{n_occurs}
1122 /FILE='@var{file_name}'
1123 /LENGTH=@var{length}
1124 /CONTINUED[=@var{cont_start}-@var{cont_end}]
1125 /ID=@var{id_start}-@var{id_end}=@var{id_var}
10921126 /@{TABLE,NOTABLE@}
1093 /DATA=var_spec@dots{}
1094
1095 where each var_spec takes one of the forms
1096 var_list start-end [type_spec]
1097 var_list (fortran_spec)
1127 /DATA=@var{var_spec}@dots{}
1128
1129 where each @var{var_spec} takes one of the forms
1130 @var{var_list} @var{start}-@var{end} [@var{type_spec}]
1131 @var{var_list} (@var{fortran_spec})
10981132 @end display
10991133
11001134 @cmd{REPEATING DATA} parses groups of data repeating in
11051139 can be used to parse groups of cases that share a subset of variables
11061140 but differ in their other data.
11071141
1108 The STARTS subcommand is required. Specify a range of columns, using
1142 The @subcmd{STARTS} subcommand is required. Specify a range of columns, using
11091143 literal numbers or numeric variable names. This range specifies the
11101144 columns on the first line that are used to contain groups of data. The
11111145 ending column is optional. If it is not specified, then the record
11131147 DATA}) this is 80 columns; for a file with fixed record widths it is the
11141148 record width; for other files it is 1024 characters by default.
11151149
1116 The OCCURS subcommand is required. It must be a number or the name of a
1150 The @subcmd{OCCURS} subcommand is required. It must be a number or the name of a
11171151 numeric variable. Its value is the number of groups present in the
11181152 current record.
11191153
1120 The DATA subcommand is required. It must be the last subcommand
1154 The @subcmd{DATA} subcommand is required. It must be the last subcommand
11211155 specified. It is used to specify the data present within each repeating
11221156 group. Column numbers are specified relative to the beginning of a
11231157 group at column 1. Data is specified in the same way as with @cmd{DATA LIST
11311165 terms of flow of control).
11321166
11331167 By default @cmd{REPEATING DATA} will output a table describing how it will
1134 parse the input data. Specifying NOTABLE will disable this behavior;
1168 parse the input data. Specifying @subcmd{NOTABLE} will disable this behavior;
11351169 specifying TABLE will explicitly enable it.
11361170
1137 The LENGTH subcommand specifies the length in characters of each group.
1138 If it is not present then length is inferred from the DATA subcommand.
1171 The @subcmd{LENGTH} subcommand specifies the length in characters of each group.
1172 If it is not present then length is inferred from the @subcmd{DATA} subcommand.
11391173 LENGTH can be a number or a variable name.
11401174
11411175 Normally all the data groups are expected to be present on a single
1142 line. Use the CONTINUED command to indicate that data can be continued
1176 line. Use the @subcmd{CONTINUED} command to indicate that data can be continued
11431177 onto additional lines. If data on continuation lines starts at the left
11441178 margin and continues through the entire field width, no column
1145 specifications are necessary on CONTINUED. Otherwise, specify the
1179 specifications are necessary on @subcmd{CONTINUED}. Otherwise, specify the
11461180 possible range of columns in the same way as on STARTS.
11471181
11481182 When data groups are continued from line to line, it is easy
11491183 for cases to get out of sync through careless hand editing. The
1150 ID subcommand allows a case identifier to be present on each line of
1184 @subcmd{ID} subcommand allows a case identifier to be present on each line of
11511185 repeating data groups. @cmd{REPEATING DATA} will check for the same
11521186 identifier on each line and report mismatches. Specify the range of
11531187 columns that the identifier will occupy, followed by an equals sign
11651199
11661200 @display
11671201 WRITE
1168 OUTFILE='file-name'
1169 RECORDS=n_lines
1202 OUTFILE='@var{file_name}'
1203 RECORDS=@var{n_lines}
11701204 @{NOTABLE,TABLE@}
1171 /[line_no] arg@dots{}
1172
1173 arg takes one of the following forms:
1174 'string' [start-end]
1175 var_list start-end [type_spec]
1176 var_list (fortran_spec)
1177 var_list *
1205 /[@var{line_no}] @var{arg}@dots{}
1206
1207 @var{arg} takes one of the following forms:
1208 '@var{string}' [@var{start}-@var{end}]
1209 @var{var_list} @var{start}-@var{end} [@var{type_spec}]
1210 @var{var_list} (@var{fortran_spec})
1211 @var{var_list} *
11781212 @end display
11791213
11801214 @code{WRITE} writes text or binary data to an output file.
00 @node Data Selection
11 @chapter Selecting data for analysis
22
3 This chapter documents PSPP commands that temporarily or permanently
3 This chapter documents @pspp{} commands that temporarily or permanently
44 select data records from the active dataset for analysis.
55
66 @menu
1818 @vindex FILTER
1919
2020 @display
21 FILTER BY var_name.
21 FILTER BY @var{var_name}.
2222 FILTER OFF.
2323 @end display
2424
2525 @cmd{FILTER} allows a boolean-valued variable to be used to select
2626 cases from the data stream for processing.
2727
28 To set up filtering, specify BY and a variable name. Keyword
28 To set up filtering, specify @subcmd{BY} and a variable name. Keyword
2929 BY is optional but recommended. Cases which have a zero or system- or
3030 user-missing value are excluded from analysis, but not deleted from the
3131 data stream. Cases with other values are analyzed.
3939 Filtering takes place immediately before cases pass to a procedure for
4040 analysis. Only one filter variable may be active at a time. Normally,
4141 case filtering continues until it is explicitly turned off with @code{FILTER
42 OFF}. However, if @cmd{FILTER} is placed after TEMPORARY, it filters only
42 OFF}. However, if @cmd{FILTER} is placed after @cmd{TEMPORARY}, it filters only
4343 the next procedure or procedure-like command.
4444
4545 @node N OF CASES
4747 @vindex N OF CASES
4848
4949 @display
50 N [OF CASES] num_of_cases [ESTIMATED].
50 N [OF CASES] @var{num_of_cases} [ESTIMATED].
5151 @end display
5252
5353 @cmd{N OF CASES} limits the number of cases processed by any
5454 procedures that follow it in the command stream. @code{N OF CASES
55 100}, for example, tells PSPP to disregard all cases after the first
55 100}, for example, tells @pspp{} to disregard all cases after the first
5656 100.
5757
5858 When @cmd{N OF CASES} is specified after @cmd{TEMPORARY}, it affects
7474 @cmd{N OF CASES} with the @code{ESTIMATED} keyword gives an estimated
7575 number of cases before @cmd{DATA LIST} or another command to read in
7676 data. @code{ESTIMATED} never limits the number of cases processed by
77 procedures. PSPP currently does not make use of case count estimates.
77 procedures. @pspp{} currently does not make use of case count estimates.
7878
7979 @node SAMPLE
8080 @section SAMPLE
8181 @vindex SAMPLE
8282
8383 @display
84 SAMPLE num1 [FROM num2].
84 SAMPLE @var{num1} [FROM @var{num2}].
8585 @end display
8686
8787 @cmd{SAMPLE} randomly samples a proportion of the cases in the active
8989 transformation, permanently removing cases from the active dataset.
9090
9191 The proportion to sample can be expressed as a single number between 0
92 and 1. If @code{k} is the number specified, and @code{N} is the number
92 and 1. If @var{k} is the number specified, and @var{N} is the number
9393 of currently-selected cases in the active dataset, then after
94 @code{SAMPLE @var{k}.}, approximately @code{k*N} cases will be
94 @subcmd{SAMPLE @var{k}.}, approximately @var{k}*@var{N} cases will be
9595 selected.
9696
97 The proportion to sample can also be specified in the style @code{SAMPLE
97 The proportion to sample can also be specified in the style @subcmd{SAMPLE
9898 @var{m} FROM @var{N}}. With this style, cases are selected as follows:
9999
100100 @enumerate
130130 @vindex SELECT IF
131131
132132 @display
133 SELECT IF expression.
134 @end display
135
136 @cmd{SELECT IF} selects cases for analysis based on the value of a
137 boolean expression. Cases not selected are permanently eliminated
133 SELECT IF @var{expression}.
134 @end display
135
136 @cmd{SELECT IF} selects cases for analysis based on the value of
137 @var{expression}. Cases not selected are permanently eliminated
138138 from the active dataset, unless @cmd{TEMPORARY} is in effect
139139 (@pxref{TEMPORARY}).
140140
156156 @vindex SPLIT FILE
157157
158158 @display
159 SPLIT FILE [@{LAYERED, SEPARATE@}] BY var_list.
159 SPLIT FILE [@{LAYERED, SEPARATE@}] BY @var{var_list}.
160160 SPLIT FILE OFF.
161161 @end display
162162
171171 variable values for the group are printed along with the analysis.
172172
173173 When a list of variable names is specified, one of the keywords
174 LAYERED or SEPARATE may also be specified. If provided, either
174 @subcmd{LAYERED} or @subcmd{SEPARATE} may also be specified. If provided, either
175175 keyword are ignored.
176176
177177 Groups are formed only by @emph{adjacent} cases. To create a split
178178 using a variable where like values are not adjacent in the working file,
179179 you should first sort the data by that variable (@pxref{SORT CASES}).
180180
181 Specify OFF to disable @cmd{SPLIT FILE} and resume analysis of the
181 Specify @subcmd{OFF} to disable @cmd{SPLIT FILE} and resume analysis of the
182182 entire active dataset as a single group of data.
183183
184184 When @cmd{SPLIT FILE} is specified after @cmd{TEMPORARY}, it affects only
217217 20
218218 24
219219 END DATA.
220
220221 COMPUTE X=X/2.
222
221223 TEMPORARY.
222224 COMPUTE X=X+3.
225
223226 DESCRIPTIVES X.
224227 DESCRIPTIVES X.
225228 @end example
233236 @vindex WEIGHT
234237
235238 @display
236 WEIGHT BY var_name.
239 WEIGHT BY @var{var_name}.
237240 WEIGHT OFF.
238241 @end display
239242
243246
244247 If a variable name is specified, @cmd{WEIGHT} causes the values of that
245248 variable to be used as weighting factors for subsequent statistical
246 procedures. Use of keyword BY is optional but recommended. Weighting
249 procedures. Use of keyword @subcmd{BY} is optional but recommended. Weighting
247250 variables must be numeric. Scratch variables may not be used for
248251 weighting (@pxref{Scratch Variables}).
249252
250 When OFF is specified, subsequent statistical procedures will weight all
253 When @subcmd{OFF} is specified, subsequent statistical procedures will weight all
251254 cases equally.
252255
253256 A positive integer weighting factor @var{w} on a case will yield the
0 @c Use @func when refering to a function.
1 @c Use @deftypefn for their definitions
2 @macro func{NAME}
3 @code{/NAME/}
4 @end macro
5
06 @node Expressions
17 @chapter Mathematical Expressions
28 @cindex expressions, mathematical
39 @cindex mathematical expressions
410
5 Expressions share a common syntax each place they appear in PSPP
11 Expressions share a common syntax each place they appear in @pspp{}
612 commands. Expressions are made up of @dfn{operands}, which can be
713 numbers, strings, or variable names, separated by @dfn{operators}.
814 There are five types of operators: grouping, arithmetic, logical,
2935 @cindex Boolean
3036 @cindex values, Boolean
3137
32 Some PSPP operators and expressions work with Boolean values, which
38 Some @pspp{} operators and expressions work with Boolean values, which
3339 represent true/false conditions. Booleans have only three possible
3440 values: 0 (false), 1 (true), and system-missing (unknown).
3541 System-missing is neither true nor false and indicates that the true
237243 @cindex @code{(}
238244 @cindex @code{)}
239245 @cindex names, of functions
240 PSPP functions provide mathematical abilities above and beyond
246 @pspp{} functions provide mathematical abilities above and beyond
241247 those possible using simple operators. Functions have a common
242248 syntax: each is composed of a function name followed by a left
243249 parenthesis, one or more arguments, and a right parenthesis.
244250
245251 Function names are not reserved. Their names are specially treated
246 only when followed by a left parenthesis, so that @code{EXP(10)}
247 refers to the constant value @code{e} raised to the 10th power, but
248 @code{EXP} by itself refers to the value of variable EXP.
252 only when followed by a left parenthesis, so that @samp{EXP(10)}
253 refers to the constant value @math{e} raised to the 10th power, but
254 @samp{EXP} by itself refers to the value of a variable called @code{EXP}.
249255
250256 The sections below describe each function in detail.
251257
272278 numeric results.
273279
274280 @deftypefn {Function} {} EXP (@var{exponent})
275 Returns @i{e} (approximately 2.71828) raised to power @var{exponent}.
281 Returns @math{e} (approximately 2.71828) raised to power @var{exponent}.
276282 @end deftypefn
277283
278284 @cindex logarithms
282288 @end deftypefn
283289
284290 @deftypefn {Function} {} LN (@var{number})
285 Takes the base-@i{e} logarithm of @var{number}. If @var{number} is
291 Takes the base-@math{e} logarithm of @var{number}. If @var{number} is
286292 not positive, the result is system-missing.
287293 @end deftypefn
288294
289295 @deftypefn {Function} {} LNGAMMA (@var{number})
290 Yields the base-@i{e} logarithm of the complete gamma of @var{number}.
296 Yields the base-@math{e} logarithm of the complete gamma of @var{number}.
291297 If @var{number} is a negative integer, the result is system-missing.
292298 @end deftypefn
293299
348354 @deftypefnx {Function} {} ACOS (@var{number})
349355 Takes the arccosine, in radians, of @var{number}. Results in
350356 system-missing if @var{number} is not between -1 and 1 inclusive.
351 This function is a PSPP extension.
357 This function is a @pspp{} extension.
352358 @end deftypefn
353359
354360 @cindex arcsine
380386 @deftypefn {Function} {} TAN (@var{angle})
381387 Takes the tangent of @var{angle} which should be in radians.
382388 Results in system-missing at values
383 of @var{angle} that are too close to odd multiples of pi/2.
389 of @var{angle} that are too close to odd multiples of @math{\pi/2}.
384390 Portability: none.
385391 @end deftypefn
386392
442448 Results in true if @var{value} is equal to any of the @var{set}
443449 values. Otherwise, results in false. If @var{value} is
444450 system-missing, returns system-missing. System-missing values in
445 @var{set} do not cause ANY to return system-missing.
451 @var{set} do not cause @func{ANY} to return system-missing.
446452 @end deftypefn
447453
448454 @deftypefn {Function} {} RANGE (@var{value}, @var{low}, @var{high} [, @var{low}, @var{high}]@dots{})
451457 Each @var{low} must be less than or equal to its corresponding
452458 @var{high} value. @var{low} and @var{high} must be given in pairs.
453459 If @var{value} is system-missing, returns system-missing.
454 System-missing values in @var{set} do not cause RANGE to return
460 System-missing values in @var{set} do not cause @func{RANGE} to return
455461 system-missing.
456462 @end deftypefn
457463
474480 Unlike most functions, statistical functions can return non-missing
475481 values even when some of their arguments are missing. Most
476482 statistical functions, by default, require only 1 non-missing value to
477 have a non-missing return, but CFVAR, SD, and VARIANCE require 2.
483 have a non-missing return, but @func{CFVAR}, @func{SD}, and @func {VARIANCE} require 2.
478484 These defaults can be increased (but not decreased) by appending a dot
479485 and the minimum number of valid arguments to the function name. For
480 example, @code{MEAN.3(X, Y, Z)} would only return non-missing if all
486 example, @subcmd{MEAN.3(X, Y, Z)} would only return non-missing if all
481487 of @samp{X}, @samp{Y}, and @samp{Z} were valid.
482488
483489 @cindex coefficient of variation
697703 @cindex dates
698704
699705 @cindex dates, valid
700 For compatibility, PSPP considers dates before 15 Oct 1582 invalid.
706 For compatibility, @pspp{} considers dates before 15 Oct 1582 invalid.
701707 Most time and date functions will not accept earlier dates.
702708
703709 @menu
716722
717723 @cindex time, concepts
718724 @cindex time, intervals
719 Times and dates are handled by PSPP as single numbers. A
720 @dfn{time} is an interval. PSPP measures times in seconds.
725 Times and dates are handled by @pspp{} as single numbers. A
726 @dfn{time} is an interval. @pspp{} measures times in seconds.
721727 Thus, the following intervals correspond with the numeric values given:
722728
723729 @example
730736 @cindex dates, concepts
731737 @cindex time, instants of
732738 A @dfn{date}, on the other hand, is a particular instant in the past
733 or the future. PSPP represents a date as a number of seconds since
739 or the future. @pspp{} represents a date as a number of seconds since
734740 midnight preceding 14 Oct 1582. Because midnight preceding the dates
735 given below correspond with the numeric PSPP dates given:
741 given below correspond with the numeric @pspp{} dates given:
736742
737743 @example
738744 15 Oct 1582 86,400
772778 @cindex examination, of times
773779 @cindex time, lengths of
774780
775 These functions take numeric arguments in PSPP time format and
781 These functions take numeric arguments in @pspp{} time format and
776782 give numeric results.
777783
778784 @cindex days
885891 @cindex date examination
886892
887893 @cindex arguments, of date extraction functions
888 These functions take numeric arguments in PSPP date or time
894 These functions take numeric arguments in @pspp{} date or time
889895 format and give numeric results. These names are used for arguments:
890896
891897 @table @var
892898 @item date
893 A numeric value in PSPP date format.
899 A numeric value in @pspp{} date format.
894900
895901 @item time
896 A numeric value in PSPP time format.
902 A numeric value in @pspp{} time format.
897903
898904 @item time-or-date
899 A numeric value in PSPP time or date format.
905 A numeric value in @pspp{} time or date format.
900906 @end table
901907
902908 @cindex days
10241030 times or dates in seconds to some other unit, like days or years,
10251031 before performing analysis.
10261032
1027 PSPP supplies a few functions for date arithmetic:
1033 @pspp{} supplies a few functions for date arithmetic:
10281034
10291035 @deftypefn {Function} {} DATEDIFF (@var{date2}, @var{date1}, @var{unit})
10301036 Returns the span of time from @var{date1} to @var{date2} in terms of
10971103 @cindex Julian date
10981104 @deftypefn {Function} {} YRMODA (@var{year}, @var{month}, @var{day})
10991105 @var{year} is a year, either between 0 and 99 or at least 1582.
1100 Unlike other PSPP date functions, years between 0 and 99 always
1106 Unlike other @pspp{} date functions, years between 0 and 99 always
11011107 correspond to 1900 through 1999. @var{month} is a month between 1 and
11021108 13. @var{day} is a day between 0 and 31. A @var{day} of 0 refers to
11031109 the last day of the previous month, and a @var{month} of 13 refers to
11201126 @node Statistical Distribution Functions
11211127 @subsection Statistical Distribution Functions
11221128
1123 PSPP can calculate several functions of standard statistical
1129 @pspp{} can calculate several functions of standard statistical
11241130 distributions. These functions are named systematically based on the
11251131 function and the distribution. The table below describes the
11261132 statistical distribution functions in general:
11431149 Tail probability function for @var{dist}, that is, the probability
11441150 that a random variate drawn from the distribution is greater than
11451151 @var{x}. The domain of @var{x} depends @var{dist}. The result is a
1146 probability. Only a few distributions include an SIG function.
1152 probability. Only a few distributions include an @func{SIG} function.
11471153
11481154 @item IDF.@var{dist} (@var{p}[, @var{param}@dots{}])
11491155 Inverse distribution function for @var{dist}, the value of @var{x} for
11591165 Noncentral probability density function. The result is the density of
11601166 the given noncentral distribution at @var{x}. The domain of @var{x}
11611167 depends on @var{dist}. The range is nonnegative real numbers. Only a
1162 few distributions include an NPDF function.
1168 few distributions include an @func{NPDF} function.
11631169
11641170 @item NCDF.@var{dist} (@var{x}[, @var{param}@dots{}])
11651171 Noncentral cumulative distribution function for @var{dist}, that is,
12351241 Exponential power distribution with positive scale parameter @var{a}
12361242 and nonnegative power parameter @var{b}. Constraints: @var{a} > 0,
12371243 @var{b} >= 0, @var{x} >= 0, 0 <= @var{p} <= 1. This distribution is a
1238 PSPP extension.
1244 @pspp{} extension.
12391245 @end deftypefn
12401246
12411247 @deftypefn {Function} {} PDF.F (@var{x}, @var{df1}, @var{df2})
13401346 @deftypefn {Function} {} PDF.NTAIL (@var{x}, @var{a}, @var{sigma})
13411347 @deftypefnx {Function} {} RV.NTAIL (@var{a}, @var{sigma})
13421348 Normal tail distribution with lower limit @var{a} and standard
1343 deviation @var{sigma}. This distribution is a PSPP extension.
1349 deviation @var{sigma}. This distribution is a @pspp{} extension.
13441350 Constraints: @var{a} > 0, @var{x} > @var{a}, 0 < @var{p} < 1.
13451351 @end deftypefn
13461352
13581364 @deftypefnx {Function} {} IDF.RAYLEIGH (@var{p}, @var{sigma})
13591365 @deftypefnx {Function} {} RV.RAYLEIGH (@var{sigma})
13601366 Rayleigh distribution with scale parameter @var{sigma}. This
1361 distribution is a PSPP extension. Constraints: @var{sigma} > 0,
1367 distribution is a @pspp{} extension. Constraints: @var{sigma} > 0,
13621368 @var{x} > 0.
13631369 @end deftypefn
13641370
13651371 @deftypefn {Function} {} PDF.RTAIL (@var{x}, @var{a}, @var{sigma})
13661372 @deftypefnx {Function} {} RV.RTAIL (@var{a}, @var{sigma})
13671373 Rayleigh tail distribution with lower limit @var{a} and scale
1368 parameter @var{sigma}. This distribution is a PSPP extension.
1374 parameter @var{sigma}. This distribution is a @pspp{} extension.
13691375 Constraints: @var{a} > 0, @var{sigma} > 0, @var{x} > @var{a}.
13701376 @end deftypefn
13711377
13981404 @deftypefnx {Function} {} CDF.T1G (@var{x}, @var{a}, @var{b})
13991405 @deftypefnx {Function} {} IDF.T1G (@var{p}, @var{a}, @var{b})
14001406 Type-1 Gumbel distribution with parameters @var{a} and @var{b}. This
1401 distribution is a PSPP extension. Constraints: 0 < @var{p} < 1.
1407 distribution is a @pspp{} extension. Constraints: 0 < @var{p} < 1.
14021408 @end deftypefn
14031409
14041410 @deftypefn {Function} {} PDF.T2G (@var{x}, @var{a}, @var{b})
14051411 @deftypefnx {Function} {} CDF.T2G (@var{x}, @var{a}, @var{b})
14061412 @deftypefnx {Function} {} IDF.T2G (@var{p}, @var{a}, @var{b})
14071413 Type-2 Gumbel distribution with parameters @var{a} and @var{b}. This
1408 distribution is a PSPP extension. Constraints: @var{x} > 0, 0 <
1414 distribution is a @pspp{} extension. Constraints: @var{x} > 0, 0 <
14091415 @var{p} < 1.
14101416 @end deftypefn
14111417
2121 @vindex APPLY DICTIONARY
2222
2323 @display
24 APPLY DICTIONARY FROM=@{'file-name',file_handle@}.
24 APPLY DICTIONARY FROM=@{'@var{file_name}',@var{file_handle}@}.
2525 @end display
2626
2727 @cmd{APPLY DICTIONARY} applies the variable labels, value labels,
8888
8989 @display
9090 EXPORT
91 /OUTFILE='file-name'
91 /OUTFILE='@var{file_name}'
9292 /UNSELECTED=@{RETAIN,DELETE@}
93 /DIGITS=n
94 /DROP=var_list
95 /KEEP=var_list
96 /RENAME=(src_names=target_names)@dots{}
93 /DIGITS=@var{n}
94 /DROP=@var{var_list}
95 /KEEP=@var{var_list}
96 /RENAME=(@var{src_names}=@var{target_names})@dots{}
9797 /TYPE=@{COMM,TAPE@}
9898 /MAP
9999 @end display
102102 data to a specified portable file.
103103
104104 By default, cases excluded with FILTER are written to the
105 file. These can be excluded by specifying DELETE on the UNSELECTED
105 file. These can be excluded by specifying DELETE on the @subcmd{UNSELECTED}
106106 subcommand. Specifying RETAIN makes the default explicit.
107107
108108 Portable files express real numbers in base 30. Integers are always
110110 Non-integers are, by default, expressed to the machine's maximum
111111 natural precision (approximately 15 decimal digits on many machines).
112112 If many numbers require this many digits, the portable file may
113 significantly increase in size. As an alternative, the DIGITS
113 significantly increase in size. As an alternative, the @subcmd{DIGITS}
114114 subcommand may be used to specify the number of decimal digits of
115 precision to write. DIGITS applies only to non-integers.
116
117 The OUTFILE subcommand, which is the only required subcommand, specifies
115 precision to write. @subcmd{DIGITS} applies only to non-integers.
116
117 The @subcmd{OUTFILE} subcommand, which is the only required subcommand, specifies
118118 the portable file to be written as a file name string or
119119 a file handle (@pxref{File Handles}).
120120
121 DROP, KEEP, and RENAME follow the same format as the SAVE procedure
122 (@pxref{SAVE}).
123
124 The TYPE subcommand specifies the character set for use in the
121 @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} follow the same format as the
122 @subcmd{SAVE} procedure (@pxref{SAVE}).
123
124 The @subcmd{TYPE} subcommand specifies the character set for use in the
125125 portable file. Its value is currently not used.
126126
127 The MAP subcommand is currently ignored.
127 The @subcmd{MAP} subcommand is currently ignored.
128128
129129 @cmd{EXPORT} is a procedure. It causes the active dataset to be read.
130130
134134
135135 @display
136136 GET
137 /FILE=@{'file-name',file_handle@}
138 /DROP=var_list
139 /KEEP=var_list
140 /RENAME=(src_names=target_names)@dots{}
141 /ENCODING='encoding'
137 /FILE=@{'@var{file_name}',@var{file_handle}@}
138 /DROP=@var{var_list}
139 /KEEP=@var{var_list}
140 /RENAME=(@var{src_names}=@var{target_names})@dots{}
141 /ENCODING='@var{encoding}'
142142 @end display
143143
144144 @cmd{GET} clears the current dictionary and active dataset and
145145 replaces them with the dictionary and data from a specified file.
146146
147 The FILE subcommand is the only required subcommand. Specify the system
147 The @subcmd{FILE} subcommand is the only required subcommand.
148 Specify the system
148149 file or portable file to be read as a string file name or
149150 a file handle (@pxref{File Handles}).
150151
151152 By default, all the variables in a file are read. The DROP
152153 subcommand can be used to specify a list of variables that are not to be
153 read. By contrast, the KEEP subcommand can be used to specify variable
154 that are to be read, with all other variables not read.
154 read. By contrast, the @subcmd{KEEP} subcommand can be used to specify
155 variable that are to be read, with all other variables not read.
155156
156157 Normally variables in a file retain the names that they were
157 saved under. Use the RENAME subcommand to change these names. Specify,
158 saved under. Use the @subcmd{RENAME} subcommand to change these names.
159 Specify,
158160 within parentheses, a list of variable names followed by an equals sign
159161 (@samp{=}) and the names that they should be renamed to. Multiple
160162 parenthesized groups of variable names can be included on a single
161 RENAME subcommand. Variables' names may be swapped using a RENAME
162 subcommand of the form @samp{/RENAME=(A B=B A)}.
163
164 Alternate syntax for the RENAME subcommand allows the parentheses to be
163 @subcmd{RENAME} subcommand.
164 Variables' names may be swapped using a @subcmd{RENAME}
165 subcommand of the form @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})}.
166
167 Alternate syntax for the @subcmd{RENAME} subcommand allows the parentheses to be
165168 eliminated. When this is done, only a single variable may be renamed at
166 once. For instance, @samp{/RENAME=A=B}. This alternate syntax is
169 once. For instance, @subcmd{/RENAME=@var{A}=@var{B}}. This alternate syntax is
167170 deprecated.
168171
169 DROP, KEEP, and RENAME are executed in left-to-right order.
172 @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} are executed in left-to-right order.
170173 Each may be present any number of times. @cmd{GET} never modifies a
171174 file on disk. Only the active dataset read from the file
172175 is affected by these subcommands.
173176
174 PSPP tries to automatically detect the encoding of string data in the
177 @pspp{} tries to automatically detect the encoding of string data in the
175178 file. Sometimes, however, this does not work well encoding,
176 especially for files written by old versions of SPSS or PSPP. Specify
177 the ENCODING subcommand with an IANA character set name as its string
178 argument to override the default. The ENCODING subcommand is a PSPP
179 especially for files written by old versions of SPSS or @pspp{}. Specify
180 the @subcmd{ENCODING} subcommand with an @acronym{IANA} character set name as its string
181 argument to override the default. The @subcmd{ENCODING} subcommand is a @pspp{}
179182 extension.
180183
181184 @cmd{GET} does not cause the data to be read, only the dictionary. The data
182185 is read later, when a procedure is executed.
183186
184 Use of @cmd{GET} to read a portable file is a PSPP extension.
187 Use of @cmd{GET} to read a portable file is a @pspp{} extension.
185188
186189 @node GET DATA
187190 @section GET DATA
198201 the current dictionary and active dataset are replaced with variables
199202 and data read from the specified source.
200203
201 The TYPE subcommand is mandatory and must be the first subcommand
204 The @subcmd{TYPE} subcommand is mandatory and must be the first subcommand
202205 specified. It determines the type of the file or source to read.
203 PSPP currently supports the following file types:
206 @pspp{} currently supports the following file types:
204207
205208 @table @asis
206209 @item GNM
230233
231234 @display
232235 GET DATA /TYPE=@{GNM, ODS@}
233 /FILE=@{'file-name'@}
234 /SHEET=@{NAME 'sheet-name', INDEX n@}
235 /CELLRANGE=@{RANGE 'range', FULL@}
236 /FILE=@{'@var{file_name}'@}
237 /SHEET=@{NAME '@var{sheet_name}', INDEX @var{n}@}
238 /CELLRANGE=@{RANGE '@var{range}', FULL@}
236239 /READNAMES=@{ON, OFF@}
237 /ASSUMEDVARWIDTH=n.
240 /ASSUMEDVARWIDTH=@var{n}.
238241 @end display
239242
240243 @cindex Gnumeric
244247 Gnumeric spreadsheets (@url{http://gnumeric.org}), and spreadsheets
245248 in OpenDocument format
246249 (@url{http://libreplanet.org/wiki/Group:OpenDocument/Software})
247 can be read using the GET DATA command.
248 Use the TYPE subcommand to indicate the file's format.
250 can be read using the @cmd{GET DATA} command.
251 Use the @subcmd{TYPE} subcommand to indicate the file's format.
249252 /TYPE=GNM indicates Gnumeric files,
250253 /TYPE=ODS indicates OpenDocument.
251 The FILE subcommand is mandatory.
254 The @subcmd{FILE} subcommand is mandatory.
252255 Use it to specify the name file to be read.
253256 All other subcommands are optional.
254257
256259 cell containing the first datum for the variable.
257260 If this cell is of string (text) format, then the width of the variable is
258261 determined from the length of the string it contains, unless the
259 ASSUMEDVARWIDTH subcommand is given.
260
261 The SHEET subcommand specifies the sheet within the spreadsheet file to read.
262 There are two forms of the SHEET subcommand.
262 @subcmd{ASSUMEDVARWIDTH} subcommand is given.
263
264 The @subcmd{SHEET} subcommand specifies the sheet within the spreadsheet file to read.
265 There are two forms of the @subcmd{SHEET} subcommand.
263266 In the first form,
264 @samp{/SHEET=name @var{sheet-name}}, the string @var{sheet-name} is the
267 @subcmd{/SHEET=name @var{sheet_name}}, the string @var{sheet_name} is the
265268 name of the sheet to read.
266 In the second form, @samp{/SHEET=index @var{idx}}, @var{idx} is a
269 In the second form, @subcmd{/SHEET=index @var{idx}}, @var{idx} is a
267270 integer which is the index of the sheet to read.
268271 The first sheet has the index 1.
269 If the SHEET subcommand is omitted, then the command will read the
272 If the @subcmd{SHEET} subcommand is omitted, then the command will read the
270273 first sheet in the file.
271274
272 The CELLRANGE subcommand specifies the range of cells within the sheet to read.
273 If the subcommand is given as @samp{/CELLRANGE=FULL}, then the entire
275 The @subcmd{CELLRANGE} subcommand specifies the range of cells within the sheet to read.
276 If the subcommand is given as @subcmd{/CELLRANGE=FULL}, then the entire
274277 sheet is read.
275278 To read only part of a sheet, use the form
276 @samp{/CELLRANGE=range '@var{top-left-cell}:@var{bottom-right-cell}'}.
277 For example, the subcommand @samp{/CELLRANGE=range 'C3:P19'} reads
279 @subcmd{/CELLRANGE=range '@var{top_left_cell}:@var{bottom_right_cell}'}.
280 For example, the subcommand @subcmd{/CELLRANGE=range 'C3:P19'} reads
278281 columns C--P, and rows 3--19 inclusive.
279 If no CELLRANGE subcommand is given, then the entire sheet is read.
280
281 If @samp{/READNAMES=ON} is specified, then the contents of cells of
282 If no @subcmd{CELLRANGE} subcommand is given, then the entire sheet is read.
283
284 If @subcmd{/READNAMES=ON} is specified, then the contents of cells of
282285 the first row are used as the names of the variables in which to store
283286 the data from subsequent rows. This is the default.
284 If @samp{/READNAMES=OFF} is
287 If @subcmd{/READNAMES=OFF} is
285288 used, then the variables receive automatically assigned names.
286289
287 The ASSUMEDVARWIDTH subcommand specifies the maximum width of string
290 The @subcmd{ASSUMEDVARWIDTH} subcommand specifies the maximum width of string
288291 variables read from the file.
289292 If omitted, the default value is determined from the length of the
290293 string in the first spreadsheet cell for each variable.
295298
296299 @display
297300 GET DATA /TYPE=PSQL
298 /CONNECT=@{connection info@}
299 /SQL=@{query@}
300 [/ASSUMEDVARWIDTH=n]
301 /CONNECT=@{@var{connection info}@}
302 /SQL=@{@var{query}@}
303 [/ASSUMEDVARWIDTH=@var{w}]
301304 [/UNENCRYPTED]
302 [/BSIZE=n].
305 [/BSIZE=@var{n}].
303306 @end display
304307
305308 @cindex postgres
310313 Variables are automatically created based on the table column names
311314 or the names specified in the SQL query.
312315 Postgres data types of high precision, will loose precision when
313 imported into PSPP.
314 Not all the postgres data types are able to be represented in PSPP.
316 imported into @pspp{}.
317 Not all the postgres data types are able to be represented in @pspp{}.
315318 If a datum cannot be represented a warning will be issued and that
316319 datum will be set to SYSMIS.
317320
318 The CONNECT subcommand is mandatory.
321 The @subcmd{CONNECT} subcommand is mandatory.
319322 It is a string specifying the parameters of the database server from
320323 which the data should be fetched.
321324 The format of the string is given in the postgres manual
322325 @url{http://www.postgresql.org/docs/8.0/static/libpq.html#LIBPQ-CONNECT}.
323326
324 The SQL subcommand is mandatory.
327 The @subcmd{SQL} subcommand is mandatory.
325328 It must be a valid SQL string to retrieve data from the database.
326329
327 The ASSUMEDVARWIDTH subcommand specifies the maximum width of string
330 The @subcmd{ASSUMEDVARWIDTH} subcommand specifies the maximum width of string
328331 variables read from the database.
329332 If omitted, the default value is determined from the length of the
330333 string in the first value read for each variable.
331334
332 The UNENCRYPTED subcommand allows data to be retrieved over an insecure
335 The @subcmd{UNENCRYPTED} subcommand allows data to be retrieved over an insecure
333336 connection.
334 If the connection is not encrypted, and the UNENCRYPTED subcommand is not
335 given, then an error will occur.
337 If the connection is not encrypted, and the @subcmd{UNENCRYPTED} subcommand is
338 not given, then an error will occur.
336339 Whether or not the connection is
337340 encrypted depends upon the underlying psql library and the
338341 capabilities of the database server.
339342
340 The BSIZE subcommand serves only to optimise the speed of data transfer.
343 The @subcmd{BSIZE} subcommand serves only to optimise the speed of data transfer.
341344 It specifies an upper limit on
342345 number of cases to fetch from the database at once.
343346 The default value is 4096.
344347 If your SQL statement fetches a large number of cases but only a small number of
345348 variables, then the data transfer may be faster if you increase this value.
346349 Conversely, if the number of variables is large, or if the machine on which
347 PSPP is running has only a
350 @pspp{} is running has only a
348351 small amount of memory, then a smaller value will be better.
349352
350353
361364
362365 @display
363366 GET DATA /TYPE=TXT
364 /FILE=@{'file-name',file_handle@}
367 /FILE=@{'@var{file_name}',@var{file_handle}@}
368 [ENCODING='@var{encoding}']
365369 [/ARRANGEMENT=@{DELIMITED,FIXED@}]
366 [/FIRSTCASE=@{first_case@}]
367 [/IMPORTCASE=@{ALL,FIRST max_cases,PERCENT percent@}]
370 [/FIRSTCASE=@{@var{first_case}@}]
371 [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}]
368372 @dots{}additional subcommands depending on ARRANGEMENT@dots{}
369373 @end display
370374
373377 When TYPE=TXT is specified, GET DATA reads data in a delimited or
374378 fixed columnar format, much like DATA LIST (@pxref{DATA LIST}).
375379
376 The FILE subcommand is mandatory. Specify the file to be read as
377 a string file name or (for textual data
378 only) a file handle (@pxref{File Handles}).
379
380 The ARRANGEMENT subcommand determines the file's basic format.
380 The @subcmd{FILE} subcommand is mandatory. Specify the file to be read as
381 a string file name or (for textual data only) a
382 file handle (@pxref{File Handles}).
383
384 The @subcmd{ENCODING} subcommand specifies the character encoding of
385 the file to be read. @xref{INSERT}, for information on supported
386 encodings.
387
388 The @subcmd{ARRANGEMENT} subcommand determines the file's basic format.
381389 DELIMITED, the default setting, specifies that fields in the input
382390 data are separated by spaces, tabs, or other user-specified
383391 delimiters. FIXED specifies that fields in the input data appear at
384392 particular fixed column positions within records of a case.
385393
386394 By default, cases are read from the input file starting from the first
387 line. To skip lines at the beginning of an input file, set FIRSTCASE
395 line. To skip lines at the beginning of an input file, set @subcmd{FIRSTCASE}
388396 to the number of the first line to read: 2 to skip the first line, 3
389397 to skip the first two lines, and so on.
390398
391 IMPORTCASE can be used to limit the number of cases read from the
399 @subcmd{IMPORTCASE} can be used to limit the number of cases read from the
392400 input file. With the default setting, ALL, all cases in the file are
393 read. Specify FIRST @i{max_cases} to read at most @i{max_cases} cases
394 from the file. Use PERCENT @i{percent} to read only @i{percent}
401 read. Specify FIRST @var{max_cases} to read at most @var{max_cases} cases
402 from the file. Use @subcmd{PERCENT @var{percent}} to read only @var{percent}
395403 percent, approximately, of the cases contained in the file. (The
396404 percentage is approximate, because there is no way to accurately count
397405 the number of cases in the file without reading the entire file. The
398406 number of cases in some kinds of unusual files cannot be estimated;
399 PSPP will read all cases in such files.)
400
401 FIRSTCASE and IMPORTCASE may be used with delimited and fixed-format
407 @pspp{} will read all cases in such files.)
408
409 @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE} may be used with delimited and fixed-format
402410 data. The remaining subcommands, which apply only to one of the two file
403411 arrangements, are described below.
404412
412420
413421 @display
414422 GET DATA /TYPE=TXT
415 /FILE=@{'file-name',file_handle@}
423 /FILE=@{'@var{file_name}',@var{file_handle}@}
416424 [/ARRANGEMENT=@{DELIMITED,FIXED@}]
417 [/FIRSTCASE=@{first_case@}]
418 [/IMPORTCASE=@{ALL,FIRST max_cases,PERCENT percent@}]
419
420 /DELIMITERS="delimiters"
421 [/QUALIFIER="quotes" [/ESCAPE]]
422 [/DELCASE=@{LINE,VARIABLES n_variables@}]
423 /VARIABLES=del_var [del_var]@dots{}
424 where each del_var takes the form:
425 [/FIRSTCASE=@{@var{first_case}@}]
426 [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}]
427
428 /DELIMITERS="@var{delimiters}"
429 [/QUALIFIER="@var{quotes}" [/ESCAPE]]
430 [/DELCASE=@{LINE,VARIABLES @var{n_variables}@}]
431 /VARIABLES=@var{del_var1} [@var{del_var2}]@dots{}
432 where each @var{del_var} takes the form:
425433 variable format
426434 @end display
427435
431439 similar to those of DATA LIST FREE (@pxref{DATA LIST FREE}), with a
432440 few enhancements.
433441
434 The required FILE subcommand and optional FIRSTCASE and IMPORTCASE
442 The required @subcmd{FILE} subcommand and optional @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE}
435443 subcommands are described above (@pxref{GET DATA /TYPE=TXT}).
436444
437 DELIMITERS, which is required, specifies the set of characters that
445 @subcmd{DELIMITERS}, which is required, specifies the set of characters that
438446 may separate fields. Each character in the string specified on
439 DELIMITERS separates one field from the next. The end of a line also
440 separates fields, regardless of DELIMITERS. Two consecutive
447 @subcmd{DELIMITERS} separates one field from the next. The end of a line also
448 separates fields, regardless of @subcmd{DELIMITERS}. Two consecutive
441449 delimiters in the input yield an empty field, as does a delimiter at
442450 the end of a line. A space character as a delimiter is an exception:
443451 consecutive spaces do not yield an empty field and neither does any
444452 number of spaces at the end of a line.
445453
446454 To use a tab as a delimiter, specify @samp{\t} at the beginning of the
447 DELIMITERS string. To use a backslash as a delimiter, specify
455 @subcmd{DELIMITERS} string. To use a backslash as a delimiter, specify
448456 @samp{\\} as the first delimiter or, if a tab should also be a
449457 delimiter, immediately following @samp{\t}. To read a data file in
450458 which each field appears on a separate line, specify the empty string
451 for DELIMITERS.
452
453 The optional QUALIFIER subcommand names one or more characters that
459 for @subcmd{DELIMITERS}.
460
461 The optional @subcmd{QUALIFIER} subcommand names one or more characters that
454462 can be used to quote values within fields in the input. A field that
455463 begins with one of the specified quote characters ends at the next
456464 matching quote. Intervening delimiters become part of the field,
457465 instead of terminating it. The ability to specify more than one quote
458 character is a PSPP extension.
459
460 By default, a character specified on QUALIFIER cannot itself be
466 character is a @pspp{} extension.
467
468 By default, a character specified on @subcmd{QUALIFIER} cannot itself be
461469 embedded within a field that it quotes, because the quote character
462470 always terminates the quoted field. With ESCAPE, however, a doubled
463471 quote character within a quoted field inserts a single instance of the
464472 quote into the field. For example, if @samp{'} is specified on
465 QUALIFIER, then without ESCAPE @code{'a''b'} specifies a pair of
473 @subcmd{QUALIFIER}, then without ESCAPE @code{'a''b'} specifies a pair of
466474 fields that contain @samp{a} and @samp{b}, but with ESCAPE it
467 specifies a single field that contains @samp{a'b}. ESCAPE is a PSPP
475 specifies a single field that contains @samp{a'b}. ESCAPE is a @pspp{}
468476 extension.
469477
470 The DELCASE subcommand controls how data may be broken across lines in
478 The @subcmd{DELCASE} subcommand controls how data may be broken across lines in
471479 the data file. With LINE, the default setting, each line must contain
472480 all the data for exactly one case. For additional flexibility, to
473481 allow a single case to be split among lines or multiple cases to be
474482 contained on a single line, specify VARIABLES @i{n_variables}, where
475483 @i{n_variables} is the number of variables per case.
476484
477 The VARIABLES subcommand is required and must be the last subcommand.
485 The @subcmd{VARIABLES} subcommand is required and must be the last subcommand.
478486 Specify the name of each variable and its input format (@pxref{Input
479487 and Output Formats}) in the order they should be read from the input
480488 file.
567575 @node GET DATA /TYPE=TXT /ARRANGEMENT=FIXED
568576 @subsubsection Reading Fixed Columnar Data
569577
578 @c (modify-syntax-entry ?_ "w")
579 @c (modify-syntax-entry ?' "'")
580 @c (modify-syntax-entry ?@ "'")
581
570582 @display
571583 GET DATA /TYPE=TXT
572 /FILE=@{'file-name',file_handle@}
584 /FILE=@{'file_name',@var{file_handle}@}
573585 [/ARRANGEMENT=@{DELIMITED,FIXED@}]
574 [/FIRSTCASE=@{first_case@}]
575 [/IMPORTCASE=@{ALL,FIRST max_cases,PERCENT percent@}]
576
577 [/FIXCASE=n]
578 /VARIABLES fixed_var [fixed_var]@dots{}
579 [/rec# fixed_var [fixed_var]@dots{}]@dots{}
580 where each fixed_var takes the form:
581 variable start-end format
582 @end display
583
584 The GET DATA command with TYPE=TXT and ARRANGEMENT=FIXED reads input
586 [/FIRSTCASE=@{@var{first_case}@}]
587 [/IMPORTCASE=@{ALL,FIRST @var{max_cases},PERCENT @var{percent}@}]
588
589 [/FIXCASE=@var{n}]
590 /VARIABLES @var{fixed_var} [@var{fixed_var}]@dots{}
591 [/rec# @var{fixed_var} [@var{fixed_var}]@dots{}]@dots{}
592 where each @var{fixed_var} takes the form:
593 @var{variable} @var{start}-@var{end} @var{format}
594 @end display
595
596 The @cmd{GET DATA} command with TYPE=TXT and ARRANGEMENT=FIXED reads input
585597 data from text files in fixed format, where each field is located in
586598 particular fixed column positions within records of a case. Its
587599 capabilities are similar to those of DATA LIST FIXED (@pxref{DATA LIST
588600 FIXED}), with a few enhancements.
589601
590 The required FILE subcommand and optional FIRSTCASE and IMPORTCASE
602 The required @subcmd{FILE} subcommand and optional @subcmd{FIRSTCASE} and @subcmd{IMPORTCASE}
591603 subcommands are described above (@pxref{GET DATA /TYPE=TXT}).
592604
593 The optional FIXCASE subcommand may be used to specify the positive
605 The optional @subcmd{FIXCASE} subcommand may be used to specify the positive
594606 integer number of input lines that make up each case. The default
595607 value is 1.
596608
597 The VARIABLES subcommand, which is required, specifies the positions
609 The @subcmd{VARIABLES} subcommand, which is required, specifies the positions
598610 at which each variable can be found. For each variable, specify its
599611 name, followed by its start and end column separated by @samp{-}
600612 (e.g.@: @samp{0-9}), followed by an input format type (e.g.@:
638650
639651 @display
640652 IMPORT
641 /FILE='file-name'
653 /FILE='@var{file_name}'
642654 /TYPE=@{COMM,TAPE@}
643 /DROP=var_list
644 /KEEP=var_list
645 /RENAME=(src_names=target_names)@dots{}
655 /DROP=@var{var_list}
656 /KEEP=@var{var_list}
657 /RENAME=(@var{src_names}=@var{target_names})@dots{}
646658 @end display
647659
648660 The @cmd{IMPORT} transformation clears the active dataset dictionary and
650662 replaces them with a dictionary and data from a system file or
651663 portable file.
652664
653 The FILE subcommand, which is the only required subcommand, specifies
665 The @subcmd{FILE} subcommand, which is the only required subcommand, specifies
654666 the portable file to be read as a file name string or a file handle
655667 (@pxref{File Handles}).
656668
657 The TYPE subcommand is currently not used.
658
659 DROP, KEEP, and RENAME follow the syntax used by @cmd{GET} (@pxref{GET}).
660
661 @cmd{IMPORT} does not cause the data to be read, only the dictionary. The
669 The @subcmd{TYPE} subcommand is currently not used.
670
671 @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} follow the syntax used by @cmd{GET} (@pxref{GET}).
672
673 @cmd{IMPORT} does not cause the data to be read; only the dictionary. The
662674 data is read later, when a procedure is executed.
663675
664 Use of @cmd{IMPORT} to read a system file is a PSPP extension.
676 Use of @cmd{IMPORT} to read a system file is a @pspp{} extension.
665677
666678 @node SAVE
667679 @section SAVE
669681
670682 @display
671683 SAVE
672 /OUTFILE=@{'file-name',file_handle@}
684 /OUTFILE=@{'@var{file_name}',@var{file_handle}@}
673685 /UNSELECTED=@{RETAIN,DELETE@}
674686 /@{COMPRESSED,UNCOMPRESSED@}
675687 /PERMISSIONS=@{WRITEABLE,READONLY@}
676 /DROP=var_list
677 /KEEP=var_list
678 /VERSION=version
679 /RENAME=(src_names=target_names)@dots{}
688 /DROP=@var{var_list}
689 /KEEP=@var{var_list}
690 /VERSION=@var{version}
691 /RENAME=(@var{src_names}=@var{target_names})@dots{}
680692 /NAMES
681693 /MAP
682694 @end display
690702 (@pxref{File Handles}).
691703
692704 By default, cases excluded with FILTER are written to the system file.
693 These can be excluded by specifying DELETE on the UNSELECTED
694 subcommand. Specifying RETAIN makes the default explicit.
695
696 The COMPRESS and UNCOMPRESS subcommand determine whether the saved
697 system file is compressed. By default, system files are compressed.
705 These can be excluded by specifying @subcmd{DELETE} on the @subcmd{UNSELECTED}
706 subcommand. Specifying @subcmd{RETAIN} makes the default explicit.
707
708 The @subcmd{COMPRESS} and @subcmd{UNCOMPRESS} subcommand determine whether
709 the saved system file is compressed. By default, system files are compressed.
698710 This default can be changed with the SET command (@pxref{SET}).
699711
700 The PERMISSIONS subcommand specifies permissions for the new system
712 The @subcmd{PERMISSIONS} subcommand specifies permissions for the new system
701713 file. WRITEABLE, the default, creates the file with read and write
702714 permission. READONLY creates the file for read-only access.
703715
704716 By default, all the variables in the active dataset dictionary are written
705 to the system file. The DROP subcommand can be used to specify a list
717 to the system file. The @subcmd{DROP} subcommand can be used to specify a list
706718 of variables not to be written. In contrast, KEEP specifies variables
707719 to be written, with all variables not specified not written.
708720
709721 Normally variables are saved to a system file under the same names they
710 have in the active dataset. Use the RENAME subcommand to change these names.
722 have in the active dataset. Use the @subcmd{RENAME} subcommand to change these names.
711723 Specify, within parentheses, a list of variable names followed by an
712724 equals sign (@samp{=}) and the names that they should be renamed to.
713725 Multiple parenthesized groups of variable names can be included on a
714 single RENAME subcommand. Variables' names may be swapped using a
715 RENAME subcommand of the form @samp{/RENAME=(A B=B A)}.
716
717 Alternate syntax for the RENAME subcommand allows the parentheses to be
726 single @subcmd{RENAME} subcommand. Variables' names may be swapped using a
727 @subcmd{RENAME} subcommand of the
728 form @subcmd{/RENAME=(@var{A} @var{B}=@var{B} @var{A})}.
729
730 Alternate syntax for the @subcmd{RENAME} subcommand allows the parentheses to be
718731 eliminated. When this is done, only a single variable may be renamed at
719 once. For instance, @samp{/RENAME=A=B}. This alternate syntax is
732 once. For instance, @subcmd{/RENAME=@var{A}=@var{B}}. This alternate syntax is
720733 deprecated.
721734
722 DROP, KEEP, and RENAME are performed in left-to-right order. They
735 @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} are performed in
736 left-to-right order. They
723737 each may be present any number of times. @cmd{SAVE} never modifies
724 the active dataset. DROP, KEEP, and RENAME only affect the system file
725 written to disk.
726
727 The VERSION subcommand specifies the version of the file format. Valid
738 the active dataset. @subcmd{DROP}, @subcmd{KEEP}, and @subcmd{RENAME} only
739 affect the system file written to disk.
740
741 The @subcmd{VERSION} subcommand specifies the version of the file format. Valid
728742 versions are 2 and 3. The default version is 3. In version 2 system
729743 files, variable names longer than 8 bytes will be truncated. The two
730744 versions are otherwise identical.
731745
732 The NAMES and MAP subcommands are currently ignored.
746 The @subcmd{NAMES} and @subcmd{MAP} subcommands are currently ignored.
733747
734748 @cmd{SAVE} causes the data to be read. It is a procedure.
735749
739753
740754 @display
741755 SAVE TRANSLATE
742 /OUTFILE=@{'file-name',file_handle@}
756 /OUTFILE=@{'@var{file_name}',@var{file_handle}@}
743757 /TYPE=@{CSV,TAB@}
744758 [/REPLACE]
745759 [/MISSING=@{IGNORE,RECODE@}]
746760
747 [/DROP=var_list]
748 [/KEEP=var_list]
749 [/RENAME=(src_names=target_names)@dots{}]
761 [/DROP=@var{var_list}]
762 [/KEEP=@var{var_list}]
763 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
750764 [/UNSELECTED=@{RETAIN,DELETE@}]
751765 [/MAP]
752766
756770 The @cmd{SAVE TRANSLATE} command is used to save data into various
757771 formats understood by other applications.
758772
759 The OUTFILE and TYPE subcommands are mandatory. OUTFILE specifies the
760 file to be written, as a string file name or a file handle
761 (@pxref{File Handles}). TYPE determines the type of the file or
773 The @subcmd{OUTFILE} and @subcmd{TYPE} subcommands are mandatory.
774 @subcmd{OUTFILE} specifies the file to be written, as a string file name or a file handle
775 (@pxref{File Handles}). @subcmd{TYPE} determines the type of the file or
762776 source to read. It must be one of the following:
763777
764778 @table @asis
769783 Tab-delimited format.
770784 @end table
771785
772 By default, SAVE TRANSLATE will not overwrite an existing file. Use
773 REPLACE to force an existing file to be overwritten.
774
775 With MISSING=IGNORE, the default, SAVE TRANSLATE treats user-missing
786 By default, @cmd{SAVE TRANSLATE} will not overwrite an existing file. Use
787 @subcmd{REPLACE} to force an existing file to be overwritten.
788
789 With MISSING=IGNORE, the default, @subcmd{SAVE TRANSLATE} treats user-missing
776790 values as if they were not missing. Specify MISSING=RECODE to output
777791 numeric user-missing values like system-missing values and string
778792 user-missing values as all spaces.
779793
780794 By default, all the variables in the active dataset dictionary are saved
781 to the system file, but DROP or KEEP can select a subset of variable
782 to save. The RENAME subcommand can also be used to change the names
783 under which variables are saved. UNSELECTED determines whether cases
784 filtered out by the FILTER command are written to the output file.
795 to the system file, but @subcmd{DROP} or @subcmd{KEEP} can select a subset of variable
796 to save. The @subcmd{RENAME} subcommand can also be used to change the names
797 under which variables are saved. @subcmd{UNSELECTED} determines whether cases
798 filtered out by the @cmd{FILTER} command are written to the output file.
785799 These subcommands have the same syntax and meaning as on the
786800 @cmd{SAVE} command (@pxref{SAVE}).
787801
799813
800814 @display
801815 SAVE TRANSLATE
802 /OUTFILE=@{'file-name',file_handle@}
816 /OUTFILE=@{'@var{file_name}',@var{file_handle}@}
803817 /TYPE=CSV
804818 [/REPLACE]
805819 [/MISSING=@{IGNORE,RECODE@}]
806820
807 [/DROP=var_list]
808 [/KEEP=var_list]
809 [/RENAME=(src_names=target_names)@dots{}]
821 [/DROP=@var{var_list}]
822 [/KEEP=@var{var_list}]
823 [/RENAME=(@var{src_names}=@var{target_names})@dots{}]
810824 [/UNSELECTED=@{RETAIN,DELETE@}]
811825
812826 [/FIELDNAMES]
813827 [/CELLS=@{VALUES,LABELS@}]
814 [/TEXTOPTIONS DELIMITER='delimiter']
815 [/TEXTOPTIONS QUALIFIER='qualifier']
828 [/TEXTOPTIONS DELIMITER='@var{delimiter}']
829 [/TEXTOPTIONS QUALIFIER='@var{qualifier}']
816830 [/TEXTOPTIONS DECIMAL=@{DOT,COMMA@}]
817831 [/TEXTOPTIONS FORMAT=@{PLAIN,VARIABLE@}]
818832 @end display
872886 @vindex SYSFILE INFO
873887
874888 @display
875 SYSFILE INFO FILE='file-name'.
889 SYSFILE INFO FILE='@var{file_name}'.
876890 @end display
877891
878892 @cmd{SYSFILE INFO} reads the dictionary in a system file and
889903
890904 @display
891905 XEXPORT
892 /OUTFILE='file-name'
893 /DIGITS=n
894 /DROP=var_list
895 /KEEP=var_list
896 /RENAME=(src_names=target_names)@dots{}
906 /OUTFILE='@var{file_name}'
907 /DIGITS=@var{n}
908 /DROP=@var{var_list}
909 /KEEP=@var{var_list}
910 /RENAME=(@var{src_names}=@var{target_names})@dots{}
897911 /TYPE=@{COMM,TAPE@}
898912 /MAP
899913 @end display
901915 The @cmd{EXPORT} transformation writes the active dataset dictionary and
902916 data to a specified portable file.
903917
904 This transformation is a PSPP extension.
918 This transformation is a @pspp{} extension.
905919
906920 It is similar to the @cmd{EXPORT} procedure, with two differences:
907921
911925 the data is read by a procedure or procedure-like command.
912926
913927 @item
914 @cmd{XEXPORT} does not support the UNSELECTED subcommand.
928 @cmd{XEXPORT} does not support the @subcmd{UNSELECTED} subcommand.
915929 @end itemize
916930
917931 @xref{EXPORT}, for more information.
922936
923937 @display
924938 XSAVE
925 /OUTFILE='file-name'
939 /OUTFILE='@var{file_name}'
926940 /@{COMPRESSED,UNCOMPRESSED@}
927941 /PERMISSIONS=@{WRITEABLE,READONLY@}
928 /DROP=var_list
929 /KEEP=var_list
930 /VERSION=version
931 /RENAME=(src_names=target_names)@dots{}
942 /DROP=@var{var_list}
943 /KEEP=@var{var_list}
944 /VERSION=@var{version}
945 /RENAME=(@var{src_names}=@var{target_names})@dots{}
932946 /NAMES
933947 /MAP
934948 @end display
943957 the data is read by a procedure or procedure-like command.
944958
945959 @item
946 @cmd{XSAVE} does not support the UNSELECTED subcommand.
960 @cmd{XSAVE} does not support the @subcmd{UNSELECTED} subcommand.
947961 @end itemize
948962
949963 @xref{SAVE}, for more information.
0
01 @node Conditionals and Looping
12 @chapter Conditional and Looping Constructs
23 @cindex conditionals
45 @cindex flow of control
56 @cindex control flow
67
7 This chapter documents PSPP commands used for conditional execution,
8 This chapter documents @pspp{} commands used for conditional execution,
89 looping, and flow of control.
910
1011 @menu
111112 would create them, e.g.@: on a @cmd{NUMERIC} or @cmd{STRING} command
112113 or on the left side of a @cmd{COMPUTE} assignment.
113114
114 Any command may appear within DO REPEAT, including nested DO REPEAT
115 commands. If @cmd{INCLUDE} or @cmd{INSERT} appears within DO REPEAT,
115 Any command may appear within @subcmd{DO REPEAT}, including nested @subcmd{DO REPEAT}
116 commands. If @cmd{INCLUDE} or @cmd{INSERT} appears within @subcmd{DO REPEAT},
116117 the substitutions do not apply to the included file.
117118
118 If PRINT is specified on @cmd{END REPEAT}, the commands after substitutions
119 If @subcmd{PRINT} is specified on @cmd{END REPEAT}, the commands after substitutions
119120 are made are printed to the listing file, prefixed by a plus sign
120121 (@samp{+}).
121122
124125 @vindex LOOP
125126
126127 @display
127 LOOP [index_var=start TO end [BY incr]] [IF condition].
128 LOOP [@var{index_var}=@var{start} TO @var{end} [BY @var{incr}]] [IF @var{condition}].
128129 @dots{}
129 END LOOP [IF condition].
130 END LOOP [IF @var{condition}].
130131 @end display
131132
132133 @cmd{LOOP} iterates a group of commands. A number of
133134 termination options are offered.
134135
135136 Specify index_var to make that variable count from one value to
136 another by a particular increment. index_var must be a pre-existing
137 numeric variable. start, end, and incr are numeric expressions
137 another by a particular increment. @var{index_var} must be a pre-existing
138 numeric variable. @var{start}, @var{end}, and @var{incr} are numeric expressions
138139 (@pxref{Expressions}.)
139140
140 During the first iteration, index_var is set to the value of start.
141 During each successive iteration, index_var is increased by the value of
142 incr. If end > start, then the loop terminates when index_var > end;
143 otherwise it terminates when index_var < end. If incr is not specified
141 During the first iteration, @var{index_var} is set to the value of @var{start}.
142 During each successive iteration, @var{index_var} is increased by the value of
143 @var{incr}. If @var{end} > @var{start}, then the loop terminates
144 when @var{index_var} > @var{end};
145 otherwise it terminates when @var{index_var} < @var{end}. If @var{incr} is not specified
144146 then it defaults to +1 or -1 as appropriate.
145147
146 If end > start and incr < 0, or if end < start and incr > 0, then the
147 loop is never executed. index_var is nevertheless set to the value of
148 If @var{end} > @var{start} and @var{incr} < 0, or if @var{end} < @var{start} and
149 @var{incr} > 0, then the
150 loop is never executed. @var{index_var} is nevertheless set to the value of
148151 start.
149152
150 Modifying index_var within the loop is allowed, but it has no effect on
151 the value of index_var in the next iteration.
153 Modifying @var{index_var} within the loop is allowed, but it has no effect on
154 the value of @var{index_var} in the next iteration.
152155
153156 Specify a boolean expression for the condition on @cmd{LOOP} to
154157 cause the loop to be executed only if the condition is true. If the
167170 condition on @cmd{END LOOP} will always execute at least once.
168171
169172 If neither the index clause nor either condition clause is
170 present, then the loop is executed MXLOOPS (@pxref{SET}) times.
171 The default MXLOOPS is 40.
173 present, then the loop is executed @var{max_loops} (@pxref{SET}) times.
174 The default value of @var{max_loops} is 40.
172175
173176 @cmd{BREAK} also terminates @cmd{LOOP} execution (@pxref{BREAK}).
174177
1414 my ($command, $description)
1515 = /^\s*UNIMPL_CMD\s*\(\s*"([^"]*)"\s*,\s*"([^"]*)"\)\s*$/
1616 or next;
17 print "\@item $command\n$description\n\n";
17 print "\@item \@cmd{$command}\n$description\n\n";
1818 }
1919 print "\@end table\n";
2020
00 @node Installation
1 @appendix Installing PSPP
1 @appendix Installing @pspp{}
22 @cindex installation
3 @cindex PSPP, installing
3 @cindex @pspp{}, installing
44
55 @cindex GNU C compiler
66 @cindex gcc
77 @cindex compiler, recommended
88 @cindex compiler, gcc
9 PSPP is written in ISO C and primarily targeted at UNIX-like
10 environments. To install PSPP under a UNIX-like operating system,
9 @pspp{} is written in ISO C and primarily targeted at UNIX-like
10 environments. To install @pspp{} under a UNIX-like operating system,
1111 follow the steps below.
1212
1313 @enumerate
1414 @item
15 @code{cd} to the directory containing the PSPP source.
15 @code{cd} to the directory containing the @pspp{} source.
1616
1717 @cindex configure, GNU
1818 @cindex GNU configure
3535
3636 @cindex self-tests, running
3737 @item
38 Type @samp{make check} to run self-tests on the compiled PSPP package.
38 Type @samp{make check} to run self-tests on the compiled @pspp{} package.
3939
4040 @cindex installation
41 @cindex PSPP, installing
41 @cindex @pspp{}, installing
4242 @cindex @file{/usr/local/share/pspp/}
4343 @cindex @file{/usr/local/bin/}
4444 @cindex @file{/usr/local/info/}
4545 @cindex documentation, installing
4646 @item
4747 Become the superuser and type @samp{make install} to install the
48 PSPP binaries, by default in @file{/usr/local/bin/}. The
48 @pspp{} binaries, by default in @file{/usr/local/bin/}. The
4949 directory @file{/usr/local/share/pspp/} is created and populated with
50 files needed by PSPP at runtime. This step will also cause the
51 PSPP documentation to be installed in @file{/usr/local/info/},
50 files needed by @pspp{} at runtime. This step will also cause the
51 @pspp{} documentation to be installed in @file{/usr/local/info/},
5252 but only if that directory already exists.
5353
5454 @item
55 (optional) Type @samp{make clean} to delete the PSPP binaries
55 (optional) Type @samp{make clean} to delete the @pspp{} binaries
5656 from the source tree.
5757 @end enumerate
11 @chapter Introduction
22 @cindex introduction
33
4 @cindex PSPP language
5 @cindex language, PSPP
6 PSPP is a tool for statistical analysis of sampled data. It reads a
4 @cindex @pspp{} language
5 @cindex language, @pspp{}
6 @pspp{} is a tool for statistical analysis of sampled data. It reads a
77 syntax file and a data file, analyzes the data, and writes the results
88 to a listing file or to standard output.
99
10 The language accepted by PSPP is similar to those accepted by SPSS
11 statistical products. The details of PSPP's language are given
10 The language accepted by @pspp{} is similar to those accepted by SPSS
11 statistical products. The details of @pspp{}'s language are given
1212 later in this manual.
1313
14 @cindex files, PSPP
15 @cindex output, PSPP
14 @cindex files, @pspp{}
15 @cindex output, @pspp{}
1616 @cindex PostScript
1717 @cindex PDF
1818 @cindex HTML
2020 @cindex graphics
2121 @cindex Ghostscript
2222 @cindex Free Software Foundation
23 PSPP produces tables and charts as output, which it can produce in
23 @pspp{} produces tables and charts as output, which it can produce in
2424 several formats; currently, ASCII, PostScript, PDF, HTML, and SVG are
2525 supported.
2626
27 The current version of PSPP, @value{VERSION}, is woefully incomplete in
28 terms of its statistical procedure support. PSPP is a work in progress.
27 The current version of @pspp{}, @value{VERSION}, is woefully incomplete in
28 terms of its statistical procedure support. @pspp{} is a work in progress.
2929 The author hopes to fully support all features in the products
30 that PSPP replaces, eventually. The author welcomes questions,
30 that @pspp{} replaces, eventually. The author welcomes questions,
3131 comments, donations, and code submissions. @xref{Bugs,,Submitting Bug
3232 Reports}, for instructions on contacting the author.
00 @node Invoking PSPP
11 @chapter Invoking @command{pspp}
22 @cindex invocation
3 @cindex PSPP, invoking
4
5 PSPP has two separate user interfaces. This chapter describes
6 @command{pspp}, PSPP's command-line driven text-based user interface.
3 @cindex @pspp{}, invoking
4
5 @pspp{} has two separate user interfaces. This chapter describes
6 @command{pspp}, @pspp{}'s command-line driven text-based user interface.
77 The following chapter briefly describes PSPPIRE, the graphical user
8 interface to PSPP.
8 interface to @pspp{}.
99
1010 The sections below describe the @command{pspp} program's command-line
1111 interface.
6969 @end example
7070 @end table
7171
72 @table @code
72 @table @asis
7373 @item @var{syntax-file}
7474 Read and execute the named syntax file. If no syntax files are
75 specified, PSPP prompts for commands. If any syntax files are
76 specified, PSPP by default exits after it runs them, but you may make
75 specified, @pspp{} prompts for commands. If any syntax files are
76 specified, @pspp{} by default exits after it runs them, but you may make
7777 it prompt for commands by specifying @samp{-} as an additional syntax
7878 file.
7979
80 @item -o @var{output-file}
81 Write output to @var{output-file}. PSPP has several different output
80 @item @option{-o @var{output-file}}
81 Write output to @var{output-file}. @pspp{} has several different output
8282 drivers that support output in various formats (use @option{--help} to
8383 list the available formats). Specify this option more than once to
8484 produce multiple output files, presumably in different formats.
8585
8686 Use @samp{-} as @var{output-file} to write output to standard output.
8787
88 If no @option{-o} option is used, then PSPP writes output to standard
88 If no @option{-o} option is used, then @pspp{} writes output to standard
8989 output in plain text format.
9090
91 @item -O @var{option}=@var{value}
91 @item @option{-O @var{option}=@var{value}}
9292 Sets an option for the output file configured by a preceding
9393 @option{-o}. Most options are specific to particular output formats.
9494 A few options that apply generically are listed below.
9595
96 @item -O format=@var{format}
97 PSPP uses the extension of the file name given on @option{-o} to
96 @item @option{-O format=@var{format}}
97 @pspp{} uses the extension of the file name given on @option{-o} to
9898 select an output format. Use this option to override this choice by
9999 specifying an alternate format, e.g.@: @option{-o pspp.out -O html} to
100100 write HTML to a file named @file{pspp.out}. Use @option{--help} to
101101 list the available formats.
102102
103 @item -O device=@{terminal|listing@}
104 Sets whether PSPP considers the output device configured by the
103 @item @option{-O device=@{terminal|listing@}}
104 Sets whether @pspp{} considers the output device configured by the
105105 preceding @option{-o} to be a terminal or a listing device. This
106106 affects what output will be sent to the device, as configured by the
107107 SET command's output routing subcommands (@pxref{SET}). By default,
108108 output written to standard output is considered a terminal device and
109109 other output is considered a listing device.
110110
111 @item --no-output
111 @item @option{--no-output}
112112 Disables output entirely, if neither @option{-o} nor @option{-O} is
113113 also used. If one of those options is used, @option{--no-output} has
114114 no effect.
115115
116 @item -e @var{error-file}
117 @itemx --error-file=@var{error-file}
118 Configures a file to receive PSPP error, warning, and note messages in
116 @item @option{-e @var{error-file}}
117 @itemx @option{--error-file=@var{error-file}}
118 Configures a file to receive @pspp{} error, warning, and note messages in
119119 plain text format. Use @samp{-} as @var{error-file} to write messages
120120 to standard output. The default error file is standard output in the
121121 absence of these options, but this is suppressed if an output device
123123 every message twice. Use @samp{none} as @var{error-file} to
124124 explicitly suppress the default.
125125
126 @item -I @var{dir}
127 @itemx --include=@var{dir}
128 Appends @var{dir} to the set of directories searched by INCLUDE
129 (@pxref{INCLUDE}) and INSERT (@pxref{INSERT}).
130
131 @item -I-
132 @itemx --no-include
126 @item @option{-I @var{dir}}
127 @itemx @option{--include=@var{dir}}
128 Appends @var{dir} to the set of directories searched by the @cmd{INCLUDE}
129 (@pxref{INCLUDE}) and @cmd{INSERT} (@pxref{INSERT}) commands.
130
131 @item @option{-I-}
132 @itemx @option{--no-include}
133133 Clears all directories from the include path, including directories
134134 inserted in the include path by default. The default include path is
135135 @file{.} (the current directory), followed by @file{.pspp} in the
136 user's home directory, followed by PSPP's system configuration
136 user's home directory, followed by @pspp{}'s system configuration
137137 directory (usually @file{/etc/pspp} or @file{/usr/local/etc/pspp}).
138138
139 @item -b
140 @item --batch
141 @item -i
142 @itemx --interactive
139 @item @option{-b}
140 @item @option{--batch}
141 @item @option{-i}
142 @itemx @option{--interactive}
143143 These options forces syntax files to be interpreted in batch mode or
144144 interactive mode, respectively, rather than the default ``auto'' mode.
145145 @xref{Syntax Variants}, for a description of the differences.
146146
147 @item -r
148 @itemx --no-statrc
149 Disables running @file{rc} at PSPP startup time.
150
151 @item -a @{enhanced|compatible@}
152 @itemx --algorithm=@{enhanced|compatible@}
153 With @code{enhanced}, the default, PSPP uses the best implemented
147 @item @option{-r}
148 @itemx @option{--no-statrc}
149 Disables running @file{rc} at @pspp{} startup time.
150
151 @item @option{-a @{enhanced|compatible@}}
152 @itemx @option{--algorithm=@{enhanced|compatible@}}
153 With @code{enhanced}, the default, @pspp{} uses the best implemented
154154 algorithms for statistical procedures. With @code{compatible},
155 however, PSPP will in some cases use inferior algorithms to produce
155 however, @pspp{} will in some cases use inferior algorithms to produce
156156 the same results as the proprietary program SPSS.
157157
158158 Some commands have subcommands that override this setting on a per
159159 command basis.
160160
161 @item -x @{enhanced|compatible@}
162 @itemx --syntax=@{enhanced|compatible@}
163 With @code{enhanced}, the default, PSPP accepts its own extensions
161 @item @option{-x @{enhanced|compatible@}}
162 @itemx @option{--syntax=@{enhanced|compatible@}}
163 With @code{enhanced}, the default, @pspp{} accepts its own extensions
164164 beyond those compatible with the proprietary program SPSS. With
165 @code{compatible}, PSPP rejects syntax that uses these extensions.
166
167 @item --syntax-encoding=@var{encoding}
165 @code{compatible}, @pspp{} rejects syntax that uses these extensions.
166
167 @item @option{--syntax-encoding=@var{encoding}}
168168 Specifies @var{encoding} as the encoding for syntax files named on the
169169 command line. The @var{encoding} also becomes the default encoding
170 for other syntax files read during the PSPP session by the
170 for other syntax files read during the @pspp{} session by the
171171 @cmd{INCLUDE} and @cmd{INSERT} commands. @xref{INSERT}, for the
172172 accepted forms of @var{encoding}.
173173
174 @item --help
175 Prints a message describing PSPP command-line syntax and the available
174 @item @option{--help}
175 Prints a message describing @pspp{} command-line syntax and the available
176176 device formats, then exits.
177177
178 @item -V
179 @itemx --version
180 Prints a brief message listing PSPP's version, warranties you don't
178 @item @option{-V}
179 @itemx @option{--version}
180 Prints a brief message listing @pspp{}'s version, warranties you don't
181181 have, copying conditions and copyright, and e-mail address for bug
182182 reports, then exits.
183183
184 @item -s
185 @itemx --safer
186 Disables certain unsafe operations. This includes the ERASE and
187 HOST commands, as well as use of pipes as input and output files.
188
189 @item --testing-mode
190 Invoke heuristics to assist with testing PSPP. For use by @code{make
191 check} and similar scripts.
184 @item @option{-s}
185 @itemx @option{--safer}
186 Disables certain unsafe operations. This includes the @subcmd{ERASE} and
187 @subcmd{HOST} commands, as well as use of pipes as input and output files.
188
189 @item @option{--testing-mode}
190 Invoke heuristics to assist with testing @pspp{}. For use
191 by @command{make check} and similar scripts.
192192 @end table
193193
194194 @node PDF PostScript and SVG Output Options
198198 @cindex SVG
199199
200200 To produce output in PDF, PostScript, and SVG formats, specify
201 @option{-o @var{file}} on the PSPP command line, optionally followed
201 @option{-o @var{file}} on the @pspp{} command line, optionally followed
202202 by any of the options shown in the table below to customize the output
203203 format.
204204
205205 PDF, PostScript, and SVG output is only available if your installation
206 of PSPP was compiled with the Cairo library.
207
208 @table @code
209 @item -O format=@{pdf|ps|svg@}
206 of @pspp{} was compiled with the Cairo library.
207
208 @table @asis
209 @item @option{-O format=@{pdf|ps|svg@}}
210210 Specify the output format. This is only necessary if the file name
211211 given on @option{-o} does not end in @file{.pdf}, @file{.ps}, or
212212 @file{.svg}.
213213
214 @item -O paper-size=@var{paper-size}
214 @item @option{-O paper-size=@var{paper-size}}
215215 Paper size, as a name (e.g.@: @code{a4}, @code{letter}) or
216216 measurements (e.g.@: @code{210x297}, @code{8.5x11in}).
217217
223223 the default paper size is read from it. As a last resort, A4 paper is
224224 assumed.
225225
226 @item -O foreground-color=@var{color}
227 @itemx -O background-color=@var{color}
226 @item @option{-O foreground-color=@var{color}}
227 @itemx @option{-O background-color=@var{color}}
228228 Sets @var{color} as the color to be used for the background or foreground.
229229 Color should be given in the format @code{#@var{RRRR}@var{GGGG}@var{BBBB}},
230230 where @var{RRRR}, @var{GGGG} and @var{BBBB} are 4 character hexadecimal
231231 representations of the red, green and blue components respectively.
232232
233 @item -O orientation=@var{orientation}
233 @item @option{-O orientation=@var{orientation}}
234234 Either @code{portrait} or @code{landscape}. Default: @code{portrait}.
235235
236 @item -O left-margin=@var{dimension}
237 @itemx -O right-margin=@var{dimension}
238 @itemx -O top-margin=@var{dimension}
239 @itemx -O bottom-margin=@var{dimension}
236 @item @option{-O left-margin=@var{dimension}}
237 @itemx @option{-O right-margin=@var{dimension}}
238 @itemx @option{-O top-margin=@var{dimension}}
239 @itemx @option{-O bottom-margin=@var{dimension}}
240240 Sets the margins around the page. See
241241 below for the allowed forms of @var{dimension} Default: @code{0.5in}.
242242
243 @item -O prop-font=@var{font-name}
244 @itemx -O emph-font=@var{font-name}
245 @itemx -O fixed-font=@var{font-name}
243 @item @option{-O prop-font=@var{font-name}}
244 @itemx @option{-O emph-font=@var{font-name}}
245 @itemx @option{-O fixed-font=@var{font-name}}
246246 Sets the font used for proportional, emphasized, or fixed-pitch text.
247247 Most systems support CSS-like font names such as ``serif'' and
248248 ``monospace'', but a wide range of system-specific font are likely to
251251 Default: proportional font @code{serif}, emphasis font @code{serif
252252 italic}, fixed-pitch font @code{monospace}.
253253
254 @item -O font-size=@var{font-size}
254 @item @option{-O font-size=@var{font-size}}
255255 Sets the size of the default fonts, in thousandths of a point. Default:
256256 10000 (10 point).
257257
258 @item -O line-gutter=@var{dimension}
258 @item @option{-O line-gutter=@var{dimension}}
259259 Sets the width of white space on either side of lines that border text
260260 or graphics objects. Default: @code{1pt}.
261261
262 @item -O line-spacing=@var{dimension}
262 @item @option{-O line-spacing=@var{dimension}}
263263 Sets the spacing between the lines in a double line in a table.
264264 Default: @code{1pt}.
265265
266 @item -O line-width=@var{dimension}
266 @item @option{-O line-width=@var{dimension}}
267267 Sets the width of the lines used in tables. Default: @code{0.5pt}.
268268 @end table
269269
276276 @node Plain Text Output Options
277277 @section Plain Text Output Options
278278
279 PSPP can produce plain text output, drawing boxes using ASCII or
279 @pspp{} can produce plain text output, drawing boxes using ASCII or
280280 Unicode line drawing characters. To produce plain text output,
281 specify @option{-o @var{file}} on the PSPP command line, optionally
281 specify @option{-o @var{file}} on the @pspp{} command line, optionally
282282 followed by options from the table below to customize the output
283283 format.
284284
285285 Plain text output is encoded in UTF-8.
286286
287 @table @code
288 @item -O format=txt
287 @table @asis
288 @item @option{-O format=txt}
289289 Specify the output format. This is only necessary if the file name
290290 given on @option{-o} does not end in @file{.txt} or @file{.list}.
291291
292 @item -O charts=@{@var{template}.png|none@}
292 @item @option{-O charts=@{@var{template}.png|none@}}
293293 Name for chart files included in output. The value should be a file
294294 name that includes a single @samp{#} and ends in @file{png}. When a
295295 chart is output, the @samp{#} is replaced by the chart number. The
297297 stripped off and replaced by @file{-#.png}.
298298
299299 Specify @code{none} to disable chart output. Charts are always
300 disabled if your installation of PSPP was compiled without the
300 disabled if your installation of @pspp{} was compiled without the
301301 Cairo library.
302302
303 @item -O paginate=@var{boolean}
304 If set, PSPP writes an ASCII formfeed the end of every page. Default:
303 @item @option{-O paginate=@var{boolean}}
304 If set, @pspp{} writes an ASCII formfeed the end of every page. Default:
305305 @code{off}.
306306
307 @item -O headers=@var{boolean}
308 If enabled, PSPP prints two lines of header information giving title
309 and subtitle, page number, date and time, and PSPP version are printed
307 @item @option{-O headers=@var{boolean}}
308 If enabled, @pspp{} prints two lines of header information giving title
309 and subtitle, page number, date and time, and @pspp{} version are printed
310310 at the top of every page. These two lines are in addition to any top
311311 margin requested. Default: @code{off}.
312312
313 @item -O length=@var{line-count}
313 @item @option{-O length=@var{line-count}}
314314 Physical length of a page. Headers and margins are subtracted from
315315 this value. You may specify the number of lines as a number, or for
316316 screen output you may specify @code{auto} to track the height of the
317317 terminal as it changes. Default: @code{66}.
318318
319 @item -O width=@var{character-count}
319 @item @option{-O width=@var{character-count}}
320320 Width of a page, in characters. Margins are subtracted from this
321321 value. For screen output you may specify @code{auto} in place of a
322322 number to track the width of the terminal as it changes. Default:
323323 @code{79}.
324324
325 @item -O top-margin=@var{top-margin-lines}
326 Length of the top margin, in lines. PSPP subtracts this value from
325 @item @option{-O top-margin=@var{top-margin-lines}}
326 Length of the top margin, in lines. @pspp{} subtracts this value from
327327 the page length. Default: @code{0}.
328328
329 @item -O bottom-margin=@var{bottom-margin-lines}
330 Length of the bottom margin, in lines. PSPP subtracts this value from
329 @item @option{-O bottom-margin=@var{bottom-margin-lines}}
330 Length of the bottom margin, in lines. @pspp{} subtracts this value from
331331 the page length. Default: @code{0}.
332332
333 @item -O box=@{ascii|unicode@}
333 @item @option{-O box=@{ascii|unicode@}}
334334 Sets the characters used for lines in tables. The default,
335335 @code{ascii}, uses @samp{-}, @samp{|}, and @samp{+} for single-width
336336 lines and @samp{=} and @samp{#} for double-width lines. Specify
337337 @code{unicode} to use Unicode box drawing characters.
338338
339 @item -O emphasis=@{none|bold|underline@}
339 @item @option{-O emphasis=@{none|bold|underline@}}
340340 How to emphasize text. Bold and underline emphasis are achieved with
341341 overstriking, which may not be supported by all the software to which
342342 you might pass the output. Default: @code{none}.
346346 @section HTML Output Options
347347 @cindex HTML
348348 To produce output in HTML format, specify @option{-o @var{file}} on
349 the PSPP command line, optionally followed by any of the options shown
349 the @pspp{} command line, optionally followed by any of the options shown
350350 in the table below to customize the output format.
351351
352 @table @code
353 @item -O format=html
352 @table @asis
353 @item @option{-O format=html}
354354 Specify the output format. This is only necessary if the file name
355355 given on @option{-o} does not end in @file{.html}.
356356
357 @item -O charts=@{@var{template}.png|none@}
357 @item @option{-O charts=@{@var{template}.png|none@}}
358358 Sets the name used for chart files. @xref{Plain Text Output Options},
359359 for details.
360360
361 @item -O borders=@var{boolean}
361 @item @option{-O borders=@var{boolean}}
362362 Decorate the tables with borders. If set to false, the tables produced
363363 will have no borders. The default value is true.
364364
365 @item -O css=@var{boolean}
365 @item @option{-O css=@var{boolean}}
366366 Use cascading style sheets. Cascading style sheets give an improved appearance
367367 and can be used to produce pages which fit a certain web site's style.
368368 The default value is true.
373373 @section OpenDocument Output Options
374374
375375 To produce output as an OpenDocument text (ODT) document, specify
376 @option{-o @var{file}} on the PSPP command line. If @var{file} does
376 @option{-o @var{file}} on the @pspp{} command line. If @var{file} does
377377 not end in @file{.odt}, you must also specify @option{-O format=odt}.
378378
379 ODT support is only available if your installation of PSPP was
379 ODT support is only available if your installation of @pspp{} was
380380 compiled with the libxml2 library.
381381
382382 The OpenDocument output format does not have any configurable options.
385385 @section Comma-Separated Value Output Options
386386
387387 To produce output in comma-separated value (CSV) format, specify
388 @option{-o @var{file}} on the PSPP command line, optionally followed
388 @option{-o @var{file}} on the @pspp{} command line, optionally followed
389389 by any of the options shown in the table below to customize the output
390390 format.
391391
392 @table @code
393 @item -O format=csv
392 @table @asis
393 @item @option{-O format=csv}
394394 Specify the output format. This is only necessary if the file name
395395 given on @option{-o} does not end in @file{.csv}.
396396
397 @item -O separator=@var{field-separator}
397 @item @option{-O separator=@var{field-separator}}
398398 Sets the character used to separate fields. Default: a comma
399399 (@samp{,}).
400400
401 @item -O quote=@var{qualifier}
401 @item @option{-O quote=@var{qualifier}}
402402 Sets @var{qualifier} as the character used to quote fields that
403403 contain white space, the separator (or any of the characters in the
404404 separator, if it contains more than one character), or the quote
406406 only the first character is used; if @var{qualifier} is the empty
407407 string, then fields are never quoted.
408408
409 @item -O captions=@var{boolean}
409 @item @option{-O captions=@var{boolean}}
410410 Whether table captions should be printed. Default: @code{on}.
411411 @end table
412412
441441 @cindex Graphic user interface
442442 @cindex PSPPIRE
443443
444 The PSPPIRE graphic user interface for PSPP can perform all
444 The PSPPIRE graphic user interface for @pspp{} can perform all
445445 functionality of the command line interface. In addition it gives an
446446 instantaneous view of the data, variables and statistical output.
447447
450450 Alternatively many systems have a system of interactive menus or buttons
451451 from which @command{psppire} can be started by a series of mouse clicks.
452452
453 Once the principles of the PSPP system are understood,
453 Once the principles of the @pspp{} system are understood,
454454 the graphic user interface is designed to be largely intuitive, and
455455 for this reason is covered only very briefly by this manual.
00 @node Language
1 @chapter The PSPP language
2 @cindex language, PSPP
3 @cindex PSPP, language
4
5 This chapter discusses elements common to many PSPP commands.
1 @chapter The @pspp{} language
2 @cindex language, @pspp{}
3 @cindex @pspp{}, language
4
5 This chapter discusses elements common to many @pspp{} commands.
66 Later chapters will describe individual commands in detail.
77
88 @menu
1313 * Order of Commands:: Commands combine to form syntax files.
1414 * Missing Observations:: Handling missing observations.
1515 * Datasets:: Data organization.
16 * Files:: Files used by PSPP.
16 * Files:: Files used by @pspp{}.
1717 * File Handles:: How files are named.
1818 * BNF:: How command syntax is described.
1919 @end menu
2626 @cindex tokens
2727 @cindex lexical analysis
2828
29 PSPP divides most syntax file lines into series of short chunks
29 @pspp{} divides most syntax file lines into series of short chunks
3030 called @dfn{tokens}.
3131 Tokens are then grouped to form commands, each of which tells
32 PSPP to take some action---read in data, write out data, perform
32 @pspp{} to take some action---read in data, write out data, perform
3333 a statistical procedure, etc. Each type of token is
3434 described below.
3535
154154 @node Commands
155155 @section Forming commands of tokens
156156
157 @cindex PSPP, command structure
157 @cindex @pspp{}, command structure
158158 @cindex language, command structure
159159 @cindex commands, structure
160160
161 Most PSPP commands share a common structure. A command begins with a
161 Most @pspp{} commands share a common structure. A command begins with a
162162 command name, such as @cmd{FREQUENCIES}, @cmd{DATA LIST}, or @cmd{N OF
163163 CASES}. The command name may be abbreviated to its first word, and
164164 each word in the command name may be abbreviated to its first three
206206 The default mode for reading commands from a file is @dfn{auto mode}.
207207 It is the same as batch mode, except that a line with a non-blank in
208208 the leftmost column only starts a new command if that line begins with
209 the name of a PSPP command. This correctly interprets most valid PSPP
209 the name of a @pspp{} command. This correctly interprets most valid @pspp{}
210210 syntax files regardless of the syntax mode for which they are
211211 intended.
212212
213213 The @option{--interactive} (or @option{-i}) or @option{--batch} (or
214 @option{-b}) options set the syntax mode for files listed on the PSPP
214 @option{-b}) options set the syntax mode for files listed on the @pspp{}
215215 command line. @xref{Main Options}, for more details.
216216
217217 @node Types of Commands
218218 @section Types of Commands
219219
220 Commands in PSPP are divided roughly into six categories:
220 Commands in @pspp{} are divided roughly into six categories:
221221
222222 @table @strong
223223 @item Utility commands
224224 @cindex utility commands
225 Set or display various global options that affect PSPP operations.
225 Set or display various global options that affect @pspp{} operations.
226226 May appear anywhere in a syntax file. @xref{Utilities, , Utility
227227 commands}.
228228
262262 @cindex commands, ordering
263263 @cindex order of commands
264264
265 PSPP does not place many restrictions on ordering of commands. The
265 @pspp{} does not place many restrictions on ordering of commands. The
266266 main restriction is that variables must be defined before they are otherwise
267267 referenced. This section describes the details of command ordering,
268268 but most users will have no need to refer to them.
269269
270 PSPP possesses five internal states, called initial, INPUT PROGRAM,
271 FILE TYPE, transformation, and procedure states. (Please note the
270 @pspp{} possesses five internal states, called @dfn{initial}, @dfn{input-program}
271 @dfn{file-type}, @dfn{transformation}, and @dfn{procedure} states. (Please note the
272272 distinction between the @cmd{INPUT PROGRAM} and @cmd{FILE TYPE}
273 @emph{commands} and the INPUT PROGRAM and FILE TYPE @emph{states}.)
274
275 PSPP starts in the initial state. Each successful completion
273 @emph{commands} and the @dfn{input-program} and @dfn{file-type} @emph{states}.)
274
275 @pspp{} starts in the initial state. Each successful completion
276276 of a command may cause a state transition. Each type of command has its
277277 own rules for state transitions:
278278
302302 @item @cmd{INPUT PROGRAM}
303303 @itemize @bullet
304304 @item
305 Invalid in INPUT PROGRAM and FILE TYPE states.
306 @item
307 Causes a transition to the INPUT PROGRAM state.
305 Invalid in input-program and file-type states.
306 @item
307 Causes a transition to the intput-program state.
308308 @item
309309 Clears the active dataset.
310310 @end itemize
312312 @item @cmd{FILE TYPE}
313313 @itemize @bullet
314314 @item
315 Invalid in INPUT PROGRAM and FILE TYPE states.
316 @item
317 Causes a transition to the FILE TYPE state.
315 Invalid in intput-program and file-type states.
316 @item
317 Causes a transition to the file-type state.
318318 @item
319319 Clears the active dataset.
320320 @end itemize
322322 @item Other file definition commands
323323 @itemize @bullet
324324 @item
325 Invalid in INPUT PROGRAM and FILE TYPE states.
325 Invalid in input-program and file-type states.
326326 @item
327327 Cause a transition to the transformation state.
328328 @item
333333 @item Transformations
334334 @itemize @bullet
335335 @item
336 Invalid in initial and FILE TYPE states.
336 Invalid in initial and file-type states.
337337 @item
338338 Cause a transition to the transformation state.
339339 @end itemize
341341 @item Restricted transformations
342342 @itemize @bullet
343343 @item
344 Invalid in initial, INPUT PROGRAM, and FILE TYPE states.
344 Invalid in initial, input-program, and file-type states.
345345 @item
346346 Cause a transition to the transformation state.
347347 @end itemize
349349 @item Procedures
350350 @itemize @bullet
351351 @item
352 Invalid in initial, INPUT PROGRAM, and FILE TYPE states.
352 Invalid in initial, input-program, and file-type states.
353353 @item
354354 Cause a transition to the procedure state.
355355 @end itemize
360360 @cindex missing values
361361 @cindex values, missing
362362
363 PSPP includes special support for unknown numeric data values.
363 @pspp{} includes special support for unknown numeric data values.
364364 Missing observations are assigned a special value, called the
365365 @dfn{system-missing value}. This ``value'' actually indicates the
366366 absence of a value; it means that the actual value is unknown. Procedures
389389 @cindex variable
390390 @cindex dictionary
391391
392 PSPP works with data organized into @dfn{datasets}. A dataset
392 @pspp{} works with data organized into @dfn{datasets}. A dataset
393393 consists of a set of @dfn{variables}, which taken together are said to
394394 form a @dfn{dictionary}, and one or more @dfn{cases}, each of which
395395 has one value for each variable.
396396
397 At any given time PSPP has exactly one distinguished dataset, called
398 the @dfn{active dataset}. Most PSPP commands work only with the
399 active dataset. In addition to the active dataset, PSPP also supports
397 At any given time @pspp{} has exactly one distinguished dataset, called
398 the @dfn{active dataset}. Most @pspp{} commands work only with the
399 active dataset. In addition to the active dataset, @pspp{} also supports
400400 any number of additional open datasets. The @cmd{DATASET} commands
401401 can choose a new active dataset from among those that are open, as
402402 well as create and destroy datasets (@pxref{DATASET}).
405405
406406 @menu
407407 * Attributes:: Attributes of variables.
408 * System Variables:: Variables automatically defined by PSPP.
408 * System Variables:: Variables automatically defined by @pspp{}.
409409 * Sets of Variables:: Lists of variable names.
410410 * Input and Output Formats:: Input and output formats.
411411 * Scratch Variables:: Variables deleted by procedures.
435435
436436 @cindex @samp{_}
437437 The final character in a variable name should not be @samp{_}, because
438 some such identifiers are used for special purposes by PSPP
438 some such identifiers are used for special purposes by @pspp{}
439439 procedures.
440440
441 As with all PSPP identifiers, variable names are not case-sensitive.
442 PSPP capitalizes variable names on output the same way they were
441 As with all @pspp{} identifiers, variable names are not case-sensitive.
442 @pspp{} capitalizes variable names on output the same way they were
443443 capitalized at their point of definition in the input.
444444
445445 @cindex variables, type
504504 @end table
505505
506506 @node System Variables
507 @subsection Variables Automatically Defined by PSPP
507 @subsection Variables Automatically Defined by @pspp{}
508508 @cindex system variables
509509 @cindex variables, system
510510
521521
522522 @cindex @code{$DATE}
523523 @item $DATE
524 Date the PSPP process was started, in format A9, following the
524 Date the @pspp{} process was started, in format A9, following the
525525 pattern @code{DD MMM YY}.
526526
527527 @cindex @code{$JDATE}
528528 @item $JDATE
529 Number of days between 15 Oct 1582 and the time the PSPP process
529 Number of days between 15 Oct 1582 and the time the @pspp{} process
530530 was started.
531531
532532 @cindex @code{$LENGTH}
585585 contains an ordinary decimal number, a time or date, a number in binary
586586 or hexadecimal notation, or one of several other notations. Input
587587 formats are used by commands such as @cmd{DATA LIST} that read data or
588 syntax files into the PSPP active dataset.
588 syntax files into the @pspp{} active dataset.
589589
590590 Every input format corresponds to a default @dfn{output format} that
591591 specifies the formatting used when the value is output later. It is
604604 most of the time, the distinction between print and write formats is
605605 unimportant.
606606
607 Input and output formats are specified to PSPP with a @dfn{format
608 specification} of the form @code{TYPEw} or @code{TYPEw.d}, where
609 @code{TYPE} is one of the format types described later, @code{w} is a
610 field width measured in columns, and @code{d} is an optional number of
611 decimal places. If @code{d} is omitted, a value of 0 is assumed. Some
612 formats do not allow a nonzero @code{d} to be specified.
607 Input and output formats are specified to @pspp{} with
608 a @dfn{format specification} of the
609 form @subcmd{@var{TYPE}@var{w}} or @code{TYPE@var{w}.@var{d}}, where
610 @var{TYPE} is one of the format types described later, @var{w} is a
611 field width measured in columns, and @var{d} is an optional number of
612 decimal places. If @var{d} is omitted, a value of 0 is assumed. Some
613 formats do not allow a nonzero @var{d} to be specified.
613614
614615 The following sections describe the input and output formats supported
615 by PSPP.
616 by @pspp{}.
616617
617618 @menu
618619 * Basic Numeric Formats::
10541055 Other than the hexadecimal representation, these formats are equivalent
10551056 to PIB and RB formats, respectively. However, bytes in PIBHEX format
10561057 are always ordered with the most-significant byte first (big-endian
1057 order), regardless of the host machine's native byte order or PSPP
1058 order), regardless of the host machine's native byte order or @pspp{}
10581059 settings.
10591060
10601061 Field widths must be even and between 2 and 16. RBHEX format allows no
10661067
10671068 @cindex time formats
10681069 @cindex date formats
1069 In PSPP, a @dfn{time} is an interval. The time formats translate
1070 between human-friendly descriptions of time intervals and PSPP's
1070 In @pspp{}, a @dfn{time} is an interval. The time formats translate
1071 between human-friendly descriptions of time intervals and @pspp{}'s
10711072 internal representation of time intervals, which is simply the number of
1072 seconds in the interval. PSPP has two time formats:
1073 seconds in the interval. @pspp{} has two time formats:
10731074
10741075 @float
10751076 @multitable {Time Format} {@code{dd-mmm-yyyy HH:MM:SS.ss}} {@code{01-OCT-1978 04:31:17.01}}
10791080 @end multitable
10801081 @end float
10811082
1082 A @dfn{date} is a moment in the past or the future. Internally, PSPP
1083 A @dfn{date} is a moment in the past or the future. Internally, @pspp{}
10831084 represents a date as the number of seconds since the @dfn{epoch},
10841085 midnight, Oct. 14, 1582. The date formats translate between
1085 human-readable dates and PSPP's numeric representation of dates and
1086 times. PSPP has several date formats:
1086 human-readable dates and @pspp{}'s numeric representation of dates and
1087 times. @pspp{} has several date formats:
10871088
10881089 @float
10891090 @multitable {Date Format} {@code{dd-mmm-yyyy HH:MM:SS.ss}} {@code{01-OCT-1978 04:31:17.01}}
12041205 @end table
12051206
12061207 For the time and date formats, the default output format is the same as
1207 the input format, except that PSPP increases the field width, if
1208 the input format, except that @pspp{} increases the field width, if
12081209 necessary, to the minimum allowed for output.
12091210
12101211 Time or dates narrower than the field width are right-justified within
12841285 variable in the analysis.
12851286
12861287 @node Files
1287 @section Files Used by PSPP
1288
1289 PSPP makes use of many files each time it runs. Some of these it
1288 @section Files Used by @pspp{}
1289
1290 @pspp{} makes use of many files each time it runs. Some of these it
12901291 reads, some it writes, some it creates. Here is a table listing the
12911292 most important of these files:
12921293
12981299 @item command file
12991300 @itemx syntax file
13001301 These names (synonyms) refer to the file that contains instructions
1301 that tell PSPP what to do. The syntax file's name is specified on
1302 the PSPP command line. Syntax files can also be read with
1302 that tell @pspp{} what to do. The syntax file's name is specified on
1303 the @pspp{} command line. Syntax files can also be read with
13031304 @cmd{INCLUDE} (@pxref{INCLUDE}).
13041305
13051306 @cindex file, data
13111312 @cindex file, output
13121313 @cindex output file
13131314 @item listing file
1314 One or more output files are created by PSPP each time it is
1315 One or more output files are created by @pspp{} each time it is
13151316 run. The output files receive the tables and charts produced by
13161317 statistical procedures. The output files may be in any number of formats,
1317 depending on how PSPP is configured.
1318 depending on how @pspp{} is configured.
13181319
13191320 @cindex system file
13201321 @cindex file, system
13471348 (e.g.@: @code{GET '|zcat mydata.sav.gz'}), and for many other
13481349 purposes.
13491350
1350 PSPP also supports declaring named file handles with the @cmd{FILE
1351 @pspp{} also supports declaring named file handles with the @cmd{FILE
13511352 HANDLE} command. This command associates an identifier of your choice
13521353 (the file handle's name) with a file. Later, the file handle name can
1353 be substituted for the name of the file. When PSPP syntax accesses a
1354 be substituted for the name of the file. When @pspp{} syntax accesses a
13541355 file multiple times, declaring a named file handle simplifies updating
13551356 the syntax later to use a different file. Use of @cmd{FILE HANDLE} is
13561357 also required to read data files in binary formats. @xref{FILE HANDLE},
13571358 for more information.
13581359
1359 In some circumstances, PSPP must distinguish whether a file handle
1360 In some circumstances, @pspp{} must distinguish whether a file handle
13601361 refers to a system file or a portable file. When this is necessary to
13611362 read a file, e.g.@: as an input file for @cmd{GET} or @cmd{MATCH FILES},
1362 PSPP uses the file's contents to decide. In the context of writing a
1363 file, e.g.@: as an output file for @cmd{SAVE} or @cmd{AGGREGATE}, PSPP
1363 @pspp{} uses the file's contents to decide. In the context of writing a
1364 file, e.g.@: as an output file for @cmd{SAVE} or @cmd{AGGREGATE}, @pspp{}
13641365 decides based on the file's name: if it ends in @samp{.por} (with any
1365 capitalization), then PSPP writes a portable file; otherwise, PSPP
1366 capitalization), then @pspp{} writes a portable file; otherwise, @pspp{}
13661367 writes a system file.
13671368
13681369 INLINE is reserved as a file handle name. It refers to the ``data
13811382 @cindex command syntax, description of
13821383 @cindex description of command syntax
13831384
1384 The syntax of some parts of the PSPP language is presented in this
1385 The syntax of some parts of the @pspp{} language is presented in this
13851386 manual using the formalism known as @dfn{Backus-Naur Form}, or BNF. The
13861387 following table describes BNF:
13871388
13891390 @cindex keywords
13901391 @cindex terminals
13911392 @item
1392 Words in all-uppercase are PSPP keyword tokens. In BNF, these are
1393 Words in all-uppercase are @pspp{} keyword tokens. In BNF, these are
13931394 often called @dfn{terminals}. There are some special terminals, which
13941395 are written in lowercase for clarity:
13951396
66 @cindex copyright
77 @cindex obligations, your
88
9 PSPP is not in the public domain. It is copyrighted and there are
9 @pspp{} is not in the public domain. It is copyrighted and there are
1010 restrictions on its distribution, but these restrictions are designed
1111 to permit everything that a good cooperating citizen would want to do.
1212 What is not allowed is to try to prevent others from further sharing
1313 any version of this program that they might get from you.
1414
1515 Specifically, we want to make sure that you have the right to give
16 away copies of PSPP, that you receive source code or else can get it
16 away copies of @pspp{}, that you receive source code or else can get it
1717 if you want it, that you can change these programs or use pieces of
1818 them in new free programs, and that you know you can do these things.
1919
2020 To make sure that everyone has such rights, we have to forbid you to
2121 deprive anyone else of these rights. For example, if you distribute
22 copies of PSPP, you must give the recipients all the rights that you
22 copies of @pspp{}, you must give the recipients all the rights that you
2323 have. You must make sure that they, too, receive or can get the
2424 source code. And you must tell them their rights.
2525
2626 Also, for our own protection, we must make certain that everyone finds
27 out that there is no warranty for PSPP. If these programs are
27 out that there is no warranty for @pspp{}. If these programs are
2828 modified by someone else and passed on, we want their recipients to
2929 know that what they have is not what we distributed, so that any
3030 problems introduced by others will not reflect on our reputation.
3535 program proprietary. To prevent this, we have made it clear that any
3636 patent must be licensed for everyone's free use or not licensed at all.
3737
38 The precise conditions of the license for PSPP are found in the
38 The precise conditions of the license for @pspp{} are found in the
3939 GNU General Public License. You should have received a copy of
4040 the GNU General Public License along with this program; if not, write
4141 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00 @node Not Implemented
11 @chapter Not Implemented
22
3 This chapter lists parts of the PSPP language that are not yet
3 This chapter lists parts of the @pspp{} language that are not yet
44 implemented.
55
66 @cindex unimplemented commands
1414
1515 @include version.texi
1616
17 @c This macro should be used for marking command names. For the purposes of markup,
18 @c no distinction is made between ``commands'' and ``procedures''.
1719 @macro cmd{CMDNAME}
18 \CMDNAME\
20 @code{\CMDNAME\}
1921 @end macro
22
23 @c This macro is used for fragments of command syntax that are not in themselves command names.
24 @c It does not necessarily have to be a subcommand.
25 @macro subcmd{CMDNAME}
26 @code{\CMDNAME\}
27 @end macro
28
29 @c Use this macro to refer to PSPP itself . Not when giving a shell command line example.
30 @macro pspp
31 @sc{pspp}
32 @end macro
33
2034
2135 @ifset MISSING_CLICKSEQUENCE
2236 @alias clicksequence = asis
3246 @dircategory Math
3347 @direntry
3448 * PSPP: (pspp). Statistical analysis package.
35 * PSPPIRE: (pspp). Graphical user interface to PSPP.
49 * PSPPIRE: (pspp). Graphical user interface to @pspp{}.
3650 @end direntry
3751
3852 @copying
3953 This manual is for GNU PSPP version @value{VERSION},
4054 software for statistical analysis.
4155
42 Copyright @copyright{} 1997, 1998, 2004, 2005, 2009 Free Software Foundation, Inc.
56 Copyright @copyright{} 1997, 1998, 2004, 2005, 2009, 2012 Free Software Foundation, Inc.
4357
4458 @quotation
4559 Permission is granted to copy, distribute and/or modify this document
00 @node REGRESSION
1 @comment node-name, next, previous, up
21 @section REGRESSION
32
43 @cindex regression
54 @cindex linear regression
6 The REGRESSION procedure fits linear models to data via least-squares
5 The @cmd{REGRESSION} procedure fits linear models to data via least-squares
76 estimation. The procedure is appropriate for data which satisfy those
87 assumptions typical in linear regression:
98
109 @itemize @bullet
1110 @item The data set contains @math{n} observations of a dependent variable, say
1211 @math{Y_1,@dots{},Y_n}, and @math{n} observations of one or more explanatory
13 variables. Let @math{X_{11}, X_{12}}, @dots{}, @math{X_{1n}} denote the @math{n} observations of the
14 first explanatory variable; @math{X_{21}},@dots{},@math{X_{2n}} denote the @math{n} observations of the
15 second explanatory variable; @math{X_{k1}},@dots{},@math{X_{kn}} denote the @math{n} observations of the kth
16 explanatory variable.
12 variables.
13 Let @math{X_{11}, X_{12}}, @dots{}, @math{X_{1n}} denote the @math{n} observations
14 of the first explanatory variable;
15 @math{X_{21}},@dots{},@math{X_{2n}} denote the @math{n} observations of the second
16 explanatory variable;
17 @math{X_{k1}},@dots{},@math{X_{kn}} denote the @math{n} observations of
18 the @math{k}th explanatory variable.
1719
1820 @item The dependent variable @math{Y} has the following relationship to the
1921 explanatory variables:
2022 @math{Y_i = b_0 + b_1 X_{1i} + ... + b_k X_{ki} + Z_i}
2123 where @math{b_0, b_1, @dots{}, b_k} are unknown
2224 coefficients, and @math{Z_1,@dots{},Z_n} are independent, normally
23 distributed ``noise'' terms with mean zero and common variance. The noise, or
24 ``error'' terms are unobserved. This relationship is called the
25 ``linear model.''
25 distributed @dfn{noise} terms with mean zero and common variance.
26 The noise, or @dfn{error} terms are unobserved.
27 This relationship is called the @dfn{linear model}.
2628 @end itemize
2729
28 The REGRESSION procedure estimates the coefficients
30 The @cmd{REGRESSION} procedure estimates the coefficients
2931 @math{b_0,@dots{},b_k} and produces output relevant to inferences for the
3032 linear model.
31
32 @c If you add any new commands, then don't forget to remove the entry in
33 @c not-implemented.texi
3433
3534 @menu
3635 * Syntax:: Syntax definition.
4342 @vindex REGRESSION
4443 @display
4544 REGRESSION
46 /VARIABLES=var_list
47 /DEPENDENT=var_list
45 /VARIABLES=@var{var_list}
46 /DEPENDENT=@var{var_list}
4847 /STATISTICS=@{ALL, DEFAULTS, R, COEFF, ANOVA, BCOV@}
4948 /SAVE=@{PRED, RESID@}
5049 @end display
5251 The @cmd{REGRESSION} procedure reads the active dataset and outputs
5352 statistics relevant to the linear model specified by the user.
5453
55 The VARIABLES subcommand, which is required, specifies the list of
56 variables to be analyzed. Keyword VARIABLES is required. The
57 DEPENDENT subcommand specifies the dependent variable of the linear
58 model. The DEPENDENT subcommand is required. All variables listed in
59 the VARIABLES subcommand, but not listed in the DEPENDENT subcommand,
54 The @subcmd{VARIABLES} subcommand, which is required, specifies the list of
55 variables to be analyzed. Keyword @subcmd{VARIABLES} is required. The
56 @subcmd{DEPENDENT} subcommand specifies the dependent variable of the linear
57 model. The @subcmd{DEPENDENT} subcommand is required. All variables listed in
58 the @subcmd{VARIABLES} subcommand, but not listed in the @subcmd{DEPENDENT} subcommand,
6059 are treated as explanatory variables in the linear model.
6160
6261 All other subcommands are optional:
6362
64 The STATISTICS subcommand specifies the statistics to be displayed:
63 The @subcmd{STATISTICS} subcommand specifies the statistics to be displayed:
6564
66 @table @code
65 @table @subcmd
6766 @item ALL
6867 All of the statistics below.
6968 @item R
7776 The covariance matrix for the estimated model coefficients.
7877 @end table
7978
80 The SAVE subcommand causes PSPP to save the residuals or predicted
79 The @subcmd{SAVE} subcommand causes @pspp{} to save the residuals or predicted
8180 values from the fitted
82 model to the active dataset. PSPP will store the residuals in a variable
83 called RES1 if no such variable exists, RES2 if RES1 already exists,
84 RES3 if RES1 and RES2 already exist, etc. It will choose the name of
85 the variable for the predicted values similarly, but with PRED as a
81 model to the active dataset. @pspp{} will store the residuals in a variable
82 called @samp{RES1} if no such variable exists, @samp{RES2} if @samp{RES1}
83 already exists,
84 @samp{RES3} if @samp{RES1} and @samp{RES2} already exist, etc. It will
85 choose the name of
86 the variable for the predicted values similarly, but with @samp{PRED} as a
8687 prefix.
8788
8889 @node Examples
8990 @subsection Examples
90 The following PSPP syntax will generate the default output and save the
91 The following @pspp{} syntax will generate the default output and save the
9192 predicted values and residuals to the active dataset.
9293
9394 @example
00 @node Statistics
11 @chapter Statistics
22
3 This chapter documents the statistical procedures that PSPP supports so
3 This chapter documents the statistical procedures that @pspp{} supports so
44 far.
55
66 @menu
2727 @vindex DESCRIPTIVES
2828 @display
2929 DESCRIPTIVES
30 /VARIABLES=var_list
30 /VARIABLES=@var{var_list}
3131 /MISSING=@{VARIABLE,LISTWISE@} @{INCLUDE,NOINCLUDE@}
3232 /FORMAT=@{LABELS,NOLABELS@} @{NOINDEX,INDEX@} @{LINE,SERIAL@}
3333 /SAVE
4444 statistics requested by the user. In addition, it can optionally
4545 compute Z-scores.
4646
47 The VARIABLES subcommand, which is required, specifies the list of
48 variables to be analyzed. Keyword VARIABLES is optional.
47 The @subcmd{VARIABLES} subcommand, which is required, specifies the list of
48 variables to be analyzed. Keyword @subcmd{VARIABLES} is optional.
4949
5050 All other subcommands are optional:
5151
52 The MISSING subcommand determines the handling of missing variables. If
53 INCLUDE is set, then user-missing values are included in the
54 calculations. If NOINCLUDE is set, which is the default, user-missing
55 values are excluded. If VARIABLE is set, then missing values are
56 excluded on a variable by variable basis; if LISTWISE is set, then
52 The @subcmd{MISSING} subcommand determines the handling of missing variables. If
53 @subcmd{INCLUDE} is set, then user-missing values are included in the
54 calculations. If @subcmd{NOINCLUDE} is set, which is the default, user-missing
55 values are excluded. If @subcmd{VARIABLE} is set, then missing values are
56 excluded on a variable by variable basis; if @subcmd{LISTWISE} is set, then
5757 the entire case is excluded whenever any value in that case has a
58 system-missing or, if INCLUDE is set, user-missing value.
59
60 The FORMAT subcommand affects the output format. Currently the
61 LABELS/NOLABELS and NOINDEX/INDEX settings are not used. When SERIAL is
58 system-missing or, if @subcmd{INCLUDE} is set, user-missing value.
59
60 The @subcmd{FORMAT} subcommand affects the output format. Currently the
61 @subcmd{LABELS/NOLABELS} and @subcmd{NOINDEX/INDEX} settings are not used.
62 When @subcmd{SERIAL} is
6263 set, both valid and missing number of cases are listed in the output;
63 when NOSERIAL is set, only valid cases are listed.
64
65 The SAVE subcommand causes @cmd{DESCRIPTIVES} to calculate Z scores for all
64 when @subcmd{NOSERIAL} is set, only valid cases are listed.
65
66 The @subcmd{SAVE} subcommand causes @cmd{DESCRIPTIVES} to calculate Z scores for all
6667 the specified variables. The Z scores are saved to new variables.
6768 Variable names are generated by trying first the original variable name
6869 with Z prepended and truncated to a maximum of 8 characters, then the
6970 names ZSC000 through ZSC999, STDZ00 through STDZ09, ZZZZ00 through
7071 ZZZZ09, ZQZQ00 through ZQZQ09, in that sequence. In addition, Z score
71 variable names can be specified explicitly on VARIABLES in the variable
72 variable names can be specified explicitly on @subcmd{VARIABLES} in the variable
7273 list by enclosing them in parentheses after each variable.
7374
74 The STATISTICS subcommand specifies the statistics to be displayed:
75 The @subcmd{STATISTICS} subcommand specifies the statistics to be displayed:
7576
7677 @table @code
77 @item ALL
78 @item @subcmd{ALL}
7879 All of the statistics below.
79 @item MEAN
80 @item @subcmd{MEAN}
8081 Arithmetic mean.
81 @item SEMEAN
82 @item @subcmd{SEMEAN}
8283 Standard error of the mean.
83 @item STDDEV
84 @item @subcmd{STDDEV}
8485 Standard deviation.
85 @item VARIANCE
86 @item @subcmd{VARIANCE}
8687 Variance.
87 @item KURTOSIS
88 @item @subcmd{KURTOSIS}
8889 Kurtosis and standard error of the kurtosis.
89 @item SKEWNESS
90 @item @subcmd{SKEWNESS}
9091 Skewness and standard error of the skewness.
91 @item RANGE
92 @item @subcmd{RANGE}
9293 Range.
9394 @item MINIMUM
9495 Minimum value.
104105 Standard error of the skewness.
105106 @end table
106107
107 The SORT subcommand specifies how the statistics should be sorted. Most
108 of the possible values should be self-explanatory. NAME causes the
108 The @subcmd{SORT} subcommand specifies how the statistics should be sorted. Most
109 of the possible values should be self-explanatory. @subcmd{NAME} causes the
109110 statistics to be sorted by name. By default, the statistics are listed
110 in the order that they are specified on the VARIABLES subcommand. The A
111 and D settings request an ascending or descending sort order,
112 respectively.
111 in the order that they are specified on the @subcmd{VARIABLES} subcommand.
112 The @subcmd{A} and @subcmd{D} settings request an ascending or descending
113 sort order, respectively.
113114
114115 @node FREQUENCIES
115116 @section FREQUENCIES
117118 @vindex FREQUENCIES
118119 @display
119120 FREQUENCIES
120 /VARIABLES=var_list
121 /FORMAT=@{TABLE,NOTABLE,LIMIT(limit)@}
121 /VARIABLES=@var{var_list}
122 /FORMAT=@{TABLE,NOTABLE,LIMIT(@var{limit})@}
122123 @{AVALUE,DVALUE,AFREQ,DFREQ@}
123124 /MISSING=@{EXCLUDE,INCLUDE@}
124125 /STATISTICS=@{DEFAULT,MEAN,SEMEAN,MEDIAN,MODE,STDDEV,VARIANCE,
125126 KURTOSIS,SKEWNESS,RANGE,MINIMUM,MAXIMUM,SUM,
126127 SESKEWNESS,SEKURTOSIS,ALL,NONE@}
127 /NTILES=ntiles
128 /NTILES=@var{ntiles}
128129 /PERCENTILES=percent@dots{}
129 /HISTOGRAM=[MINIMUM(x_min)] [MAXIMUM(x_max)]
130 [@{FREQ[(y_max)],PERCENT[(y_max)]@}] [@{NONORMAL,NORMAL@}]
131 /PIECHART=[MINIMUM(x_min)] [MAXIMUM(x_max)]
130 /HISTOGRAM=[MINIMUM(@var{x_min})] [MAXIMUM(@var{x_max})]
131 [@{FREQ[(@var{y_max})],PERCENT[(@var{y_max})]@}] [@{NONORMAL,NORMAL@}]
132 /PIECHART=[MINIMUM(@var{x_min})] [MAXIMUM(@var{x_max})]
132133 [@{FREQ,PERCENT@}] [@{NOMISSING,MISSING@}]
133134
134135 (These options are not currently implemented.)
144145 @cmd{FREQUENCIES} can also output
145146 histograms and pie charts.
146147
147 The VARIABLES subcommand is the only required subcommand. Specify the
148 The @subcmd{VARIABLES} subcommand is the only required subcommand. Specify the
148149 variables to be analyzed.
149150
150 The FORMAT subcommand controls the output format. It has several
151 The @subcmd{FORMAT} subcommand controls the output format. It has several
151152 possible settings:
152153
153 @itemize @bullet
154 @itemize @subcmd{}
154155 @item
155 TABLE, the default, causes a frequency table to be output for every
156 variable specified. NOTABLE prevents them from being output. LIMIT
156 @subcmd{TABLE}, the default, causes a frequency table to be output for every
157 variable specified. @subcmd{NOTABLE} prevents them from being output. @subcmd{LIMIT}
157158 with a numeric argument causes them to be output except when there are
158159 more than the specified number of values in the table.
159160
160161 @item
161162 Normally frequency tables are sorted in ascending order by value. This
162 is AVALUE. DVALUE tables are sorted in descending order by value.
163 AFREQ and DFREQ tables are sorted in ascending and descending order,
163 is @subcmd{AVALUE}. @subcmd{DVALUE} tables are sorted in descending order by value.
164 @subcmd{AFREQ} and @subcmd{DFREQ} tables are sorted in ascending and descending order,
164165 respectively, by frequency count.
165166 @end itemize
166167
167 The MISSING subcommand controls the handling of user-missing values.
168 When EXCLUDE, the default, is set, user-missing values are not included
169 in frequency tables or statistics. When INCLUDE is set, user-missing
168 The @subcmd{MISSING} subcommand controls the handling of user-missing values.
169 When @subcmd{EXCLUDE}, the default, is set, user-missing values are not included
170 in frequency tables or statistics. When @subcmd{INCLUDE} is set, user-missing
170171 are included. System-missing values are never included in statistics,
171172 but are listed in frequency tables.
172173
173 The available STATISTICS are the same as available in @cmd{DESCRIPTIVES}
174 (@pxref{DESCRIPTIVES}), with the addition of MEDIAN, the data's median
174 The available @subcmd{STATISTICS} are the same as available
175 in @cmd{DESCRIPTIVES} (@pxref{DESCRIPTIVES}), with the addition
176 of @subcmd{MEDIAN}, the data's median
175177 value, and MODE, the mode. (If there are multiple modes, the smallest
176178 value is reported.) By default, the mean, standard deviation of the
177179 mean, minimum, and maximum are reported for each variable.
178180
179181 @cindex percentiles
180 PERCENTILES causes the specified percentiles to be reported.
182 @subcmd{PERCENTILES} causes the specified percentiles to be reported.
181183 The percentiles should be presented at a list of numbers between 0
182184 and 100 inclusive.
183 The NTILES subcommand causes the percentiles to be reported at the
185 The @subcmd{NTILES} subcommand causes the percentiles to be reported at the
184186 boundaries of the data set divided into the specified number of ranges.
185 For instance, @code{/NTILES=4} would cause quartiles to be reported.
187 For instance, @subcmd{/NTILES=4} would cause quartiles to be reported.
186188
187189 @cindex histogram
188 The HISTOGRAM subcommand causes the output to include a histogram for
190 The @subcmd{HISTOGRAM} subcommand causes the output to include a histogram for
189191 each specified numeric variable. The X axis by default ranges from
190 the minimum to the maximum value observed in the data, but the MINIMUM
191 and MAXIMUM keywords can set an explicit range. Specify NORMAL to
192 the minimum to the maximum value observed in the data, but the @subcmd{MINIMUM}
193 and @subcmd{MAXIMUM} keywords can set an explicit range. Specify @subcmd{NORMAL} to
192194 superimpose a normal curve on the histogram. Histograms are not
193195 created for string variables.
194196
195197 @cindex piechart
196 The PIECHART adds a pie chart for each variable to the data. Each
198 The @subcmd{PIECHART} subcommand adds a pie chart for each variable to the data. Each
197199 slice represents one value, with the size of the slice proportional to
198200 the value's frequency. By default, all non-missing values are given
199 slices. The MINIMUM and MAXIMUM keywords can be used to limit the
200 displayed slices to a given range of values. The MISSING keyword adds
201 slices. The @subcmd{MINIMUM} and @subcmd{MAXIMUM} keywords can be used to limit the
202 displayed slices to a given range of values. The @subcmd{MISSING} keyword adds
201203 slices for missing values.
202204
203 The FREQ and PERCENT options on HISTOGRAM and PIECHART are accepted
204 but not currently honored.
205 The @subcmd{FREQ} and @subcmd{PERCENT} options on @subcmd{HISTOGRAM} and @subcmd{PIECHART} are accepted
206 but not currently honoured.
205207
206208 @node EXAMINE
207 @comment node-name, next, previous, up
208209 @section EXAMINE
210
209211 @vindex EXAMINE
210
212 @cindex Exploratory data analysis
211213 @cindex Normality, testing for
212214
213215 @display
214216 EXAMINE
215 VARIABLES=var_list [BY factor_list ]
216 /STATISTICS=@{DESCRIPTIVES, EXTREME[(n)], ALL, NONE@}
217 /PLOT=@{BOXPLOT, NPPLOT, HISTOGRAM, ALL, NONE@}
218 /CINTERVAL n
217 VARIABLES= @var{var1} [@var{var2}] @dots{} [@var{varN}]
218 [BY @var{factor1} [BY @var{subfactor1}]
219 [ @var{factor2} [BY @var{subfactor2}]]
220 @dots{}
221 [ @var{factor3} [BY @var{subfactor3}]]
222 ]
223 /STATISTICS=@{DESCRIPTIVES, EXTREME[(@var{n})], ALL, NONE@}
224 /PLOT=@{BOXPLOT, NPPLOT, HISTOGRAM, SPREADLEVEL[(@var{t})], ALL, NONE@}
225 /CINTERVAL @var{p}
219226 /COMPARE=@{GROUPS,VARIABLES@}
220 /ID=var_name
227 /ID=@var{identity_variable}
221228 /@{TOTAL,NOTOTAL@}
222 /PERCENTILE=[value_list]=@{HAVERAGE, WAVERAGE, ROUND, AEMPIRICAL, EMPIRICAL @}
229 /PERCENTILE=[@var{percentiles}]=@{HAVERAGE, WAVERAGE, ROUND, AEMPIRICAL, EMPIRICAL @}
223230 /MISSING=@{LISTWISE, PAIRWISE@} [@{EXCLUDE, INCLUDE@}]
224231 [@{NOREPORT,REPORT@}]
225232
226233 @end display
227234
228 The @cmd{EXAMINE} command is used to test how closely a distribution is to a
229 normal distribution. It also shows you outliers and extreme values.
230
231 The VARIABLES subcommand specifies the dependent variables and the
232 independent variable to use as factors for the analysis. Variables
233 listed before the first BY keyword are the dependent variables.
235 The @cmd{EXAMINE} command is used to perform exploratory data analysis.
236 In particular, it is useful for testing how closely a distribution follows a
237 normal distribution, and for finding outliers and extreme values.
238
239 The @subcmd{VARIABLES} subcommand is mandatory.
240 It specifies the dependent variables and optionally variables to use as
241 factors for the analysis.
242 Variables listed before the first @subcmd{BY} keyword (if any) are the
243 dependent variables.
234244 The dependent variables may optionally be followed by a list of
235 factors which tell PSPP how to break down the analysis for each
236 dependent variable. The format for each factor is
237 @display
238 var [BY var].
239 @end display
240
241
242 The STATISTICS subcommand specifies the analysis to be done.
243 DESCRIPTIVES will produce a table showing some parametric and
244 non-parametrics statistics. EXTREME produces a table showing extreme
245 values of the dependent variable. A number in parentheses determines
246 how many upper and lower extremes to show. The default number is 5.
247
245 factors which tell @pspp{} how to break down the analysis for each
246 dependent variable.
247
248 Following the dependent variables, factors may be specified.
249 The factors (if desired) should be preceeded by a single @subcmd{BY} keyword.
250 The format for each factor is
251 @display
252 @var{factorvar} [BY @var{subfactorvar}].
253 @end display
254 Each unique combination of the values of @var{factorvar} and
255 @var{subfactorvar} divide the dataset into @dfn{cells}.
256 Statistics will be calculated for each cell
257 and for the entire dataset (unless @subcmd{NOTOTAL} is given).
258
259 The @subcmd{STATISTICS} subcommand specifies which statistics to show.
260 @subcmd{DESCRIPTIVES} will produce a table showing some parametric and
261 non-parametrics statistics.
262 @subcmd{EXTREME} produces a table showing the extremities of each cell.
263 A number in parentheses, @var{n} determines
264 how many upper and lower extremities to show.
265 The default number is 5.
266
267 The subcommands @subcmd{TOTAL} and @subcmd{NOTOTAL} are mutually exclusive.
268 If @subcmd{TOTAL} appears, then statistics will be produced for the entire dataset
269 as well as for each cell.
270 If @subcmd{NOTOTAL} appears, then statistics will be produced only for the cells
271 (unless no factor variables have been given).
272 These subcommands have no effect if there have been no factor variables
273 specified.
248274
249275 @cindex boxplot
250276 @cindex histogram
251277 @cindex npplot
252 The PLOT subcommand specifies which plots are to be produced if any.
253 Available plots are HISTOGRAM, NPPLOT and BOXPLOT.
254
255 The COMPARE subcommand is only relevant if producing boxplots, and it is only
256 useful there is more than one dependent variable and at least one factor. If
257 /COMPARE=GROUPS is specified, then one plot per dependent variable is produced,
258 containing boxplots for all the factors.
259 If /COMPARE=VARIABLES is specified, then one plot per factor is produced, each
278 @cindex spreadlevel plot
279 The @subcmd{PLOT} subcommand specifies which plots are to be produced if any.
280 Available plots are @subcmd{HISTOGRAM}, @subcmd{NPPLOT}, @subcmd{BOXPLOT} and
281 @subcmd{SPREADLEVEL}.
282 The first three can be used to visualise how closely each cell conforms to a
283 normal distribution, whilst the spread vs.@: level plot can be useful to visualise
284 how the variance of differs between factors.
285 Boxplots will also show you the outliers and extreme values.
286
287 The @subcmd{SPREADLEVEL} plot displays the interquartile range versus the
288 median. It takes an optional parameter @var{t}, which specifies how the data
289 should be transformed prior to plotting.
290 The given value @var{t} is a power to which the data is raised. For example, if
291 @var{t} is given as 2, then the data will be squared.
292 Zero, however is a special value. If @var{t} is 0 or
293 is omitted, then data will be transformed by taking its natural logarithm instead of
294 raising to the power of @var{t}.
295
296 The @subcmd{COMPARE} subcommand is only relevant if producing boxplots, and it is only
297 useful there is more than one dependent variable and at least one factor.
298 If
299 @subcmd{/COMPARE=GROUPS} is specified, then one plot per dependent variable is produced,
300 each of which contain boxplots for all the cells.
301 If @subcmd{/COMPARE=VARIABLES} is specified, then one plot per cell is produced,
260302 each containing one boxplot per dependent variable.
261 If the /COMPARE subcommand is omitted, then PSPP uses the default value of
262 /COMPARE=GROUPS.
303 If the @subcmd{/COMPARE} subcommand is omitted, then @pspp{} behaves as if
304 @subcmd{/COMPARE=GROUPS} were given.
263305
264 The ID subcommand also pertains to boxplots. If given, it must
265 specify a variable name. Outliers and extreme cases plotted in
266 boxplots will be labelled with the case from that variable. Numeric or
267 string variables are permissible. If the ID subcommand is not given,
268 then the casenumber will be used for labelling.
269
270 The CINTERVAL subcommand specifies the confidence interval to use in
271 calculation of the descriptives command. The default it 95%.
306 The @subcmd{ID} subcommand is relevant only if @subcmd{/PLOT=BOXPLOT} or
307 @subcmd{/STATISTICS=EXTREME} has been given.
308 If given, it shoule provide the name of a variable which is to be used
309 to labels extreme values and outliers.
310 Numeric or string variables are permissible.
311 If the @subcmd{ID} subcommand is not given, then the casenumber will be used for
312 labelling.
313
314 The @subcmd{CINTERVAL} subcommand specifies the confidence interval to use in
315 calculation of the descriptives command. The default is 95%.
272316
273317 @cindex percentiles
274 The PERCENTILES subcommand specifies which percentiles are to be calculated,
318 The @subcmd{PERCENTILES} subcommand specifies which percentiles are to be calculated,
275319 and which algorithm to use for calculating them. The default is to
276320 calculate the 5, 10, 25, 50, 75, 90, 95 percentiles using the
277 HAVERAGE algorithm.
278
279 The TOTAL and NOTOTAL subcommands are mutually exclusive. If NOTOTAL
280 is given and factors have been specified in the VARIABLES subcommand,
321 @subcmd{HAVERAGE} algorithm.
322
323 The @subcmd{TOTAL} and @subcmd{NOTOTAL} subcommands are mutually exclusive. If @subcmd{NOTOTAL}
324 is given and factors have been specified in the @subcmd{VARIABLES} subcommand,
281325 then then statistics for the unfactored dependent variables are
282326 produced in addition to the factored variables. If there are no
283 factors specified then TOTAL and NOTOTAL have no effect.
327 factors specified then @subcmd{TOTAL} and @subcmd{NOTOTAL} have no effect.
328
329
330 The following example will generate descriptive statistics and histograms for
331 two variables @var{score1} and @var{score2}.
332 Two factors are given, @i{viz}: @var{gender} and @var{gender} BY @var{culture}.
333 Therefore, the descriptives and histograms will be generated for each
334 distinct value
335 of @var{gender} @emph{and} for each distinct combination of the values
336 of @var{gender} and @var{race}.
337 Since the @subcmd{NOTOTAL} keyword is given, statistics and histograms for
338 @var{score1} and @var{score2} covering the whole dataset are not produced.
339 @example
340 EXAMINE @var{score1} @var{score2} BY
341 @var{gender}
342 @var{gender} BY @var{culture}
343 /STATISTICS = DESCRIPTIVES
344 /PLOT = HISTOGRAM
345 /NOTOTAL.
346 @end example
347
348 Here is a second example showing how the @cmd{examine} command can be used to find extremities.
349 @example
350 EXAMINE @var{height} @var{weight} BY
351 @var{gender}
352 /STATISTICS = EXTREME (3)
353 /PLOT = BOXPLOT
354 /COMPARE = GROUPS
355 /ID = @var{name}.
356 @end example
357 In this example, we look at the height and weight of a sample of individuals and
358 how they differ between male and female.
359 A table showing the 3 largest and the 3 smallest values of @var{height} and
360 @var{weight} for each gender, and for the whole dataset will be shown.
361 Boxplots will also be produced.
362 Because @subcmd{/COMPARE = GROUPS} was given, boxplots for male and female will be
363 shown in the same graphic, allowing us to easily see the difference between
364 the genders.
365 Since the variable @var{name} was specified on the @subcmd{ID} subcommand, this will be
366 used to label the extreme values.
284367
285368 @strong{Warning!}
286 If many dependent variable are given, or factors are given for which
369 If many dependent variables are specified, or if factor variables are
370 specified for which
287371 there are many distinct values, then @cmd{EXAMINE} will produce a very
288372 large quantity of output.
289373
293377 @vindex CORRELATIONS
294378 @display
295379 CORRELATIONS
296 /VARIABLES = varlist [ WITH varlist ]
380 /VARIABLES = @var{var_list} [ WITH @var{var_list} ]
297381 [
298382 .
299383 .
300384 .
301 /VARIABLES = varlist [ WITH varlist ]
302 /VARIABLES = varlist [ WITH varlist ]
385 /VARIABLES = @var{var_list} [ WITH @var{var_list} ]
386 /VARIABLES = @var{var_list} [ WITH @var{var_list} ]
303387 ]
304388
305389 [ /PRINT=@{TWOTAIL, ONETAIL@} @{SIG, NOSIG@} ]
311395 The @cmd{CORRELATIONS} procedure produces tables of the Pearson correlation coefficient
312396 for a set of variables. The significance of the coefficients are also given.
313397
314 At least one VARIABLES subcommand is required. If the WITH keyword is used, then a non-square
315 correlation table will be produced.
316 The variables preceding WITH, will be used as the rows of the table, and the variables following
317 will be the columns of the table.
318 If no WITH subcommand is given, then a square, symmetrical table using all variables is produced.
398 At least one @subcmd{VARIABLES} subcommand is required. If the @subcmd{WITH}
399 keyword is used, then a non-square correlation table will be produced.
400 The variables preceding @subcmd{WITH}, will be used as the rows of the table,
401 and the variables following will be the columns of the table.
402 If no @subcmd{WITH} subcommand is given, then a square, symmetrical table using all variables is produced.
319403
320404
321405 The @cmd{MISSING} subcommand determines the handling of missing variables.
322 If INCLUDE is set, then user-missing values are included in the
406 If @subcmd{INCLUDE} is set, then user-missing values are included in the
323407 calculations, but system-missing values are not.
324 If EXCLUDE is set, which is the default, user-missing
408 If @subcmd{EXCLUDE} is set, which is the default, user-missing
325409 values are excluded as well as system-missing values.
326 This is the default.
327
328 If LISTWISE is set, then the entire case is excluded from analysis
410
411 If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis
329412 whenever any variable specified in any @cmd{/VARIABLES} subcommand
330413 contains a missing value.
331 If PAIRWISE is set, then a case is considered missing only if either of the
414 If @subcmd{PAIRWISE} is set, then a case is considered missing only if either of the
332415 values for the particular coefficient are missing.
333 The default is PAIRWISE.
334
335 The PRINT subcommand is used to control how the reported significance values are printed.
336 If the TWOTAIL option is used, then a two-tailed test of significance is
337 printed. If the ONETAIL option is given, then a one-tailed test is used.
338 The default is TWOTAIL.
339
340 If the NOSIG option is specified, then correlation coefficients with significance less than
416 The default is @subcmd{PAIRWISE}.
417
418 The @subcmd{PRINT} subcommand is used to control how the reported significance values are printed.
419 If the @subcmd{TWOTAIL} option is used, then a two-tailed test of significance is
420 printed. If the @subcmd{ONETAIL} option is given, then a one-tailed test is used.
421 The default is @subcmd{TWOTAIL}.
422
423 If the @subcmd{NOSIG} option is specified, then correlation coefficients with significance less than
341424 0.05 are highlighted.
342 If SIG is specified, then no highlighting is performed. This is the default.
425 If @subcmd{SIG} is specified, then no highlighting is performed. This is the default.
343426
344427 @cindex covariance
345 The STATISTICS subcommand requests additional statistics to be displayed. The keyword
346 DESCRIPTIVES requests that the mean, number of non-missing cases, and the non-biased
428 The @subcmd{STATISTICS} subcommand requests additional statistics to be displayed. The keyword
429 @subcmd{DESCRIPTIVES} requests that the mean, number of non-missing cases, and the non-biased
347430 estimator of the standard deviation are displayed.
348431 These statistics will be displayed in a separated table, for all the variables listed
349 in any /VARIABLES subcommand.
350 The XPROD keyword requests cross-product deviations and covariance estimators to
432 in any @subcmd{/VARIABLES} subcommand.
433 The @subcmd{XPROD} keyword requests cross-product deviations and covariance estimators to
351434 be displayed for each pair of variables.
352 The keyword ALL is the union of DESCRIPTIVES and XPROD.
435 The keyword @subcmd{ALL} is the union of @subcmd{DESCRIPTIVES} and @subcmd{XPROD}.
353436
354437 @node CROSSTABS
355438 @section CROSSTABS
357440 @vindex CROSSTABS
358441 @display
359442 CROSSTABS
360 /TABLES=var_list BY var_list [BY var_list]@dots{}
443 /TABLES=@var{var_list} BY @var{var_list} [BY @var{var_list}]@dots{}
361444 /MISSING=@{TABLE,INCLUDE,REPORT@}
362445 /WRITE=@{NONE,CELLS,ALL@}
363446 /FORMAT=@{TABLES,NOTABLES@}
371454 KAPPA,ETA,CORR,ALL,NONE@}
372455
373456 (Integer mode.)
374 /VARIABLES=var_list (low,high)@dots{}
457 /VARIABLES=@var{var_list} (@var{low},@var{high})@dots{}
375458 @end display
376459
377460 The @cmd{CROSSTABS} procedure displays crosstabulation
379462 each cell in the crosstabulation tables. In addition, a number of
380463 statistics can be calculated for each table itself.
381464
382 The TABLES subcommand is used to specify the tables to be reported. Any
465 The @subcmd{TABLES} subcommand is used to specify the tables to be reported. Any
383466 number of dimensions is permitted, and any number of variables per
384 dimension is allowed. The TABLES subcommand may be repeated as many
467 dimension is allowed. The @subcmd{TABLES} subcommand may be repeated as many
385468 times as needed. This is the only required subcommand in @dfn{general
386469 mode}.
387470
388471 Occasionally, one may want to invoke a special mode called @dfn{integer
389 mode}. Normally, in general mode, PSPP automatically determines
472 mode}. Normally, in general mode, @pspp{} automatically determines
390473 what values occur in the data. In integer mode, the user specifies the
391474 range of values that the data assumes. To invoke this mode, specify the
392 VARIABLES subcommand, giving a range of data values in parentheses for
393 each variable to be used on the TABLES subcommand. Data values inside
475 @subcmd{VARIABLES} subcommand, giving a range of data values in parentheses for
476 each variable to be used on the @subcmd{TABLES} subcommand. Data values inside
394477 the range are truncated to the nearest integer, then assigned to that
395478 value. If values occur outside this range, they are discarded. When it
396 is present, the VARIABLES subcommand must precede the TABLES
479 is present, the @subcmd{VARIABLES} subcommand must precede the @subcmd{TABLES}
397480 subcommand.
398481
399482 In general mode, numeric and string variables may be specified on
400483 TABLES. In integer mode, only numeric variables are allowed.
401484
402 The MISSING subcommand determines the handling of user-missing values.
403 When set to TABLE, the default, missing values are dropped on a table by
404 table basis. When set to INCLUDE, user-missing values are included in
405 tables and statistics. When set to REPORT, which is allowed only in
485 The @subcmd{MISSING} subcommand determines the handling of user-missing values.
486 When set to @subcmd{TABLE}, the default, missing values are dropped on a table by
487 table basis. When set to @subcmd{INCLUDE}, user-missing values are included in
488 tables and statistics. When set to @subcmd{REPORT}, which is allowed only in
406489 integer mode, user-missing values are included in tables but marked with
407490 an @samp{M} (for ``missing'') and excluded from statistical
408491 calculations.
409492
410 Currently the WRITE subcommand is ignored.
411
412 The FORMAT subcommand controls the characteristics of the
493 Currently the @subcmd{WRITE} subcommand is ignored.
494
495 The @subcmd{FORMAT} subcommand controls the characteristics of the
413496 crosstabulation tables to be displayed. It has a number of possible
414497 settings:
415498
416 @itemize @bullet
499 @itemize @asis
417500 @item
418 TABLES, the default, causes crosstabulation tables to be output.
419 NOTABLES suppresses them.
501 @subcmd{TABLES}, the default, causes crosstabulation tables to be output.
502 @subcmd{NOTABLES} suppresses them.
420503
421504 @item
422 PIVOT, the default, causes each TABLES subcommand to be displayed in a
423 pivot table format. NOPIVOT causes the old-style crosstabulation format
505 @subcmd{PIVOT}, the default, causes each @subcmd{TABLES} subcommand to be displayed in a
506 pivot table format. @subcmd{NOPIVOT} causes the old-style crosstabulation format
424507 to be used.
425508
426509 @item
427 AVALUE, the default, causes values to be sorted in ascending order.
428 DVALUE asserts a descending sort order.
510 @subcmd{AVALUE}, the default, causes values to be sorted in ascending order.
511 @subcmd{DVALUE} asserts a descending sort order.
429512
430513 @item
431 INDEX/NOINDEX is currently ignored.
514 @subcmd{INDEX} and @subcmd{NOINDEX} are currently ignored.
432515
433516 @item
434 BOX/NOBOX is currently ignored.
517 @subcmd{BOX} and @subcmd{NOBOX} is currently ignored.
435518 @end itemize
436519
437 The CELLS subcommand controls the contents of each cell in the displayed
520 The @subcmd{CELLS} subcommand controls the contents of each cell in the displayed
438521 crosstabulation table. The possible settings are:
439522
440523 @table @asis
460543 Suppress cells entirely.
461544 @end table
462545
463 @samp{/CELLS} without any settings specified requests COUNT, ROW,
464 COLUMN, and TOTAL. If CELLS is not specified at all then only COUNT
546 @samp{/CELLS} without any settings specified requests @subcmd{COUNT}, @subcmd{ROW},
547 @subcmd{COLUMN}, and @subcmd{TOTAL}.
548 If @subcmd{CELLS} is not specified at all then only @subcmd{COUNT}
465549 will be selected.
466550
467 The STATISTICS subcommand selects statistics for computation:
551 The @subcmd{STATISTICS} subcommand selects statistics for computation:
468552
469553 @table @asis
470554 @item CHISQ
508592 some statistics are calculated only in integer mode.
509593
510594 @samp{/STATISTICS} without any settings selects CHISQ. If the
511 STATISTICS subcommand is not given, no statistics are calculated.
512
513 @strong{Please note:} Currently the implementation of CROSSTABS has the
595 @subcmd{STATISTICS} subcommand is not given, no statistics are calculated.
596
597 @strong{Please note:} Currently the implementation of @cmd{CROSSTABS} has the
514598 followings bugs:
515599
516600 @itemize @bullet
542626 @cindex data reduction
543627
544628 @display
545 FACTOR VARIABLES=var_list
629 FACTOR VARIABLES=@var{var_list}
546630
547631 [ /METHOD = @{CORRELATION, COVARIANCE@} ]
548632
561645 [ /MISSING=[@{LISTWISE, PAIRWISE@}] [@{INCLUDE, EXCLUDE@}] ]
562646 @end display
563647
564 The FACTOR command performs Factor Analysis or Principal Axis Factoring on a dataset. It may be used to find
648 The @cmd{FACTOR} command performs Factor Analysis or Principal Axis Factoring on a dataset. It may be used to find
565649 common factors in the data or for data reduction purposes.
566650
567 The VARIABLES subcommand is required. It lists the variables which are to partake in the analysis.
568
569 The /EXTRACTION subcommand is used to specify the way in which factors (components) are extracted from the data.
570 If PC is specified, then Principal Components Analysis is used. If PAF is specified, then Principal Axis Factoring is
651 The @subcmd{VARIABLES} subcommand is required. It lists the variables which are to partake in the analysis.
652
653 The @subcmd{/EXTRACTION} subcommand is used to specify the way in which factors (components) are extracted from the data.
654 If @subcmd{PC} is specified, then Principal Components Analysis is used.
655 If @subcmd{PAF} is specified, then Principal Axis Factoring is
571656 used. By default Principal Components Analysis will be used.
572657
573 The /ROTATION subcommand is used to specify the method by which the extracted solution will be rotated.
574 Three methods are available: VARIMAX (which is the default), EQUAMAX, and QUARTIMAX.
575 If don't want any rotation to be performed, the word NOROTATE will prevent the command from performing any
658 The @subcmd{/ROTATION} subcommand is used to specify the method by which the extracted solution will be rotated.
659 Three methods are available: @subcmd{VARIMAX} (which is the default), @subcmd{EQUAMAX}, and @subcmd{QUARTIMAX}.
660 If don't want any rotation to be performed, the word @subcmd{NOROTATE} will prevent the command from performing any
576661 rotation on the data. Oblique rotations are not supported.
577662
578 The /METHOD subcommand should be used to determine whether the covariance matrix or the correlation matrix of the data is
663 The @subcmd{/METHOD} subcommand should be used to determine whether the covariance matrix or the correlation matrix of the data is
579664 to be analysed. By default, the correlation matrix is analysed.
580665
581 The /PRINT subcommand may be used to select which features of the analysis are reported:
582
583 @itemize
584 @item UNIVARIATE
666 The @subcmd{/PRINT} subcommand may be used to select which features of the analysis are reported:
667
668 @itemize
669 @item @subcmd{UNIVARIATE}
585670 A table of mean values, standard deviations and total weights are printed.
586 @item INITIAL
671 @item @subcmd{INITIAL}
587672 Initial communalities and eigenvalues are printed.
588 @item EXTRACTION
673 @item @subcmd{EXTRACTION}
589674 Extracted communalities and eigenvalues are printed.
590 @item ROTATION
675 @item @subcmd{ROTATION}
591676 Rotated communalities and eigenvalues are printed.
592 @item CORRELATION
677 @item @subcmd{CORRELATION}
593678 The correlation matrix is printed.
594 @item COVARIANCE
679 @item @subcmd{COVARIANCE}
595680 The covariance matrix is printed.
596 @item DET
681 @item @subcmd{DET}
597682 The determinant of the correlation or covariance matrix is printed.
598 @item KMO
683 @item @subcmd{KMO}
599684 The Kaiser-Meyer-Olkin measure of sampling adequacy and the Bartlett test of sphericity is printed.
600 @item SIG
685 @item @subcmd{SIG}
601686 The significance of the elements of correlation matrix is printed.
602 @item ALL
687 @item @subcmd{ALL}
603688 All of the above are printed.
604 @item DEFAULT
605 Identical to INITIAL and EXTRACTION.
689 @item @subcmd{DEFAULT}
690 Identical to @subcmd{INITIAL} and @subcmd{EXTRACTION}.
606691 @end itemize
607692
608 If /PLOT=EIGEN is given, then a ``Scree'' plot of the eigenvalues will be printed. This can be useful for visualizing
693 If @subcmd{/PLOT=EIGEN} is given, then a ``Scree'' plot of the eigenvalues will be printed. This can be useful for visualizing
609694 which factors (components) should be retained.
610695
611 The /FORMAT subcommand determined how data are to be displayed in loading matrices. If SORT is specified, then the variables
612 are sorted in descending order of significance. If BLANK(@var{n}) is specified, then coefficients whose absolute value is less
613 than @var{n} will not be printed. If the keyword DEFAULT is given, or if no /FORMAT subcommand is given, then no sorting is
696 The @subcmd{/FORMAT} subcommand determined how data are to be displayed in loading matrices. If @subcmd{SORT} is specified, then the variables
697 are sorted in descending order of significance. If @subcmd{BLANK(@var{n})} is specified, then coefficients whose absolute value is less
698 than @var{n} will not be printed. If the keyword @subcmd{DEFAULT} is given, or if no @subcmd{/FORMAT} subcommand is given, then no sorting is
614699 performed, and all coefficients will be printed.
615700
616 The /CRITERIA subcommand is used to specify how the number of extracted factors (components) are chosen. If FACTORS(@var{n}) is
617 specified, where @var{n} is an integer, then @var{n} factors will be extracted. Otherwise, the MINEIGEN setting will
618 be used. MINEIGEN(@var{l}) requests that all factors whose eigenvalues are greater than or equal to @var{l} are extracted.
619 The default value of @var{l} is 1. The ECONVERGE and ITERATE settings have effect only when iterative algorithms for factor
620 extraction (such as Principal Axis Factoring) are used. ECONVERGE(@var{delta}) specifies that iteration should cease when
701 The @subcmd{/CRITERIA} subcommand is used to specify how the number of extracted factors (components) are chosen.
702 If @subcmd{FACTORS(@var{n})} is
703 specified, where @var{n} is an integer, then @var{n} factors will be extracted. Otherwise, the @subcmd{MINEIGEN} setting will
704 be used. @subcmd{MINEIGEN(@var{l})} requests that all factors whose eigenvalues are greater than or equal to @var{l} are extracted.
705 The default value of @var{l} is 1. The @subcmd{ECONVERGE} and @subcmd{ITERATE} settings have effect only when iterative algorithms for factor
706 extraction (such as Principal Axis Factoring) are used. @subcmd{ECONVERGE(@var{delta})} specifies that
707 iteration should cease when
621708 the maximum absolute value of the communality estimate between one iteration and the previous is less than @var{delta}. The
622709 default value of @var{delta} is 0.001.
623 The ITERATE(@var{m}) setting sets the maximum number of iterations to @var{m}. The default value of @var{m} is 25.
710 The @subcmd{ITERATE(@var{m})} setting sets the maximum number of iterations to @var{m}. The default value of @var{m} is 25.
624711
625712 The @cmd{MISSING} subcommand determines the handling of missing variables.
626 If INCLUDE is set, then user-missing values are included in the
713 If @subcmd{INCLUDE} is set, then user-missing values are included in the
627714 calculations, but system-missing values are not.
628 If EXCLUDE is set, which is the default, user-missing
715 If @subcmd{EXCLUDE} is set, which is the default, user-missing
629716 values are excluded as well as system-missing values.
630717 This is the default.
631 If LISTWISE is set, then the entire case is excluded from analysis
718 If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis
632719 whenever any variable specified in the @cmd{VARIABLES} subcommand
633720 contains a missing value.
634 If PAIRWISE is set, then a case is considered missing only if either of the
721 If @subcmd{PAIRWISE} is set, then a case is considered missing only if either of the
635722 values for the particular coefficient are missing.
636 The default is LISTWISE.
723 The default is @subcmd{LISTWISE}.
637724
638725 @node MEANS
639726 @section MEANS
643730
644731 @display
645732 MEANS [TABLES =]
646 @{varlist@}
647 [ BY @{varlist@} [BY @{varlist@} [BY @{varlist@} @dots{} ]]]
648
649 [ /@{varlist@}
650 [ BY @{varlist@} [BY @{varlist@} [BY @{varlist@} @dots{} ]]] ]
733 @{@var{var_list}@}
734 [ BY @{@var{var_list}@} [BY @{@var{var_list}@} [BY @{@var{var_list}@} @dots{} ]]]
735
736 [ /@{@var{var_list}@}
737 [ BY @{@var{var_list}@} [BY @{@var{var_list}@} [BY @{@var{var_list}@} @dots{} ]]] ]
651738
652739 [/CELLS = [MEAN] [COUNT] [STDDEV] [SEMEAN] [SUM] [MIN] [MAX] [RANGE]
653740 [VARIANCE] [KURT] [SEKURT]
660747 [/MISSING = [TABLE] [INCLUDE] [DEPENDENT]]
661748 @end display
662749
663 You can use the MEANS command to calculate the arithmetic mean and similar
750 You can use the @cmd{MEANS} command to calculate the arithmetic mean and similar
664751 statistics, either for the dataset as a whole or for categories of data.
665752
666753 The simplest form of the command is
683770 This example calculates the harmonic mean, the sum and the minimum values of @var{x} and @var{y}
684771 grouped by @var{g}.
685772
686 The CELLS subcommand specifies which statistics to calculate. The available statistics
773 The @subcmd{CELLS} subcommand specifies which statistics to calculate. The available statistics
687774 are:
688775 @itemize
689 @item MEAN
776 @item @subcmd{MEAN}
690777 @cindex arithmetic mean
691778 The arithmetic mean.
692 @item COUNT
779 @item @subcmd{COUNT}
693780 The count of the values.
694 @item STDDEV
781 @item @subcmd{STDDEV}
695782 The standard deviation.
696 @item SEMEAN
783 @item @subcmd{SEMEAN}
697784 The standard error of the mean.
698 @item SUM
785 @item @subcmd{SUM}
699786 The sum of the values.
700 @item MIN
787 @item @subcmd{MIN}
701788 The minimum value.
702 @item MAX
789 @item @subcmd{MAX}
703790 The maximum value.
704 @item RANGE
791 @item @subcmd{RANGE}
705792 The difference between the maximum and minimum values.
706 @item VARIANCE
793 @item @subcmd{VARIANCE}
707794 The variance.
708 @item FIRST
795 @item @subcmd{FIRST}
709796 The first value in the category.
710 @item LAST
797 @item @subcmd{LAST}
711798 The last value in the category.
712 @item SKEW
799 @item @subcmd{SKEW}
713800 The skewness.
714 @item SESKEW
801 @item @subcmd{SESKEW}
715802 The standard error of the skewness.
716 @item KURT
803 @item @subcmd{KURT}
717804 The kurtosis
718 @item SEKURT
805 @item @subcmd{SEKURT}
719806 The standard error of the kurtosis.
720 @item HARMONIC
807 @item @subcmd{HARMONIC}
721808 @cindex harmonic mean
722809 The harmonic mean.
723 @item GEOMETRIC
810 @item @subcmd{GEOMETRIC}
724811 @cindex geometric mean
725812 The geometric mean.
726813 @end itemize
727814
728815 In addition, three special keywords are recognized:
729816 @itemize
730 @item DEFAULT
731 This is the same as MEAN COUNT STDDEV
732 @item ALL
817 @item @subcmd{DEFAULT}
818 This is the same as @subcmd{MEAN} @subcmd{COUNT} @subcmd{STDDEV}.
819 @item @subcmd{ALL}
733820 All of the above statistics will be calculated.
734 @item NONE
821 @item @subcmd{NONE}
735822 No statistics will be calculated (only a summary will be shown).
736823 @end itemize
737824
758845 (either system missing or user missing)
759846 for any of the variables directly involved in their calculation are
760847 encountered.
761 This behaviour can be modified with the /MISSING subcommand.
762 Three options are possible: TABLE, INCLUDE and DEPENDENT.
763
764 /MISSING = TABLE causes cases to be dropped if any variable is missing
848 This behaviour can be modified with the @subcmd{/MISSING} subcommand.
849 Three options are possible: @subcmd{TABLE}, @subcmd{INCLUDE} and @subcmd{DEPENDENT}.
850
851 @subcmd{/MISSING = TABLE} causes cases to be dropped if any variable is missing
765852 in the table specification currently being processed, regardless of
766853 whether it is needed to calculate the statistic.
767854
768 /MISSING = INCLUDE says that user missing values, either in the dependent
855 @subcmd{/MISSING = INCLUDE} says that user missing values, either in the dependent
769856 variables or in the categorical variables should be taken at their face
770857 value, and not excluded.
771858
772 /MISSING = DEPENDENT says that user missing values, in the dependent
859 @subcmd{/MISSING = DEPENDENT} says that user missing values, in the dependent
773860 variables should be taken at their face value, however cases which
774861 have user missing values for the categorical variables should be omitted
775862 from the calculation.
792879
793880 [ /MISSING=@{ANALYSIS, LISTWISE@} @{INCLUDE, EXCLUDE@} ]
794881
795 [ /METHOD=EXACT [ TIMER [(n)] ] ]
796 @end display
797
798 NPAR TESTS performs nonparametric tests.
882 [ /METHOD=EXACT [ TIMER [(@var{n})] ] ]
883 @end display
884
885 @cmd{NPAR TESTS} performs nonparametric tests.
799886 Non parametric tests make very few assumptions about the distribution of the
800887 data.
801888 One or more tests may be specified by using the corresponding subcommand.
802 If the /STATISTICS subcommand is also specified, then summary statistics are
889 If the @subcmd{/STATISTICS} subcommand is also specified, then summary statistics are
803890 produces for each variable that is the subject of any test.
804891
805892 Certain tests may take a long time to execute, if an exact figure is required.
806893 Therefore, by default asymptotic approximations are used unless the
807 subcommand /METHOD=EXACT is specified.
894 subcommand @subcmd{/METHOD=EXACT} is specified.
808895 Exact tests give more accurate results, but may take an unacceptably long
809 time to perform. If the TIMER keyword is used, it sets a maximum time,
896 time to perform. If the @subcmd{TIMER} keyword is used, it sets a maximum time,
810897 after which the test will be abandoned, and a warning message printed.
811 The time, in minutes, should be specified in parentheses after the TIMER keyword.
812 If the TIMER keyword is given without this figure, then a default value of 5 minutes
898 The time, in minutes, should be specified in parentheses after the @subcmd{TIMER} keyword.
899 If the @subcmd{TIMER} keyword is given without this figure, then a default value of 5 minutes
813900 is used.
814901
815902
836923 @cindex binomial test
837924
838925 @display
839 [ /BINOMIAL[(p)]=var_list[(value1[, value2)] ] ]
926 [ /BINOMIAL[(@var{p})]=@var{var_list}[(@var{value1}[, @var{value2})] ] ]
840927 @end display
841928
842 The /BINOMIAL subcommand compares the observed distribution of a dichotomous
929 The @subcmd{/BINOMIAL} subcommand compares the observed distribution of a dichotomous
843930 variable with that of a binomial distribution.
844931 The variable @var{p} specifies the test proportion of the binomial
845932 distribution.
872959 That is to say, the test is always performed in the observed
873960 direction.
874961
875 PSPP uses a very precise approximation to the gamma function to
962 @pspp{} uses a very precise approximation to the gamma function to
876963 compute the binomial significance. Thus, exact results are reported
877964 even for very large sample sizes.
878965
885972
886973
887974 @display
888 [ /CHISQUARE=var_list[(lo,hi)] [/EXPECTED=@{EQUAL|f1, f2 @dots{} fn@}] ]
975 [ /CHISQUARE=@var{var_list}[(@var{lo},@var{hi})] [/EXPECTED=@{EQUAL|@var{f1}, @var{f2} @dots{} @var{fn}@}] ]
889976 @end display
890977
891978
892 The /CHISQUARE subcommand produces a chi-square statistic for the differences
979 The @subcmd{/CHISQUARE} subcommand produces a chi-square statistic for the differences
893980 between the expected and observed frequencies of the categories of a variable.
894981 Optionally, a range of values may appear after the variable list.
895982 If a range is given, then non integer values are truncated, and values
896983 outside the specified range are excluded from the analysis.
897984
898 The /EXPECTED subcommand specifies the expected values of each
985 The @subcmd{/EXPECTED} subcommand specifies the expected values of each
899986 category.
900987 There must be exactly one non-zero expected value, for each observed
901 category, or the EQUAL keywork must be specified.
902 You may use the notation @var{n}*@var{f} to specify @var{n}
988 category, or the @subcmd{EQUAL} keywork must be specified.
989 You may use the notation @subcmd{@var{n}*@var{f}} to specify @var{n}
903990 consecutive expected categories all taking a frequency of @var{f}.
904991 The frequencies given are proportions, not absolute frequencies. The
905992 sum of the frequencies need not be 1.
906 If no /EXPECTED subcommand is given, then then equal frequencies
993 If no @subcmd{/EXPECTED} subcommand is given, then then equal frequencies
907994 are expected.
908995
909996
9141001 @cindex Q, Cochran Q
9151002
9161003 @display
917 [ /COCHRAN = varlist ]
1004 [ /COCHRAN = @var{var_list} ]
9181005 @end display
9191006
9201007 The Cochran Q test is used to test for differences between three or more groups.
921 The data for @var{varlist} in all cases must assume exactly two distinct values (other than missing values).
1008 The data for @var{var_list} in all cases must assume exactly two distinct values (other than missing values).
9221009
9231010 The value of Q will be displayed and its Asymptotic significance based on a chi-square distribution.
9241011
9281015 @cindex Friedman test
9291016
9301017 @display
931 [ /FRIEDMAN = varlist ]
932 @end display
933
934 The Friedman test is used to test for differences between repeated measures when there is no indication that the distributions are normally distributed.
935
936 A list of variables which contain the measured data must be given. The procedure prints the sum of ranks for each variable, the test statistic and its significance.
1018 [ /FRIEDMAN = @var{var_list} ]
1019 @end display
1020
1021 The Friedman test is used to test for differences between repeated measures when
1022 there is no indication that the distributions are normally distributed.
1023
1024 A list of variables which contain the measured data must be given. The procedure
1025 prints the sum of ranks for each variable, the test statistic and its significance.
9371026
9381027 @node KENDALL
9391028 @subsection Kendall's W Test
9421031 @cindex coefficient of concordance
9431032
9441033 @display
945 [ /KENDALL = varlist ]
1034 [ /KENDALL = @var{var_list} ]
9461035 @end display
9471036
9481037 The Kendall test investigates whether an arbitrary number of related samples come from the
9591048 @cindex Kolmogorov-Smirnov test
9601049
9611050 @display
962 [ /KOLMOGOROV-SMIRNOV (@{NORMAL [@var{mu}, @var{sigma}], UNIFORM [@var{min}, @var{max}], POISSON [@var{lambda}], EXPONENTIAL [@var{scale}] @}) = varlist ]
1051 [ /KOLMOGOROV-SMIRNOV (@{NORMAL [@var{mu}, @var{sigma}], UNIFORM [@var{min}, @var{max}], POISSON [@var{lambda}], EXPONENTIAL [@var{scale}] @}) = @var{var_list} ]
9631052 @end display
9641053
9651054 The one sample Kolmogorov-Smirnov subcommand is used to test whether or not a dataset is
9891078 /KOLMOGOROV-SMIRNOV (normal 40 1.5) = @var{age}.
9901079 @end example
9911080
992 The abbreviated subcommand K-S may be used in place of KOLMOGOROV-SMIRNOV.
1081 The abbreviated subcommand @subcmd{K-S} may be used in place of @subcmd{KOLMOGOROV-SMIRNOV}.
9931082
9941083 @node KRUSKAL-WALLIS
9951084 @subsection Kruskal-Wallis Test
9981087 @cindex Kruskal-Wallis test
9991088
10001089 @display
1001 [ /KRUSKAL-WALLIS = varlist BY var (lower, upper) ]
1090 [ /KRUSKAL-WALLIS = @var{var_list} BY var (@var{lower}, @var{upper}) ]
10021091 @end display
10031092
10041093 The Kruskal-Wallis test is used to compare data from an
10051094 arbitrary number of populations. It does not assume normality.
1006 The data to be compared are specified by @var{varlist}.
1095 The data to be compared are specified by @var{var_list}.
10071096 The categorical variable determining the groups to which the
10081097 data belongs is given by @var{var}. The limits @var{lower} and
10091098 @var{upper} specify the valid range of @var{var}. Any cases for
10121101
10131102 The mean rank of each group as well as the chi-squared value and significance
10141103 of the test will be printed.
1015 The abbreviated subcommand K-W may be used in place of KRUSKAL-WALLIS.
1104 The abbreviated subcommand @subcmd{K-W} may be used in place of @subcmd{KRUSKAL-WALLIS}.
10161105
10171106
10181107 @node MANN-WHITNEY
10231112 @cindex U, Mann-Whitney U
10241113
10251114 @display
1026 [ /MANN-WHITNEY = varlist BY var (group1, group2) ]
1115 [ /MANN-WHITNEY = @var{var_list} BY var (@var{group1}, @var{group2}) ]
10271116 @end display
10281117
10291118 The Mann-Whitney subcommand is used to test whether two groups of data come from different populations.
1030 The variables to be tested should be specified in @var{varlist} and the grouping variable, that determines to which group the test variables belong, in @var{var}.
1119 The variables to be tested should be specified in @var{var_list} and the grouping variable, that determines to which group the test variables belong, in @var{var}.
10311120 @var{Var} may be either a string or an alpha variable.
10321121 @var{Group1} and @var{group2} specify the
10331122 two values of @var{var} which determine the groups of the test data.
10341123 Cases for which the @var{var} value is neither @var{group1} or @var{group2} will be ignored.
10351124
10361125 The value of the Mann-Whitney U statistic, the Wilcoxon W, and the significance will be printed.
1037 The abbreviated subcommand M-W may be used in place of MANN-WHITNEY.
1126 The abbreviated subcommand @subcmd{M-W} may be used in place of @subcmd{MANN-WHITNEY}.
10381127
10391128 @node MCNEMAR
10401129 @subsection McNemar Test
10421131 @cindex McNemar test
10431132
10441133 @display
1045 [ /MCNEMAR varlist [ WITH varlist [ (PAIRED) ]]]
1134 [ /MCNEMAR @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]]
10461135 @end display
10471136
10481137 Use McNemar's test to analyse the significance of the difference between
10701159 @cindex Median test
10711160
10721161 @display
1073 [ /MEDIAN [(value)] = varlist BY variable (value1, value2) ]
1162 [ /MEDIAN [(@var{value})] = @var{var_list} BY @var{variable} (@var{value1}, @var{value2}) ]
10741163 @end display
10751164
10761165 The median test is used to test whether independent samples come from
10771166 populations with a common median.
10781167 The median of the populations against which the samples are to be tested
10791168 may be given in parentheses immediately after the
1080 /MEDIAN subcommand. If it is not given, the median will be imputed from the
1169 @subcmd{/MEDIAN} subcommand. If it is not given, the median will be imputed from the
10811170 union of all the samples.
10821171
10831172 The variables of the samples to be tested should immediately follow the @samp{=} sign. The
10951184 @cindex runs test
10961185
10971186 @display
1098 [ /RUNS (@{MEAN, MEDIAN, MODE, value@}) = varlist ]
1099 @end display
1100
1101 The /RUNS subcommand tests whether a data sequence is randomly ordered.
1187 [ /RUNS (@{MEAN, MEDIAN, MODE, @var{value}@}) = @var{var_list} ]
1188 @end display
1189
1190 The @subcmd{/RUNS} subcommand tests whether a data sequence is randomly ordered.
11021191
11031192 It works by examining the number of times a variable's value crosses a given threshold.
11041193 The desired threshold must be specified within parentheses.
1105 It may either be specified as a number or as one of MEAN, MEDIAN or MODE.
1194 It may either be specified as a number or as one of @subcmd{MEAN}, @subcmd{MEDIAN} or @subcmd{MODE}.
11061195 Following the threshold specification comes the list of variables whose values are to be
11071196 tested.
11081197
11151204 @cindex sign test
11161205
11171206 @display
1118 [ /SIGN varlist [ WITH varlist [ (PAIRED) ]]]
1119 @end display
1120
1121 The /SIGN subcommand tests for differences between medians of the
1207 [ /SIGN @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]]
1208 @end display
1209
1210 The @subcmd{/SIGN} subcommand tests for differences between medians of the
11221211 variables listed.
11231212 The test does not make any assumptions about the
11241213 distribution of the data.
11371226
11381227 @node WILCOXON
11391228 @subsection Wilcoxon Matched Pairs Signed Ranks Test
1140 @comment node-name, next, previous, up
11411229 @vindex WILCOXON
11421230 @cindex wilcoxon matched pairs signed ranks test
11431231
11441232 @display
1145 [ /WILCOXON varlist [ WITH varlist [ (PAIRED) ]]]
1146 @end display
1147
1148 The /WILCOXON subcommand tests for differences between medians of the
1233 [ /WILCOXON @var{var_list} [ WITH @var{var_list} [ (PAIRED) ]]]
1234 @end display
1235
1236 The @subcmd{/WILCOXON} subcommand tests for differences between medians of the
11491237 variables listed.
11501238 The test does not make any assumptions about the variances of the samples.
11511239 It does however assume that the distribution is symetrical.
11521240
1153 If the @code{WITH} keyword is omitted, then tests for all
1241 If the @subcmd{WITH} keyword is omitted, then tests for all
11541242 combinations of the listed variables are performed.
1155 If the @code{WITH} keyword is given, and the @code{(PAIRED)} keyword
1156 is also given, then the number of variables preceding @code{WITH}
1243 If the @subcmd{WITH} keyword is given, and the @subcmd{(PAIRED)} keyword
1244 is also given, then the number of variables preceding @subcmd{WITH}
11571245 must be the same as the number following it.
11581246 In this case, tests for each respective pair of variables are
11591247 performed.
1160 If the @code{WITH} keyword is given, but the
1161 @code{(PAIRED)} keyword is omitted, then tests for each combination
1162 of variable preceding @code{WITH} against variable following
1163 @code{WITH} are performed.
1248 If the @subcmd{WITH} keyword is given, but the
1249 @subcmd{(PAIRED)} keyword is omitted, then tests for each combination
1250 of variable preceding @subcmd{WITH} against variable following
1251 @subcmd{WITH} are performed.
11641252
11651253 @node T-TEST
1166 @comment node-name, next, previous, up
11671254 @section T-TEST
11681255
11691256 @vindex T-TEST
11711258 @display
11721259 T-TEST
11731260 /MISSING=@{ANALYSIS,LISTWISE@} @{EXCLUDE,INCLUDE@}
1174 /CRITERIA=CIN(confidence)
1261 /CRITERIA=CIN(@var{confidence})
11751262
11761263
11771264 (One Sample mode.)
1178 TESTVAL=test_value
1179 /VARIABLES=var_list
1265 TESTVAL=@var{test_value}
1266 /VARIABLES=@var{var_list}
11801267
11811268
11821269 (Independent Samples mode.)
1183 GROUPS=var(value1 [, value2])
1184 /VARIABLES=var_list
1270 GROUPS=var(@var{value1} [, @var{value2}])
1271 /VARIABLES=@var{var_list}
11851272
11861273
11871274 (Paired Samples mode.)
1188 PAIRS=var_list [WITH var_list [(PAIRED)] ]
1275 PAIRS=@var{var_list} [WITH @var{var_list} [(PAIRED)] ]
11891276
11901277 @end display
11911278
12031290 Each of these modes are described in more detail below.
12041291 There are two optional subcommands which are common to all modes.
12051292
1206 The @cmd{/CRITERIA} subcommand tells PSPP the confidence interval used
1293 The @cmd{/CRITERIA} subcommand tells @pspp{} the confidence interval used
12071294 in the tests. The default value is 0.95.
12081295
12091296
12101297 The @cmd{MISSING} subcommand determines the handling of missing
12111298 variables.
1212 If INCLUDE is set, then user-missing values are included in the
1299 If @subcmd{INCLUDE} is set, then user-missing values are included in the
12131300 calculations, but system-missing values are not.
1214 If EXCLUDE is set, which is the default, user-missing
1301 If @subcmd{EXCLUDE} is set, which is the default, user-missing
12151302 values are excluded as well as system-missing values.
12161303 This is the default.
12171304
1218 If LISTWISE is set, then the entire case is excluded from analysis
1219 whenever any variable specified in the @cmd{/VARIABLES}, @cmd{/PAIRS} or
1220 @cmd{/GROUPS} subcommands contains a missing value.
1221 If ANALYSIS is set, then missing values are excluded only in the analysis for
1305 If @subcmd{LISTWISE} is set, then the entire case is excluded from analysis
1306 whenever any variable specified in the @subcmd{/VARIABLES}, @subcmd{/PAIRS} or
1307 @subcmd{/GROUPS} subcommands contains a missing value.
1308 If @subcmd{ANALYSIS} is set, then missing values are excluded only in the analysis for
12221309 which they would be needed. This is the default.
12231310
12241311
12311318 @node One Sample Mode
12321319 @subsection One Sample Mode
12331320
1234 The @cmd{TESTVAL} subcommand invokes the One Sample mode.
1321 The @subcmd{TESTVAL} subcommand invokes the One Sample mode.
12351322 This mode is used to test a population mean against a hypothesized
12361323 mean.
1237 The value given to the @cmd{TESTVAL} subcommand is the value against
1324 The value given to the @subcmd{TESTVAL} subcommand is the value against
12381325 which you wish to test.
1239 In this mode, you must also use the @cmd{/VARIABLES} subcommand to
1240 tell PSPP which variables you wish to test.
1326 In this mode, you must also use the @subcmd{/VARIABLES} subcommand to
1327 tell @pspp{} which variables you wish to test.
12411328
12421329 @node Independent Samples Mode
1243 @comment node-name, next, previous, up
12441330 @subsection Independent Samples Mode
12451331
1246 The @cmd{GROUPS} subcommand invokes Independent Samples mode or
1332 The @subcmd{GROUPS} subcommand invokes Independent Samples mode or
12471333 `Groups' mode.
12481334 This mode is used to test whether two groups of values have the
12491335 same population mean.
1250 In this mode, you must also use the @cmd{/VARIABLES} subcommand to
1251 tell PSPP the dependent variables you wish to test.
1252
1253 The variable given in the @cmd{GROUPS} subcommand is the independent
1336 In this mode, you must also use the @subcmd{/VARIABLES} subcommand to
1337 tell @pspp{} the dependent variables you wish to test.
1338
1339 The variable given in the @subcmd{GROUPS} subcommand is the independent
12541340 variable which determines to which group the samples belong.
12551341 The values in parentheses are the specific values of the independent
12561342 variable for each group.
12621348 If you do this, cases where the independent variable is
12631349 greater than or equal to this value belong to the first group, and cases
12641350 less than this value belong to the second group.
1265 When using this form of the @cmd{GROUPS} subcommand, missing values in
1351 When using this form of the @subcmd{GROUPS} subcommand, missing values in
12661352 the independent variable are excluded on a listwise basis, regardless
1267 of whether @cmd{/MISSING=LISTWISE} was specified.
1353 of whether @subcmd{/MISSING=LISTWISE} was specified.
12681354
12691355
12701356 @node Paired Samples Mode
1271 @comment node-name, next, previous, up
12721357 @subsection Paired Samples Mode
12731358
12741359 The @cmd{PAIRS} subcommand introduces Paired Samples mode.
12751360 Use this mode when repeated measures have been taken from the same
12761361 samples.
1277 If the @code{WITH} keyword is omitted, then tables for all
1362 If the @subcmd{WITH} keyword is omitted, then tables for all
12781363 combinations of variables given in the @cmd{PAIRS} subcommand are
12791364 generated.
1280 If the @code{WITH} keyword is given, and the @code{(PAIRED)} keyword
1281 is also given, then the number of variables preceding @code{WITH}
1365 If the @subcmd{WITH} keyword is given, and the @subcmd{(PAIRED)} keyword
1366 is also given, then the number of variables preceding @subcmd{WITH}
12821367 must be the same as the number following it.
12831368 In this case, tables for each respective pair of variables are
12841369 generated.
1285 In the event that the @code{WITH} keyword is given, but the
1286 @code{(PAIRED)} keyword is omitted, then tables for each combination
1287 of variable preceding @code{WITH} against variable following
1288 @code{WITH} are generated.
1370 In the event that the @subcmd{WITH} keyword is given, but the
1371 @subcmd{(PAIRED)} keyword is omitted, then tables for each combination
1372 of variable preceding @subcmd{WITH} against variable following
1373 @subcmd{WITH} are generated.
12891374
12901375
12911376 @node ONEWAY
1292 @comment node-name, next, previous, up
12931377 @section ONEWAY
12941378
12951379 @vindex ONEWAY
12981382
12991383 @display
13001384 ONEWAY
1301 [/VARIABLES = ] var_list BY var
1385 [/VARIABLES = ] @var{var_list} BY @var{var}
13021386 /MISSING=@{ANALYSIS,LISTWISE@} @{EXCLUDE,INCLUDE@}
1303 /CONTRAST= value1 [, value2] ... [,valueN]
1387 /CONTRAST= @var{value1} [, @var{value2}] ... [,@var{valueN}]
13041388 /STATISTICS=@{DESCRIPTIVES,HOMOGENEITY@}
1305 /POSTHOC=@{BONFERRONI, GH, LSD, SCHEFFE, SIDAK, TUKEY, ALPHA ([value])@}
1389 /POSTHOC=@{BONFERRONI, GH, LSD, SCHEFFE, SIDAK, TUKEY, ALPHA ([@var{value}])@}
13061390 @end display
13071391
13081392 The @cmd{ONEWAY} procedure performs a one-way analysis of variance of
13101394 It is used to compare the means of a population
13111395 divided into more than two groups.
13121396
1313 The dependent variables to be analysed should be given in the @code{VARIABLES}
1397 The dependent variables to be analysed should be given in the @subcmd{VARIABLES}
13141398 subcommand.
1315 The list of variables must be followed by the @code{BY} keyword and
1399 The list of variables must be followed by the @subcmd{BY} keyword and
13161400 the name of the independent (or factor) variable.
13171401
1318 You can use the @code{STATISTICS} subcommand to tell PSPP to display
1402 You can use the @subcmd{STATISTICS} subcommand to tell @pspp{} to display
13191403 ancilliary information. The options accepted are:
13201404 @itemize
13211405 @item DESCRIPTIVES
13261410 variables and their groups.
13271411 @end itemize
13281412
1329 The @code{CONTRAST} subcommand is used when you anticipate certain
1413 The @subcmd{CONTRAST} subcommand is used when you anticipate certain
13301414 differences between the groups.
13311415 The subcommand must be followed by a list of numerals which are the
13321416 coefficients of the groups to be tested.
13331417 The number of coefficients must correspond to the number of distinct
13341418 groups (or values of the independent variable).
1335 If the total sum of the coefficients are not zero, then PSPP will
1419 If the total sum of the coefficients are not zero, then @pspp{} will
13361420 display a warning, but will proceed with the analysis.
1337 The @code{CONTRAST} subcommand may be given up to 10 times in order
1421 The @subcmd{CONTRAST} subcommand may be given up to 10 times in order
13381422 to specify different contrast tests.
1339 The @code{MISSING} subcommand defines how missing values are handled.
1340 If LISTWISE is specified then cases which have missing values for
1423 The @subcmd{MISSING} subcommand defines how missing values are handled.
1424 If @subcmd{LISTWISE} is specified then cases which have missing values for
13411425 the independent variable or any dependent variable will be ignored.
1342 If ANALYSIS is specified, then cases will be ignored if the independent
1426 If @subcmd{ANALYSIS} is specified, then cases will be ignored if the independent
13431427 variable is missing or if the dependent variable currently being
1344 analysed is missing. The default is ANALYSIS.
1345 A setting of EXCLUDE means that variables whose values are
1428 analysed is missing. The default is @subcmd{ANALYSIS}.
1429 A setting of @subcmd{EXCLUDE} means that variables whose values are
13461430 user-missing are to be excluded from the analysis. A setting of
1347 INCLUDE means they are to be included. The default is EXCLUDE.
1431 @subcmd{INCLUDE} means they are to be included. The default is @subcmd{EXCLUDE}.
13481432
13491433 Using the @code{POSTHOC} subcommand you can perform multiple
13501434 pairwise comparisons on the data. The following comparison methods
13511435 are available:
13521436 @itemize
1353 @item LSD
1437 @item @subcmd{LSD}
13541438 Least Significant Difference.
1355 @item TUKEY
1439 @item @subcmd{TUKEY}
13561440 Tukey Honestly Significant Difference.
1357 @item BONFERRONI
1441 @item @subcmd{BONFERRONI}
13581442 Bonferroni test.
1359 @item SCHEFFE
1443 @item @subcmd{SCHEFFE}
13601444 Scheff@'e's test.
1361 @item SIDAK
1445 @item @subcmd{SIDAK}
13621446 Sidak test.
1363 @item GH
1447 @item @subcmd{GH}
13641448 The Games-Howell test.
13651449 @end itemize
13661450
13711455 The default is 0.05.
13721456
13731457 @node QUICK CLUSTER
1374 @comment node-name, next, previous, up
13751458 @section QUICK CLUSTER
13761459 @vindex QUICK CLUSTER
13771460
13791462 @cindex clustering
13801463
13811464 @display
1382 QUICK CLUSTER var_list
1465 QUICK CLUSTER @var{var_list}
13831466 [/CRITERIA=CLUSTERS(@var{k}) [MXITER(@var{max_iter})]]
13841467 [/MISSING=@{EXCLUDE,INCLUDE@} @{LISTWISE, PAIRWISE@}]
13851468 @end display
13901473
13911474 The minimum specification is @samp{QUICK CLUSTER} followed by the names
13921475 of the variables which contain the cluster data. Normally you will also
1393 want to specify @samp{/CRITERIA=CLUSTERS(@var{k})} where @var{k} is the
1476 want to specify @subcmd{/CRITERIA=CLUSTERS(@var{k})} where @var{k} is the
13941477 number of clusters. If this is not given, then @var{k} defaults to 2.
13951478
13961479 The command uses an iterative algorithm to determine the clusters for
13971480 each case. It will continue iterating until convergence, or until @var{max_iter}
13981481 iterations have been done. The default value of @var{max_iter} is 2.
13991482
1400 The @cmd{MISSING} subcommand determines the handling of missing variables.
1401 If INCLUDE is set, then user-missing values are considered at their face
1483 The @subcmd{MISSING} subcommand determines the handling of missing variables.
1484 If @subcmd{INCLUDE} is set, then user-missing values are considered at their face
14021485 value and not as missing values.
1403 If EXCLUDE is set, which is the default, user-missing
1486 If @subcmd{EXCLUDE} is set, which is the default, user-missing
14041487 values are excluded as well as system-missing values.
14051488
1406 If LISTWISE is set, then the entire case is excluded from the analysis
1489 If @subcmd{LISTWISE} is set, then the entire case is excluded from the analysis
14071490 whenever any of the clustering variables contains a missing value.
1408 If PAIRWISE is set, then a case is considered missing only if all the
1491 If @subcmd{PAIRWISE} is set, then a case is considered missing only if all the
14091492 clustering variables contain missing values. Otherwise it is clustered
14101493 on the basis of the non-missing values.
1411 The default is LISTWISE.
1494 The default is @subcmd{LISTWISE}.
14121495
14131496
14141497 @node RANK
1415 @comment node-name, next, previous, up
14161498 @section RANK
14171499
1418
14191500 @vindex RANK
14201501 @display
14211502 RANK
1422 [VARIABLES=] var_list [@{A,D@}] [BY var_list]
1503 [VARIABLES=] @var{var_list} [@{A,D@}] [BY @var{var_list}]
14231504 /TIES=@{MEAN,LOW,HIGH,CONDENSE@}
14241505 /FRACTION=@{BLOM,TUKEY,VW,RANKIT@}
14251506 /PRINT[=@{YES,NO@}
14261507 /MISSING=@{EXCLUDE,INCLUDE@}
14271508
1428 /RANK [INTO var_list]
1429 /NTILES(k) [INTO var_list]
1430 /NORMAL [INTO var_list]
1431 /PERCENT [INTO var_list]
1432 /RFRACTION [INTO var_list]
1433 /PROPORTION [INTO var_list]
1434 /N [INTO var_list]
1435 /SAVAGE [INTO var_list]
1509 /RANK [INTO @var{var_list}]
1510 /NTILES(k) [INTO @var{var_list}]
1511 /NORMAL [INTO @var{var_list}]
1512 /PERCENT [INTO @var{var_list}]
1513 /RFRACTION [INTO @var{var_list}]
1514 /PROPORTION [INTO @var{var_list}]
1515 /N [INTO @var{var_list}]
1516 /SAVAGE [INTO @var{var_list}]
14361517 @end display
14371518
14381519 The @cmd{RANK} command ranks variables and stores the results into new
14391520 variables.
14401521
1441 The VARIABLES subcommand, which is mandatory, specifies one or
1522 The @subcmd{VARIABLES} subcommand, which is mandatory, specifies one or
14421523 more variables whose values are to be ranked.
14431524 After each variable, @samp{A} or @samp{D} may appear, indicating that
14441525 the variable is to be ranked in ascending or descending order.
14451526 Ascending is the default.
1446 If a BY keyword appears, it should be followed by a list of variables
1527 If a @subcmd{BY} keyword appears, it should be followed by a list of variables
14471528 which are to serve as group variables.
14481529 In this case, the cases are gathered into groups, and ranks calculated
14491530 for each group.
14501531
1451 The TIES subcommand specifies how tied values are to be treated. The
1532 The @subcmd{TIES} subcommand specifies how tied values are to be treated. The
14521533 default is to take the mean value of all the tied cases.
14531534
1454 The FRACTION subcommand specifies how proportional ranks are to be
1455 calculated. This only has any effect if NORMAL or PROPORTIONAL rank
1535 The @subcmd{FRACTION} subcommand specifies how proportional ranks are to be
1536 calculated. This only has any effect if @subcmd{NORMAL} or @subcmd{PROPORTIONAL} rank
14561537 functions are requested.
14571538
1458 The PRINT subcommand may be used to specify that a summary of the rank
1539 The @subcmd{PRINT} subcommand may be used to specify that a summary of the rank
14591540 variables created should appear in the output.
14601541
1461 The function subcommands are RANK, NTILES, NORMAL, PERCENT, RFRACTION,
1462 PROPORTION and SAVAGE. Any number of function subcommands may appear.
1542 The function subcommands are @subcmd{RANK}, @subcmd{NTILES}, @subcmd{NORMAL}, @subcmd{PERCENT}, @subcmd{RFRACTION},
1543 @subcmd{PROPORTION} and @subcmd{SAVAGE}. Any number of function subcommands may appear.
14631544 If none are given, then the default is RANK.
1464 The NTILES subcommand must take an integer specifying the number of
1545 The @subcmd{NTILES} subcommand must take an integer specifying the number of
14651546 partitions into which values should be ranked.
1466 Each subcommand may be followed by the INTO keyword and a list of
1547 Each subcommand may be followed by the @subcmd{INTO} keyword and a list of
14671548 variables which are the variables to be created and receive the rank
14681549 scores. There may be as many variables specified as there are
1469 variables named on the VARIABLES subcommand. If fewer are specified,
1550 variables named on the @subcmd{VARIABLES} subcommand. If fewer are specified,
14701551 then the variable names are automatically created.
14711552
1472 The MISSING subcommand determines how user missing values are to be
1473 treated. A setting of EXCLUDE means that variables whose values are
1553 The @subcmd{MISSING} subcommand determines how user missing values are to be
1554 treated. A setting of @subcmd{EXCLUDE} means that variables whose values are
14741555 user-missing are to be excluded from the rank scores. A setting of
1475 INCLUDE means they are to be included. The default is EXCLUDE.
1556 @subcmd{INCLUDE} means they are to be included. The default is @subcmd{EXCLUDE}.
14761557
14771558 @include regression.texi
14781559
14831564 @vindex RELIABILITY
14841565 @display
14851566 RELIABILITY
1486 /VARIABLES=var_list
1487 /SCALE (@var{name}) = @{var_list, ALL@}
1488 /MODEL=@{ALPHA, SPLIT[(N)]@}
1567 /VARIABLES=@var{var_list}
1568 /SCALE (@var{name}) = @{@var{var_list}, ALL@}
1569 /MODEL=@{ALPHA, SPLIT[(@var{n})]@}
14891570 /SUMMARY=@{TOTAL,ALL@}
14901571 /MISSING=@{EXCLUDE,INCLUDE@}
14911572 @end display
14931574 @cindex Cronbach's Alpha
14941575 The @cmd{RELIABILTY} command performs reliability analysis on the data.
14951576
1496 The VARIABLES subcommand is required. It determines the set of variables
1577 The @subcmd{VARIABLES} subcommand is required. It determines the set of variables
14971578 upon which analysis is to be performed.
14981579
1499 The SCALE subcommand determines which variables reliability is to be
1580 The @subcmd{SCALE} subcommand determines which variables reliability is to be
15001581 calculated for. If it is omitted, then analysis for all variables named
1501 in the VARIABLES subcommand will be used.
1582 in the @subcmd{VARIABLES} subcommand will be used.
15021583 Optionally, the @var{name} parameter may be specified to set a string name
15031584 for the scale.
15041585
1505 The MODEL subcommand determines the type of analysis. If ALPHA is specified,
1506 then Cronbach's Alpha is calculated for the scale. If the model is SPLIT,
1586 The @subcmd{MODEL} subcommand determines the type of analysis. If @subcmd{ALPHA} is specified,
1587 then Cronbach's Alpha is calculated for the scale. If the model is @subcmd{SPLIT},
15071588 then the variables are divided into 2 subsets. An optional parameter
1508 @var{N} may be given, to specify how many variables to be in the first subset.
1509 If @var{N} is omitted, then it defaults to one half of the variables in the
1589 @var{n} may be given, to specify how many variables to be in the first subset.
1590 If @var{n} is omitted, then it defaults to one half of the variables in the
15101591 scale, or one half minus one if there are an odd number of variables.
1511 The default model is ALPHA.
1592 The default model is @subcmd{ALPHA}.
15121593
15131594 By default, any cases with user missing, or system missing values for
15141595 any variables given
1515 in the VARIABLES subcommand will be omitted from analysis.
1516 The MISSING subcommand determines whether user missing values are to
1596 in the @subcmd{VARIABLES} subcommand will be omitted from analysis.
1597 The @subcmd{MISSING} subcommand determines whether user missing values are to
15171598 be included or excluded in the analysis.
15181599
1519 The SUMMARY subcommand determines the type of summary analysis to be performed.
1520 Currently there is only one type: SUMMARY=TOTAL, which displays per-item
1600 The @subcmd{SUMMARY} subcommand determines the type of summary analysis to be performed.
1601 Currently there is only one type: @subcmd{SUMMARY=TOTAL}, which displays per-item
15211602 analysis tested against the totals.
15221603
15231604
15491630 The variable @var{state_var} is the variable whose values represent the actual states,
15501631 and @var{state_value} is the value of this variable which represents the positive state.
15511632
1552 The optional subcommand PLOT is used to determine if and how the ROC curve is drawn.
1553 The keyword CURVE means that the ROC curve should be drawn, and the optional keyword REFERENCE,
1633 The optional subcommand @subcmd{PLOT} is used to determine if and how the @subcmd{ROC} curve is drawn.
1634 The keyword @subcmd{CURVE} means that the @subcmd{ROC} curve should be drawn, and the optional keyword @subcmd{REFERENCE},
15541635 which should be enclosed in parentheses, says that the diagonal reference line should be drawn.
1555 If the keyword NONE is given, then no ROC curve is drawn.
1636 If the keyword @subcmd{NONE} is given, then no @subcmd{ROC} curve is drawn.
15561637 By default, the curve is drawn with no reference line.
15571638
1558 The optional subcommand PRINT determines which additional tables should be printed.
1639 The optional subcommand @subcmd{PRINT} determines which additional tables should be printed.
15591640 Two additional tables are available.
1560 The SE keyword says that standard error of the area under the curve should be printed as well as
1641 The @subcmd{SE} keyword says that standard error of the area under the curve should be printed as well as
15611642 the area itself.
15621643 In addition, a p-value under the null hypothesis that the area under the curve equals 0.5 will be
15631644 printed.
1564 The COORDINATES keyword says that a table of coordinates of the ROC curve should be printed.
1565
1566 The CRITERIA subcommand has four optional parameters:
1645 The @subcmd{COORDINATES} keyword says that a table of coordinates of the @subcmd{ROC} curve should be printed.
1646
1647 The @subcmd{CRITERIA} subcommand has four optional parameters:
15671648 @itemize @bullet
1568 @item The TESTPOS parameter may be LARGE or SMALL.
1569 LARGE is the default, and says that larger values in the predictor variables are to be
1570 considered positive. SMALL indicates that smaller values should be considered positive.
1571
1572 @item The CI parameter specifies the confidence interval that should be printed.
1573 It has no effect if the SE keyword in the PRINT subcommand has not been given.
1574
1575 @item The DISTRIBUTION parameter determines the method to be used when estimating the area
1649 @item The @subcmd{TESTPOS} parameter may be @subcmd{LARGE} or @subcmd{SMALL}.
1650 @subcmd{LARGE} is the default, and says that larger values in the predictor variables are to be
1651 considered positive. @subcmd{SMALL} indicates that smaller values should be considered positive.
1652
1653 @item The @subcmd{CI} parameter specifies the confidence interval that should be printed.
1654 It has no effect if the @subcmd{SE} keyword in the @subcmd{PRINT} subcommand has not been given.
1655
1656 @item The @subcmd{DISTRIBUTION} parameter determines the method to be used when estimating the area
15761657 under the curve.
1577 There are two possibilities, @i{viz}: FREE and NEGEXPO.
1578 The FREE method uses a non-parametric estimate, and the NEGEXPO method a bi-negative
1658 There are two possibilities, @i{viz}: @subcmd{FREE} and @subcmd{NEGEXPO}.
1659 The @subcmd{FREE} method uses a non-parametric estimate, and the @subcmd{NEGEXPO} method a bi-negative
15791660 exponential distribution estimate.
1580 The NEGEXPO method should only be used when the number of positive actual states is
1661 The @subcmd{NEGEXPO} method should only be used when the number of positive actual states is
15811662 equal to the number of negative actual states.
1582 The default is FREE.
1583
1584 @item The CUTOFF parameter is for compatibility and is ignored.
1663 The default is @subcmd{FREE}.
1664
1665 @item The @subcmd{CUTOFF} parameter is for compatibility and is ignored.
15851666 @end itemize
15861667
1587 The MISSING subcommand determines whether user missing values are to
1668 The @subcmd{MISSING} subcommand determines whether user missing values are to
15881669 be included or excluded in the analysis. The default behaviour is to
15891670 exclude them.
15901671 Cases are excluded on a listwise basis; if any of the variables in @var{var_list}
11 @chapter Data transformations
22 @cindex transformations
33
4 The PSPP procedures examined in this chapter manipulate data and
4 The @pspp{} procedures examined in this chapter manipulate data and
55 prepare the active dataset for later analyses. They do not produce output,
66 as a rule.
77
2222
2323 @display
2424 AGGREGATE
25 OUTFILE=@{*,'file-name',file_handle@} [MODE=@{REPLACE, ADDVARIABLES@}]
25 OUTFILE=@{*,'@var{file_name}',@var{file_handle}@} [MODE=@{REPLACE, ADDVARIABLES@}]
2626 /PRESORTED
2727 /DOCUMENT
2828 /MISSING=COLUMNWISE
29 /BREAK=var_list
30 /dest_var['label']@dots{}=agr_func(src_vars, args@dots{})@dots{}
29 /BREAK=@var{var_list}
30 /@var{dest_var}['@var{label}']@dots{}=@var{agr_func}(@var{src_vars}, @var{args}@dots{})@dots{}
3131 @end display
3232
3333 @cmd{AGGREGATE} summarizes groups of cases into single cases.
3535 variables called @dfn{break variables}. Several functions are available
3636 for summarizing case contents.
3737
38 The OUTFILE subcommand is required and must appear first. Specify a
38 The @subcmd{OUTFILE} subcommand is required and must appear first. Specify a
3939 system file or portable file by file name or file
4040 handle (@pxref{File Handles}), or a dataset by its name
4141 (@pxref{Datasets}).
4242 The aggregated cases are written to this file. If @samp{*} is
4343 specified, then the aggregated cases replace the active dataset's data.
44 Use of OUTFILE to write a portable file is a PSPP extension.
45
46 If OUTFILE=@samp{*} is given, then the subcommand MODE may also be
44 Use of @subcmd{OUTFILE} to write a portable file is a @pspp{} extension.
45
46 If @subcmd{OUTFILE=*} is given, then the subcommand @subcmd{MODE} may also be
4747 specified.
48 The mode subcommand has two possible values: ADDVARIABLES or REPLACE.
49 In REPLACE mode, the entire active dataset is replaced by a new dataset
48 The mode subcommand has two possible values: @subcmd{ADDVARIABLES} or @subcmd{REPLACE}.
49 In @subcmd{REPLACE} mode, the entire active dataset is replaced by a new dataset
5050 which contains just the break variables and the destination varibles.
5151 In this mode, the new file will contain as many cases as there are
5252 unique combinations of the break variables.
53 In ADDVARIABLES mode, the destination variables will be appended to
53 In @subcmd{ADDVARIABLES} mode, the destination variables will be appended to
5454 the existing active dataset.
5555 Cases which have identical combinations of values in their break
5656 variables, will receive identical values for the destination variables.
5757 The number of cases in the active dataset will remain unchanged.
58 Note that if ADDVARIABLES is specified, then the data @emph{must} be
58 Note that if @subcmd{ADDVARIABLES} is specified, then the data @emph{must} be
5959 sorted on the break variables.
6060
6161 By default, the active dataset will be sorted based on the break variables
6262 before aggregation takes place. If the active dataset is already sorted
6363 or otherwise grouped in terms of the break variables, specify
64 PRESORTED to save time.
65 PRESORTED is assumed if MODE=ADDVARIABLES is used.
66
67 Specify DOCUMENT to copy the documents from the active dataset into the
64 @subcmd{PRESORTED} to save time.
65 @subcmd{PRESORTED} is assumed if @subcmd{MODE=ADDVARIABLES} is used.
66
67 Specify @subcmd{DOCUMENT} to copy the documents from the active dataset into the
6868 aggregate file (@pxref{DOCUMENT}). Otherwise, the aggregate file will
6969 not contain any documents, even if the aggregate file replaces the
7070 active dataset.
7171
72 Normally, only a single case (for SD and SD., two cases) need be
72 Normally, only a single case (for @subcmd{SD} and @subcmd{SD}., two cases) need be
7373 non-missing in each group for the aggregate variable to be
74 non-missing. Specifying /MISSING=COLUMNWISE inverts this behavior, so
74 non-missing. Specifying @subcmd{/MISSING=COLUMNWISE} inverts this behavior, so
7575 that the aggregate variable becomes missing if any aggregated value is
7676 missing.
7777
78 If PRESORTED, DOCUMENT, or MISSING are specified, they must appear
79 between OUTFILE and BREAK.
80
81 At least one break variable must be specified on BREAK, a
78 If @subcmd{PRESORTED}, @subcmd{DOCUMENT}, or @subcmd{MISSING} are specified, they must appear
79 between @subcmd{OUTFILE} and @subcmd{BREAK}.
80
81 At least one break variable must be specified on @subcmd{BREAK}, a
8282 required subcommand. The values of these variables are used to divide
8383 the active dataset into groups to be summarized. In addition, at least
8484 one @var{dest_var} must be specified.
9999 Each set must have exactly as many source variables as aggregation
100100 variables. Each aggregation variable receives the results of applying
101101 the specified aggregation function to the corresponding source
102 variable. The MEAN, MEDIAN, SD, and SUM aggregation functions may only be
102 variable. The @subcmd{MEAN}, @subcmd{MEDIAN}, @subcmd{SD}, and @subcmd{SUM}
103 aggregation functions may only be
103104 applied to numeric variables. All the rest may be applied to numeric
104105 and string variables.
105106
106107 The available aggregation functions are as follows:
107108
108109 @table @asis
109 @item FGT(var_name, value)
110 @item @subcmd{FGT(@var{var_name}, @var{value})}
110111 Fraction of values greater than the specified constant. The default
111112 format is F5.3.
112113
113 @item FIN(var_name, low, high)
114 @item @subcmd{FIN(@var{var_name}, @var{low}, @var{high})}
114115 Fraction of values within the specified inclusive range of constants.
115116 The default format is F5.3.
116117
117 @item FLT(var_name, value)
118 @item @subcmd{FLT(@var{var_name}, @var{value})}
118119 Fraction of values less than the specified constant. The default
119120 format is F5.3.
120121
121 @item FIRST(var_name)
122 @item @subcmd{FIRST(@var{var_name})}
122123 First non-missing value in break group. The aggregation variable
123124 receives the complete dictionary information from the source variable.
124 The sort performed by AGGREGATE (and by SORT CASES) is stable, so that
125 The sort performed by @cmd{AGGREGATE} (and by @cmd{SORT CASES}) is stable, so that
125126 the first case with particular values for the break variables before
126127 sorting will also be the first case in that break group after sorting.
127128
128 @item FOUT(var_name, low, high)
129 @item @subcmd{FOUT(@var{var_name}, @var{low}, @var{high})}
129130 Fraction of values strictly outside the specified range of constants.
130131 The default format is F5.3.
131132
132 @item LAST(var_name)
133 @item @subcmd{LAST(@var{var_name})}
133134 Last non-missing value in break group. The aggregation variable
134135 receives the complete dictionary information from the source variable.
135 The sort performed by AGGREGATE (and by SORT CASES) is stable, so that
136 The sort performed by @cmd{AGGREGATE} (and by @cmd{SORT CASES}) is stable, so that
136137 the last case with particular values for the break variables before
137138 sorting will also be the last case in that break group after sorting.
138139
139 @item MAX(var_name)
140 @item @subcmd{MAX(@var{var_name})}
140141 Maximum value. The aggregation variable receives the complete
141142 dictionary information from the source variable.
142143
143 @item MEAN(var_name)
144 @item @subcmd{MEAN(@var{var_name})}
144145 Arithmetic mean. Limited to numeric values. The default format is
145146 F8.2.
146147
147 @item MEDIAN(var_name)
148 @item @subcmd{MEDIAN(@var{var_name})}
148149 The median value. Limited to numeric values. The default format is F8.2.
149150
150 @item MIN(var_name)
151 @item @subcmd{MIN(@var{var_name})}
151152 Minimum value. The aggregation variable receives the complete
152153 dictionary information from the source variable.
153154
154 @item N(var_name)
155 @item @subcmd{N(@var{var_name})}
155156 Number of non-missing values. The default format is F7.0 if weighting
156157 is not enabled, F8.2 if it is (@pxref{WEIGHT}).
157158
158 @item N
159 @item @subcmd{N}
159160 Number of cases aggregated to form this group. The default format is
160161 F7.0 if weighting is not enabled, F8.2 if it is (@pxref{WEIGHT}).
161162
162 @item NMISS(var_name)
163 @item @subcmd{NMISS(@var{var_name})}
163164 Number of missing values. The default format is F7.0 if weighting is
164165 not enabled, F8.2 if it is (@pxref{WEIGHT}).
165166
166 @item NU(var_name)
167 @item @subcmd{NU(@var{var_name})}
167168 Number of non-missing values. Each case is considered to have a weight
168169 of 1, regardless of the current weighting variable (@pxref{WEIGHT}).
169170 The default format is F7.0.
170171
171 @item NU
172 @item @subcmd{NU}
172173 Number of cases aggregated to form this group. Each case is considered
173174 to have a weight of 1, regardless of the current weighting variable.
174175 The default format is F7.0.
175176
176 @item NUMISS(var_name)
177 @item @subcmd{NUMISS(@var{var_name})}
177178 Number of missing values. Each case is considered to have a weight of
178179 1, regardless of the current weighting variable. The default format is F7.0.
179180
180 @item PGT(var_name, value)
181 @item @subcmd{PGT(@var{var_name}, @var{value})}
181182 Percentage between 0 and 100 of values greater than the specified
182183 constant. The default format is F5.1.
183184
184 @item PIN(var_name, low, high)
185 @item @subcmd{PIN(@var{var_name}, @var{low}, @var{high})}
185186 Percentage of values within the specified inclusive range of
186187 constants. The default format is F5.1.
187188
188 @item PLT(var_name, value)
189 @item @subcmd{PLT(@var{var_name}, @var{value})}
189190 Percentage of values less than the specified constant. The default
190191 format is F5.1.
191192
192 @item POUT(var_name, low, high)
193 @item @subcmd{POUT(@var{var_name}, @var{low}, @var{high})}
193194 Percentage of values strictly outside the specified range of
194195 constants. The default format is F5.1.
195196
196 @item SD(var_name)
197 @item @subcmd{SD(@var{var_name})}
197198 Standard deviation of the mean. Limited to numeric values. The
198199 default format is F8.2.
199200
200 @item SUM(var_name)
201 @item @subcmd{SUM(@var{var_name})}
201202 Sum. Limited to numeric values. The default format is F8.2.
202203 @end table
203204
204205 Aggregation functions compare string values in terms of internal
205 character codes. On most modern computers, this is a form of ASCII.
206 character codes.
207 On most modern computers, this is @acronym{ASCII} or a superset thereof.
206208
207209 The aggregation functions listed above exclude all user-missing values
208210 from calculations. To include user-missing values, insert a period
218220 @vindex AUTORECODE
219221
220222 @display
221 AUTORECODE VARIABLES=src_vars INTO dest_vars
223 AUTORECODE VARIABLES=@var{src_vars} INTO @var{dest_vars}
222224 [ /DESCENDING ]
223225 [ /PRINT ]
224226 [ /GROUP ]
229231 takes on and maps them onto values 1@dots{}@var{n} on a new numeric
230232 variable.
231233
232 Subcommand VARIABLES is the only required subcommand and must come
233 first. Specify VARIABLES, an equals sign (@samp{=}), a list of source
234 variables, INTO, and a list of target variables. There must the same
234 Subcommand @subcmd{VARIABLES} is the only required subcommand and must come
235 first. Specify @subcmd{VARIABLES}, an equals sign (@samp{=}), a list of source
236 variables, @subcmd{INTO}, and a list of target variables. There must the same
235237 number of source and target variables. The target variables must not
236238 already exist.
237239
239241 is based on character code comparisons) are recoded to increasing values
240242 of its target variable. To cause increasing values of a source variable
241243 to be recoded to decreasing values of its target variable (@var{n} down
242 to 1), specify DESCENDING.
243
244 PRINT is currently ignored.
245
246 The GROUP subcommand is relevant only if more than one variable is to be
244 to 1), specify @subcmd{DESCENDING}.
245
246 @subcmd{PRINT} is currently ignored.
247
248 The @subcmd{GROUP} subcommand is relevant only if more than one variable is to be
247249 recoded. It causes a single mapping between source and target values to
248250 be used, instead of one map per variable.
249251
250 If /BLANK=MISSING is given, then string variables which contain only
251 whitespace are recoded as SYSMIS. If /BLANK=VALID is given then they
252 will be allocated a value like any other. /BLANK is not relevant
253 to numeric values. /BLANK=VALID is the default.
252 If @subcmd{/BLANK=MISSING} is given, then string variables which contain only
253 whitespace are recoded as SYSMIS. If @subcmd{/BLANK=VALID} is given then they
254 will be allocated a value like any other. @subcmd{/BLANK} is not relevant
255 to numeric values. @subcmd{/BLANK=VALID} is the default.
254256
255257 @cmd{AUTORECODE} is a procedure. It causes the data to be read.
256258
259261 @vindex COMPUTE
260262
261263 @display
262 COMPUTE variable = expression.
264 COMPUTE @var{variable} = @var{expression}.
265 @end display
263266 or
264 COMPUTE vector(index) = expression.
267 @display
268 COMPUTE vector(@var{index}) = @var{expression}.
265269 @end display
266270
267271 @cmd{COMPUTE} assigns the value of an expression to a target
278282 they can be used as targets for @cmd{COMPUTE}.
279283
280284 The target variable may be specified as an element of a vector
281 (@pxref{VECTOR}). In this case, a vector index expression must be
282 specified in parentheses following the vector name. The index
283 expression must evaluate to a numeric value that, after rounding down
285 (@pxref{VECTOR}). In this case, an expression @var{index} must be
286 specified in parentheses following the vector name. The expression @var{index}
287 must evaluate to a numeric value that, after rounding down
284288 to the nearest integer, is a valid index for the named vector.
285289
286290 Using @cmd{COMPUTE} to assign to a variable specified on @cmd{LEAVE}
299303 @vindex COUNT
300304
301305 @display
302 COUNT var_name = var@dots{} (value@dots{}).
303
304 Each value takes one of the following forms:
305 number
306 string
307 num1 THRU num2
306 COUNT @var{var_name} = @var{var}@dots{} (@var{value}@dots{}).
307
308 Each @var{value} takes one of the following forms:
309 @var{number}
310 @var{string}
311 @var{num1} THRU @var{num2}
308312 MISSING
309313 SYSMIS
310 In addition, num1 and num2 can be LO or LOWEST, or HI or HIGHEST,
311 respectively.
314 where @var{num1} is a numeric expression or the words @subcmd{LO} or @subcmd{LOWEST}
315 and @var{num2} is a numeric expression or @subcmd{HI} or @subcmd{HIGHEST}.
312316 @end display
313317
314318 @cmd{COUNT} creates or replaces a numeric @dfn{target} variable that
324328 values. They are @strong{not} treated as system-missing values.
325329 User-missing values that are criterion values or inside ranges of
326330 criterion values are counted as any other values. However (for numeric
327 variables), keyword MISSING may be used to refer to all system-
331 variables), keyword @subcmd{MISSING} may be used to refer to all system-
328332 and user-missing values.
329333
330334 @cmd{COUNT} target variables are assigned values in the order
331 specified. In the command @code{COUNT A=A B(1) /B=A B(2).}, the
335 specified. In the command @subcmd{COUNT @var{A}=@var{A} @var{B}(1) /@var{B}=@var{A} @var{B}(2).}, the
332336 following actions occur:
333337
334338 @itemize @minus
335339 @item
336 The number of occurrences of 1 between @code{A} and @code{B} is counted.
337
338 @item
339 @code{A} is assigned this value.
340
341 @item
342 The number of occurrences of 1 between @code{B} and the @strong{new}
343 value of @code{A} is counted.
344
345 @item
346 @code{B} is assigned this value.
340 The number of occurrences of 1 between @var{A} and @var{B} is counted.
341
342 @item
343 @var{A} is assigned this value.
344
345 @item
346 The number of occurrences of 1 between @var{B} and the @strong{new}
347 value of @var{A} is counted.
348
349 @item
350 @var{B} is assigned this value.
347351 @end itemize
348352
349353 Despite this ordering, all @cmd{COUNT} criterion variables must exist
403407 @vindex FLIP
404408
405409 @display
406 FLIP /VARIABLES=var_list /NEWNAMES=var_name.
410 FLIP /VARIABLES=@var{var_list} /NEWNAMES=@var{var_name}.
407411 @end display
408412
409413 @cmd{FLIP} transposes rows and columns in the active dataset. It
412416 All variables in the transposed active dataset are numeric. String
413417 variables take on the system-missing value in the transposed file.
414418
415 No subcommands are required. If specified, the VARIABLES subcommand
419 @subcmd{N} subcommands are required. If specified, the @subcmd{VARIABLES} subcommand
416420 selects variables to be transformed into cases, and variables not
417 specified are discarded. If the VARIABLES subcommand is omitted, all
421 specified are discarded. If the @subcmd{VARIABLES} subcommand is omitted, all
418422 variables are selected for transposition.
419423
420 The variables specified by NEWNAMES, which must be a string variable, is
424 The variables specified by @subcmd{NEWNAMES}, which must be a
425 string variable, is
421426 used to give names to the variables created by @cmd{FLIP}. Only the
422427 first 8 characters of the variable are used. If
423 NEWNAMES is not
428 @subcmd{NEWNAMES} is not
424429 specified then the default is a variable named CASE_LBL, if it exists.
425 If it does not then the variables created by FLIP are named VAR000
430 If it does not then the variables created by @cmd{FLIP} are named VAR000
426431 through VAR999, then VAR1000, VAR1001, and so on.
427432
428 When a NEWNAMES variable is available, the names must be canonicalized
433 When a @subcmd{NEWNAMES} variable is available, the names must be canonicalized
429434 before becoming variable names. Invalid characters are replaced by
430435 letter @samp{V} in the first position, or by @samp{_} in subsequent
431436 positions. If the name thus generated is not unique, then numeric
432437 extensions are added, starting with 1, until a unique name is found or
433438 there are no remaining possibilities. If the latter occurs then the
434 FLIP operation aborts.
439 @cmd{FLIP} operation aborts.
435440
436441 The resultant dictionary contains a CASE_LBL variable, a string
437442 variable of width 8, which stores the names of the variables in the
440445 transposed using @cmd{FLIP}, this variable can be used to recreate the
441446 original variable names.
442447
443 FLIP honors @cmd{N OF CASES} (@pxref{N OF CASES}). It ignores
448 @cmd{FLIP} honors @cmd{N OF CASES} (@pxref{N OF CASES}). It ignores
444449 @cmd{TEMPORARY} (@pxref{TEMPORARY}), so that ``temporary''
445450 transformations become permanent.
446451
449454 @vindex IF
450455
451456 @display
452 IF condition variable=expression.
457 IF @var{condition} @var{variable}=@var{expression}.
458 @end display
453459 or
454 IF condition vector(index)=expression.
460 @display
461 IF @var{condition} vector(@var{index})=@var{expression}.
455462 @end display
456463
457464 The @cmd{IF} transformation conditionally assigns the value of a target
459466 expression.
460467
461468 Specify a boolean-valued expression (@pxref{Expressions}) to be tested
462 following the IF keyword. This expression is evaluated for each case.
469 following the @cmd{IF} keyword. This expression is evaluated for each case.
463470 If the value is true, then the value of the expression is computed and
464471 assigned to the specified variable. If the value is false or missing,
465472 nothing is done. Numeric and string variables may be
498505 [INTO @var{dest_vars}].
499506 @end display
500507
501 Following the RECODE keyword itself comes @var{src_vars} which is a list
508 Following the @cmd{RECODE} keyword itself comes @var{src_vars} which is a list
502509 of variables whose values are to be transformed.
503510 These variables may be string variables or they may be numeric.
504511 However the list must be homogeneous; you may not mix string variables and
670677 @vindex SORT CASES
671678
672679 @display
673 SORT CASES BY var_list[(@{D|A@}] [ var_list[(@{D|A@}] ] ...
680 SORT CASES BY @var{var_list}[(@{D|A@}] [ @var{var_list}[(@{D|A@}] ] ...
674681 @end display
675682
676683 @cmd{SORT CASES} sorts the active dataset by the values of one or more
677684 variables.
678685
679 Specify BY and a list of variables to sort by. By default, variables
680 are sorted in ascending order. To override sort order, specify (D) or
681 (DOWN) after a list of variables to get descending order, or (A) or (UP)
686 Specify @subcmd{BY} and a list of variables to sort by. By default, variables
687 are sorted in ascending order. To override sort order, specify @subcmd{(D)} or
688 @subcmd{(DOWN)} after a list of variables to get descending order, or @subcmd{(A)} or @subcmd{(UP)}
682689 for ascending order. These apply to all the listed variables
683 up until the preceding (A), (D), (UP) or (DOWN).
690 up until the preceding @subcmd{(A)}, @subcmd{(D)}, @subcmd{(UP)} or @subcmd{(DOWN)}.
684691
685692 The sort algorithms used by @cmd{SORT CASES} are stable. That is,
686693 records that have equal values of the sort variables will have the
694701 If workspace is exhausted, it falls back to a merge sort algorithm that
695702 involves creates numerous temporary files.
696703
697 @cmd{SORT CASES} may not be specified following TEMPORARY.
704 @cmd{SORT CASES} may not be specified following @cmd{TEMPORARY}.
22 @include tut.texi
33
44 @node Using PSPP
5 @chapter Using PSPP
6
7 PSPP is a tool for the statistical analysis of sampled data.
5 @chapter Using @pspp{}
6
7 @pspp{} is a tool for the statistical analysis of sampled data.
88 You can use it to discover patterns in the data,
99 to explain differences in one subset of data in terms of another subset
1010 and to find out
1111 whether certain beliefs about the data are justified.
1212 This chapter does not attempt to introduce the theory behind the
1313 statistical analysis,
14 but it shows how such analysis can be performed using PSPP.
15
16 For the purposes of this tutorial, it is assumed that you are using PSPP in its
14 but it shows how such analysis can be performed using @pspp{}.
15
16 For the purposes of this tutorial, it is assumed that you are using @pspp{} in its
1717 interactive mode from the command line.
1818 However, the example commands can also be typed into a file and executed in
1919 a post-hoc mode by typing @samp{pspp @var{filename}} at a shell prompt,
2424 executed.
2525 Whichever method you choose, the syntax is identical.
2626
27 When using the interactive method, PSPP tells you that it's waiting for your
27 When using the interactive method, @pspp{} tells you that it's waiting for your
2828 data with a string like @prompt{PSPP>} or @prompt{data>}.
2929 In the examples of this chapter, whenever you see text like this, it
30 indicates the prompt displayed by PSPP, @emph{not} something that you
30 indicates the prompt displayed by @pspp{}, @emph{not} something that you
3131 should type.
3232
3333 Throughout this chapter reference is made to a number of sample data files.
3434 So that you can try the examples for yourself,
35 you should have received these files along with your copy of PSPP.@c
35 you should have received these files along with your copy of @pspp{}.@c
3636 @footnote{These files contain purely fictitious data. They should not be used
3737 for research purposes.}
3838 @note{Normally these files are installed in the directory
5252 @section Preparation of Data Files
5353
5454
55 Before analysis can commence, the data must be loaded into PSPP and
56 arranged such that both PSPP and humans can understand what
55 Before analysis can commence, the data must be loaded into @pspp{} and
56 arranged such that both @pspp{} and humans can understand what
5757 the data represents.
5858 There are two aspects of data:
5959
126126 @item
127127 The words @samp{data list list} are an example of the @cmd{DATA LIST}
128128 command. @xref{DATA LIST}.
129 It tells PSPP to prepare for reading data.
129 It tells @pspp{} to prepare for reading data.
130130 The word @samp{list} intentionally appears twice.
131131 The first occurrence is part of the @cmd{DATA LIST} call,
132132 whilst the second
133 tells PSPP that the data is to be read as free format data with
133 tells @pspp{} that the data is to be read as free format data with
134134 one record per line.
135135
136136 @item
147147
148148
149149 @item
150 Normally, PSPP displays the prompt @prompt{PSPP>} whenever it's
150 Normally, @pspp{} displays the prompt @prompt{PSPP>} whenever it's
151151 expecting a command.
152152 However, when it's expecting data, the prompt changes to @prompt{data>}
153153 so that you know to enter data and not a command.
154154
155155 @item
156156 At the end of every command there is a terminating @samp{.} which tells
157 PSPP that the end of a command has been encountered.
157 @pspp{} that the end of a command has been encountered.
158158 You should not enter @samp{.} when data is expected (@i{ie.} when
159159 the @prompt{data>} prompt is current) since it is appropriate only for
160160 terminating commands.
225225 For full details refer to @pxref{DATA LIST}.
226226
227227 @node Reading data from a pre-prepared PSPP file
228 @subsection Reading data from a pre-prepared PSPP file
228 @subsection Reading data from a pre-prepared @pspp{} file
229229 @cindex system files
230230 @vindex GET
231231
232 When working with other PSPP users, or users of other software which
233 uses the PSPP data format, you may be given the data in
234 a pre-prepared PSPP file.
232 When working with other @pspp{} users, or users of other software which
233 uses the @pspp{} data format, you may be given the data in
234 a pre-prepared @pspp{} file.
235235 Such files contain not only the data, but the variable definitions,
236236 along with their formats, labels and other meta-data.
237237 Conventionally, these files (sometimes called ``system'' files)
246246
247247
248248 @node Saving data to a PSPP file.
249 @subsection Saving data to a PSPP file.
249 @subsection Saving data to a @pspp{} file.
250250 @cindex saving
251251 @vindex SAVE
252252
253253 If you want to save your data, along with the variable definitions so
254 that you or other PSPP users can use it later, you can do this with
254 that you or other @pspp{} users can use it later, you can do this with
255255 the @cmd{SAVE} command.
256256
257257 The following syntax will save the existing data and variables to a
300300 @cindex errors, in data
301301
302302 Data from real sources is rarely error free.
303 PSPP has a number of procedures which can be used to help
303 @pspp{} has a number of procedures which can be used to help
304304 identify data which might be incorrect.
305305
306306 The @cmd{DESCRIPTIVES} command (@pxref{DESCRIPTIVES}) is used to generate
402402 If possible, suspect data should be checked and re-measured.
403403 However, this may not always be feasible, in which case the researcher may
404404 decide to disregard these values.
405 PSPP has a feature whereby data can assume the special value `SYSMIS', and
405 @pspp{} has a feature whereby data can assume the special value `SYSMIS', and
406406 will be disregarded in future analysis. @xref{Missing Observations}.
407407 You can set the two suspect values to the `SYSMIS' value using the @cmd{RECODE}
408408 command.
409409 @example
410 PSPP> recode height (179 = SYSMIS).
411 PSPP> recode weight (LOWEST THRU 0 = SYSMIS).
410 @pspp{}> recode height (179 = SYSMIS).
411 @pspp{}> recode weight (LOWEST THRU 0 = SYSMIS).
412412 @end example
413413 @noindent
414414 The first command says that for any observation which has a
433433 The sample file @file{hotel.sav} comprises data gathered from a
434434 customer satisfaction survey of clients at a particular hotel.
435435 In @ref{reliability}, this file is loaded for analysis.
436 The line @code{display dictionary.} tells PSPP to display the
436 The line @code{display dictionary.} tells @pspp{} to display the
437437 variables and associated data.
438438 The output from this command has been omitted from the example for the sake of clarity, but
439439 you will notice that each of the variables
478478 One would therefore expect the values of these variables (after recoding)
479479 to closely follow one another, and we can test that with the @cmd{RELIABILITY}
480480 command (@pxref{RELIABILITY}).
481 @ref{reliability} shows a PSPP session where the user (after recoding
481 @ref{reliability} shows a @pspp{} session where the user (after recoding
482482 negatively scaled variables) requests reliability statistics for
483483 @var{v1}, @var{v3} and @var{v5}.
484484
641641 or
642642 whether the mean of a dataset significantly differs from a particular
643643 value.
644 This section presents just some of the possible tests that PSPP offers.
644 This section presents just some of the possible tests that @pspp{} offers.
645645
646646 The researcher starts by making a @dfn{null hypothesis}.
647647 Often this is a hypothesis which he suspects to be false.
694694 If the variances are equal, then a more powerful form of the T-test can be used.
695695 However if it is unsafe to assume equal variances,
696696 then an alternative calculation is necessary.
697 PSPP performs both calculations.
697 @pspp{} performs both calculations.
698698
699699 For the @var{height} variable, the output shows the significance of the
700700 Levene test to be 0.33 which means there is a
2020 * ERASE:: Erase a file.
2121 * EXECUTE:: Execute pending transformations.
2222 * FILE LABEL:: Set the active dataset's label.
23 * FINISH:: Terminate the PSPP session.
23 * FINISH:: Terminate the @pspp{} session.
2424 * HOST:: Temporarily return to the operating system.
2525 * INCLUDE:: Include a file within the current one.
2626 * INSERT:: Insert a file within the current one.
2727 * PERMISSIONS:: Change permissions on a file.
2828 * PRESERVE and RESTORE:: Saving settings and restoring them later.
29 * SET:: Adjust PSPP runtime parameters.
29 * SET:: Adjust @pspp{} runtime parameters.
3030 * SHOW:: Display runtime parameters.
3131 * SUBTITLE:: Provide a document subtitle.
3232 * TITLE:: Provide a document title.
3333 @end menu
3434
3535 @node ADD DOCUMENT
36 @comment node-name, next, previous, up
3736 @section ADD DOCUMENT
3837 @vindex ADD DOCUMENT
3938
8685 @end display
8786
8887 @cmd{COMMENT} is ignored. It is used to provide information to
89 the author and other readers of the PSPP syntax file.
88 the author and other readers of the @pspp{} syntax file.
9089
9190 @cmd{COMMENT} can extend over any number of lines. Don't forget to
9291 terminate it with a dot or a blank line.
107106 DOCUMENTS}. They can be removed from the active dataset with @cmd{DROP
108107 DOCUMENTS}.
109108
110 Specify the @var{documentary text} following the DOCUMENT keyword.
109 Specify the @var{documentary text} following the @subcmd{DOCUMENT} keyword.
111110 It is interpreted literally --- any quotes or other punctuation marks
112111 will be included in the file.
113112 You can extend the documentary text over as many lines as necessary.
138137 active dataset,
139138 if any. @xref{FILE LABEL}.
140139
141 This command is a PSPP extension.
140 This command is a @pspp{} extension.
142141
143142 @node DROP DOCUMENTS
144143 @section DROP DOCUMENTS
165164 Use @cmd{ECHO} to write arbitrary text to the output stream. The text should be enclosed in quotation marks following the normal rules for string tokens (@pxref{Tokens}).
166165
167166 @node ERASE
168 @comment node-name, next, previous, up
169167 @section ERASE
170168 @vindex ERASE
171169
172170 @display
173 ERASE FILE file_name.
171 ERASE FILE @var{file_name}.
174172 @end display
175173
176174 @cmd{ERASE FILE} deletes a file from the local filesystem.
177 file_name must be quoted.
178 This command cannot be used if the SAFER setting is active.
175 @var{file_name} must be quoted.
176 This command cannot be used if the SAFER (@pxref{SET}) setting is active.
179177
180178
181179 @node EXECUTE
194192 @vindex FILE LABEL
195193
196194 @display
197 FILE LABEL file_label.
195 FILE LABEL @var{file_label}.
198196 @end display
199197
200198 @cmd{FILE LABEL} provides a title for the active dataset. This
201199 title will be saved into system files and portable files that are
202 created during this PSPP run.
203
204 file_label need not be quoted. If quotes are
205 included, they become part of the file label.
200 created during this @pspp{} run.
201
202 @var{file_label} should not be quoted.
203 If quotes are included, they are literally interpreted and become part of the file label.
206204
207205 @node FINISH
208206 @section FINISH
212210 FINISH.
213211 @end display
214212
215 @cmd{FINISH} terminates the current PSPP session and returns
213 @cmd{FINISH} terminates the current @pspp{} session and returns
216214 control to the operating system.
217215
218216 @node HOST
219 @comment node-name, next, previous, up
220217 @section HOST
221218 @vindex HOST
222219
223220 @display
224221 HOST.
225 HOST COMMAND=['command'...].
226 @end display
227
228 @cmd{HOST} suspends the current PSPP session and temporarily returns control
222 HOST COMMAND=['@var{command}'...].
223 @end display
224
225 @cmd{HOST} suspends the current @pspp{} session and temporarily returns control
229226 to the operating system.
230 This command cannot be used if the SAFER setting is active.
231
232 If the COMMAND subcommand is specified, as a sequence of shell
233 commands as quoted strings within square brackets, then PSPP executes
227 This command cannot be used if the SAFER (@pxref{SET}) setting is active.
228
229 If the @subcmd{COMMAND} subcommand is specified, as a sequence of shell
230 commands as quoted strings within square brackets, then @pspp{} executes
234231 them together in a single subshell.
235232
236 If no subcommands are specified, then PSPP invokes an interactive
233 If no subcommands are specified, then @pspp{} invokes an interactive
237234 subshell.
238235
239236 @node INCLUDE
241238 @vindex INCLUDE
242239
243240 @display
244 INCLUDE [FILE=]'file-name' [ENCODING='encoding'].
245 @end display
246
247 @cmd{INCLUDE} causes the PSPP command processor to read an
241 INCLUDE [FILE=]'@var{file_name}' [ENCODING='@var{encoding}'].
242 @end display
243
244 @cmd{INCLUDE} causes the @pspp{} command processor to read an
248245 additional command file as if it were included bodily in the current
249246 command file.
250247 If errors are encountered in the included file, then command processing will
253250 memory.
254251
255252 The @cmd{INSERT} command (@pxref{INSERT}) is a more flexible
256 alternative to @cmd{INCLUDE}. An INCLUDE command acts the same as
257 INSERT with ERROR=STOP CD=NO SYNTAX=BATCH specified.
258
259 The optional ENCODING subcommand has the same meaning as on INSERT.
253 alternative to @cmd{INCLUDE}. An @cmd{INCLUDE} command acts the same as
254 @cmd{INSERT} with @subcmd{ERROR=STOP CD=NO SYNTAX=BATCH} specified.
255
256 The optional @subcmd{ENCODING} subcommand has the same meaning as with @cmd{INSERT}.
260257
261258 @node INSERT
262259 @section INSERT
263260 @vindex INSERT
264261
265262 @display
266 INSERT [FILE=]'file-name'
263 INSERT [FILE=]'@var{file_name}'
267264 [CD=@{NO,YES@}]
268265 [ERROR=@{CONTINUE,STOP@}]
269266 [SYNTAX=@{BATCH,INTERACTIVE@}]
270 [ENCODING='encoding'].
267 [ENCODING=@{LOCALE, '@var{charset_name}'@}].
271268 @end display
272269
273270 @cmd{INSERT} is similar to @cmd{INCLUDE} (@pxref{INCLUDE})
275272 It causes the command processor to read a file as if it were embedded in the
276273 current command file.
277274
278 If @samp{CD=YES} is specified, then before including the file, the
275 If @subcmd{CD=YES} is specified, then before including the file, the
279276 current directory will be changed to the directory of the included
280277 file.
281278 The default setting is @samp{CD=NO}.
285282 It will not revert to its original setting even after the included
286283 file is finished processing.
287284
288 If @samp{ERROR=STOP} is specified, errors encountered in the
285 If @subcmd{ERROR=STOP} is specified, errors encountered in the
289286 inserted file will cause processing to immediately cease.
290287 Otherwise processing will continue at the next command.
291 The default setting is @samp{ERROR=CONTINUE}.
292
293 If @samp{SYNTAX=INTERACTIVE} is specified then the syntax contained in
288 The default setting is @subcmd{ERROR=CONTINUE}.
289
290 If @subcmd{SYNTAX=INTERACTIVE} is specified then the syntax contained in
294291 the included file must conform to interactive syntax
295292 conventions. @xref{Syntax Variants}.
296 The default setting is @samp{SYNTAX=BATCH}.
297
298 ENCODING optionally specifies the character set used by the included
293 The default setting is @subcmd{SYNTAX=BATCH}.
294
295 @subcmd{ENCODING} optionally specifies the character set used by the included
299296 file. Its argument, which is not case-sensitive, must be in one of
300297 the following forms:
301298
302299 @table @asis
303 @item @code{Locale}
304 The encoding used by the system locale, or as overridden by the SET
305 LOCALE command (@pxref{SET}). On Unix systems, environment variables,
306 e.g.@: @env{LANG} or @env{LC_ALL}, determine the system locale.
307
308 @item IANA character set name
309 One of the character set names listed by IANA at
300 @item @subcmd{LOCALE}
301 The encoding used by the system locale, or as overridden by the
302 @cmd{SET} command (@pxref{SET}). On GNU/Linux and other Unix-like systems,
303 environment variables, e.g.@: @env{LANG} or @env{LC_ALL}, determine the
304 system locale.
305
306 @item @var{charset_name}
307 One of the character set names listed by @acronym{IANA} at
310308 @uref{http://www.iana.org/assignments/character-sets}. Some examples
311309 are @code{ASCII} (United States), @code{ISO-8859-1} (western Europe),
312310 @code{EUC-JP} (Japan), and @code{windows-1252} (Windows). Not all
314312
315313 @item @code{Auto,@var{encoding}}
316314 Automatically detects whether a syntax file is encoded in an Unicode
317 encoding such as UTF-8, UTF-16, or UTF-32. If it is not, then PSPP
318 generally assumes that the file is encoded in @var{encoding} (an IANA
315 encoding such as UTF-8, UTF-16, or UTF-32. If it is not, then @pspp{}
316 generally assumes that the file is encoded in @var{encoding} (an @acronym{IANA}
319317 character set name). However, if @var{encoding} is UTF-8, and the
320 syntax file is not valid UTF-8, PSPP instead assumes that the file
318 syntax file is not valid UTF-8, @pspp{} instead assumes that the file
321319 is encoded in @code{windows-1252}.
322320
323 For best results, @var{encoding} should be an ASCII-compatible
324 encoding (the most common locale encodings are all ASCII-compatible),
325 because encodings that are not ASCII compatible cannot be
321 For best results, @var{encoding} should be an @acronym{ASCII}-compatible
322 encoding (the most common locale encodings are all @acronym{ASCII}-compatible),
323 because encodings that are not @acronym{ASCII} compatible cannot be
326324 automatically distinguished from UTF-8.
327325
328326 @item @code{Auto}
329327 @item @code{Auto,Locale}
330328 Automatic detection, as above, with the default encoding taken from
331 the system locale or the setting on SET LOCALE.
329 the system locale or the setting on @subcmd{SET LOCALE}.
332330 @end table
333331
334332 When ENCODING is not specified, the default is taken from the
344342
345343 @display
346344 PERMISSIONS
347 FILE='file-name'
345 FILE='@var{file_name}'
348346 /PERMISSIONS = @{READONLY,WRITEABLE@}.
349347 @end display
350348
351349 @cmd{PERMISSIONS} changes the permissions of a file.
352350 There is one mandatory subcommand which specifies the permissions to
353351 which the file should be changed.
354 If you set a file's permission to READONLY, then the file will become
352 If you set a file's permission to @subcmd{READONLY}, then the file will become
355353 unwritable either by you or anyone else on the system.
356 If you set the permission to WRITEABLE, then the file will become
354 If you set the permission to @subcmd{WRITEABLE}, then the file will become
357355 writeable by you; the permissions afforded to others will be
358356 unchanged.
359 This command cannot be used if the SAFER setting is active.
357 This command cannot be used if the @subcmd{SAFER} (@pxref{SET}) setting is active.
360358
361359
362360 @node PRESERVE and RESTORE
385383 (data input)
386384 /BLANKS=@{SYSMIS,'.',number@}
387385 /DECIMAL=@{DOT,COMMA@}
388 /FORMAT=fmt_spec
389 /EPOCH=@{AUTOMATIC,year@}
386 /FORMAT=@var{fmt_spec}
387 /EPOCH=@{AUTOMATIC,@var{year}@}
390388 /RIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@}
391389 /RRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@}
392390
393391 (interaction)
394 /MXERRS=max_errs
395 /MXWARNS=max_warnings
396 /WORKSPACE=workspace_size
392 /MXERRS=@var{max_errs}
393 /MXWARNS=@var{max_warnings}
394 /WORKSPACE=@var{workspace_size}
397395
398396 (syntax execution)
399 /LOCALE='locale'
397 /LOCALE='@var{locale}'
400398 /MEXPAND=@{ON,OFF@}
401 /MITERATE=max_iterations
402 /MNEST=max_nest
399 /MITERATE=@var{max_iterations}
400 /MNEST=@var{max_nest}
403401 /MPRINT=@{ON,OFF@}
404 /MXLOOPS=max_loops
405 /SEED=@{RANDOM,seed_value@}
402 /MXLOOPS=@var{max_loops}
403 /SEED=@{RANDOM,@var{seed_value}@}
406404 /UNDEFINED=@{WARN,NOWARN@}
407405
408406 (data output)
409 /CC@{A,B,C,D,E@}=@{'npre,pre,suf,nsuf','npre.pre.suf.nsuf'@}
407 /CC@{A,B,C,D,E@}=@{'@var{npre},@var{pre},@var{suf},@var{nsuf}','@var{npre}.@var{pre}.@var{suf}.@var{nsuf}'@}
410408 /DECIMAL=@{DOT,COMMA@}
411 /FORMAT=fmt_spec
409 /FORMAT=@var{fmt_spec}
412410 /WIB=@{NATIVE,MSBFIRST,LSBFIRST,VAX@}
413411 /WRB=@{NATIVE,ISL,ISB,IDL,IDB,VF,VD,VG,ZS,ZL@}
414412
420418
421419 (output driver options)
422420 /HEADERS=@{NO,YES,BLANK@}
423 /LENGTH=@{NONE,length_in_lines@}
421 /LENGTH=@{NONE,@var{n_lines}@}
424422 /MORE=@{ON,OFF@}
425 /WIDTH=@{NARROW,WIDTH,n_characters@}
423 /WIDTH=@{NARROW,WIDTH,@var{n_characters}@}
426424 /TNUMBERS=@{VALUES,LABELS,BOTH@}
425 /TVARS=@{NAMES,LABELS,BOTH@}
427426
428427 (logging)
429 /JOURNAL=@{ON,OFF@} ['file-name']
428 /JOURNAL=@{ON,OFF@} ['@var{file_name}']
430429
431430 (system files)
432431 /COMPRESSION=@{ON,OFF@}
434433
435434 (miscellaneous)
436435 /SAFER=ON
437 /LOCALE='string'
436 /LOCALE='@var{string}'
438437
439438
440439 (obsolete settings accepted for compatibility, but ignored)
441 /BOXSTRING=@{'xxx','xxxxxxxxxxx'@}
440 /BOXSTRING=@{'@var{xxx}','@var{xxxxxxxxxxx}'@}
442441 /CASE=@{UPPER,UPLOW@}
443442 /CPI=cpi_value
444443 /HIGHRES=@{ON,OFF@}
445 /HISTOGRAM='c'
444 /HISTOGRAM='@var{c}'
446445 /LOWRES=@{AUTO,ON,OFF@}
447 /LPI=lpi_value
446 /LPI=@var{lpi_value}
448447 /MENUS=@{STANDARD,EXTENDED@}
449 /MXMEMORY=max_memory
448 /MXMEMORY=@var{max_memory}
450449 /SCRIPTTAB='c'
451 /TB1=@{'xxx','xxxxxxxxxxx'@}
452 /TBFONTS='string'
450 /TB1=@{'@var{xxx}','@var{xxxxxxxxxxx}'@}
451 /TBFONTS='@var{string}'
453452 /XSORT=@{YES,NO@}
454453 @end display
455454
456455 @cmd{SET} allows the user to adjust several parameters relating to
457 PSPP's execution. Since there are many subcommands to this command, its
456 @pspp{}'s execution. Since there are many subcommands to this command, its
458457 subcommands will be examined in groups.
459458
460 On subcommands that take boolean values, ON and YES are synonym, and
461 as are OFF and NO, when used as subcommand values.
459 For subcommands that take boolean values, @subcmd{ON} and @subcmd{YES} are synonymous,
460 as are @subcmd{OFF} and @subcmd{NO}, when used as subcommand values.
462461
463462 The data input subcommands affect the way that data is read from data
464463 files. The data input subcommands are
473472
474473 @item DECIMAL
475474 @anchor{SET DECIMAL}
476 This value may be set to DOT or COMMA.
477 Setting it to DOT causes the decimal point character to be
475 This value may be set to @subcmd{DOT} or @subcmd{COMMA}.
476 Setting it to @subcmd{DOT} causes the decimal point character to be
478477 @samp{.} and the grouping character to be @samp{,}.
479 Setting it to COMMA
478 Setting it to @subcmd{COMMA}
480479 causes the decimal point character to be @samp{,} and the grouping
481480 character to be @samp{.}.
482481 The default value is determined from the system locale.
491490 data file or used in a date construction expression (@pxref{Date
492491 Construction}). If a 4-digit year is specified for the epoch, then
493492 2-digit years are interpreted starting from that year, known as the
494 epoch. If AUTOMATIC (the default) is specified, then the epoch begins
493 epoch. If @subcmd{AUTOMATIC} (the default) is specified, then the epoch begins
495494 69 years before the current date.
496495
497496 @item RIB
498497 @anchor{SET RIB}
499498
500 PSPP extension to set the byte ordering (endianness) used for reading
499 @pspp{} extension to set the byte ordering (endianness) used for reading
501500 data in IB or PIB format (@pxref{Binary and Hexadecimal Numeric
502 Formats}). In MSBFIRST ordering, the most-significant byte appears at
503 the left end of a IB or PIB field. In LSBFIRST ordering, the
504 least-significant byte appears at the left end. VAX ordering is like
505 MSBFIRST, except that each pair of bytes is in reverse order. NATIVE,
506 the default, is equivalent to MSBFIRST or LSBFIRST depending on the
507 native format of the machine running PSPP.
501 Formats}). In @subcmd{MSBFIRST} ordering, the most-significant byte appears at
502 the left end of a IB or PIB field. In @subcmd{LSBFIRST} ordering, the
503 least-significant byte appears at the left end. @subcmd{VAX} ordering is like
504 @subcmd{MSBFIRST}, except that each pair of bytes is in reverse order. @subcmd{NATIVE},
505 the default, is equivalent to @subcmd{MSBFIRST} or @subcmd{LSBFIRST} depending on the
506 native format of the machine running @pspp{}.
508507
509508 @item RRB
510509 @anchor{SET RRB}
511510
512 PSPP extension to set the floating-point format used for reading data in
511 @pspp{} extension to set the floating-point format used for reading data in
513512 RB format (@pxref{Binary and Hexadecimal Numeric Formats}). The
514513 possibilities are:
515514
516515 @table @asis
517516 @item NATIVE
518 The native format of the machine running PSPP. Equivalent to either IDL
517 The native format of the machine running @pspp{}. Equivalent to either IDL
519518 or IDB.
520519
521520 @item ISL
557556 The default is NATIVE.
558557 @end table
559558
560 Interaction subcommands affect the way that PSPP interacts with an
559 Interaction subcommands affect the way that @pspp{} interacts with an
561560 online user. The interaction subcommands are
562561
563562 @table @asis
564563 @item MXERRS
565 The maximum number of errors before PSPP halts processing of the current
564 The maximum number of errors before @pspp{} halts processing of the current
566565 command file. The default is 50.
567566
568567 @item MXWARNS
569 The maximum number of warnings + errors before PSPP halts processing the
568 The maximum number of warnings + errors before @pspp{} halts processing the
570569 current command file.
571570 The special value of zero means that all warning situations should be ignored.
572571 No warnings will be issued, except a single initial warning advising the user
574573 The default value is 100.
575574 @end table
576575
577 Syntax execution subcommands control the way that PSPP commands
576 Syntax execution subcommands control the way that @pspp{} commands
578577 execute. The syntax execution subcommands are
579578
580579 @table @asis
581580 @item LOCALE
582581 Overrides the system locale for the purpose of reading and writing
583582 syntax and data files. The argument should be a locale name in the
584 general form @code{language_country.encoding}, where @code{language}
585 and @code{country} are 2-character language and country abbreviations,
586 respectively, and @code{encoding} is an IANA character set name.
583 general form @code{@var{language}_@var{country}.@var{encoding}}, where @var{language}
584 and @var{country} are 2-character language and country abbreviations,
585 respectively, and @var{encoding} is an @acronym{IANA} character set name.
587586 Example locales are @code{en_US.UTF-8} (UTF-8 encoded English as
588587 spoken in the United States) and @code{ja_JP.EUC-JP} (EUC-JP encoded
589588 Japanese as spoken in Japan).
596595
597596 @item MXLOOPS
598597 The maximum number of iterations for an uncontrolled loop (@pxref{LOOP}).
599 The default MXLOOPS is 40.
598 The default @var{max_loops} is 40.
600599
601600 @item SEED
602601 The initial pseudo-random number seed. Set to a real number or to
606605 Currently not used.
607606
608607 @item WORKSPACE
609 The maximum amount of memory that PSPP will use to store data being processed.
610 If memory in excess of the workspace size is required, then PSPP will start
608 The maximum amount of memory that @pspp{} will use to store data being processed.
609 If memory in excess of the workspace size is required, then @pspp{} will start
611610 to use temporary files to store the data.
612611 Setting a higher value will, in general, mean procedures will run faster,
613612 but may cause other applications to run slower.
614613 On platforms without virtual memory management, setting a very large workspace
615 may cause PSPP to abort.
614 may cause @pspp{} to abort.
616615 @cindex workspace
617616 @cindex memory, amount used to store cases
618617 @end table
632631 details.
633632
634633 @item DECIMAL
635 The default DOT setting causes the decimal point character to be
636 @samp{.}. A setting of COMMA causes the decimal point character to be
634 The default @subcmd{DOT} setting causes the decimal point character to be
635 @samp{.}. A setting of @subcmd{COMMA} causes the decimal point character to be
637636 @samp{,}.
638637
639638 @item FORMAT
643642 @item WIB
644643 @anchor{SET WIB}
645644
646 PSPP extension to set the byte ordering (endianness) used for writing
645 @pspp{} extension to set the byte ordering (endianness) used for writing
647646 data in IB or PIB format (@pxref{Binary and Hexadecimal Numeric
648 Formats}). In MSBFIRST ordering, the most-significant byte appears at
649 the left end of a IB or PIB field. In LSBFIRST ordering, the
650 least-significant byte appears at the left end. VAX ordering is like
651 MSBFIRST, except that each pair of bytes is in reverse order. NATIVE,
652 the default, is equivalent to MSBFIRST or LSBFIRST depending on the
653 native format of the machine running PSPP.
647 Formats}). In @subcmd{MSBFIRST} ordering, the most-significant byte appears at
648 the left end of a IB or PIB field. In @subcmd{LSBFIRST} ordering, the
649 least-significant byte appears at the left end. @subcmd{VAX} ordering is like
650 @subcmd{MSBFIRST}, except that each pair of bytes is in reverse order. @subcmd{NATIVE},
651 the default, is equivalent to @subcmd{MSBFIRST} or @subcmd{LSBFIRST} depending on the
652 native format of the machine running @pspp{}.
654653
655654 @item WRB
656655 @anchor{SET WRB}
657656
658 PSPP extension to set the floating-point format used for writing data in
657 @pspp{} extension to set the floating-point format used for writing data in
659658 RB format (@pxref{Binary and Hexadecimal Numeric Formats}). The choices
660 are the same as SET RIB. The default is NATIVE.
661 @end table
662
663 In the PSPP text-based interface, the output routing subcommands
659 are the same as @subcmd{SET RIB}. The default is @subcmd{NATIVE}.
660 @end table
661
662 In the @pspp{} text-based interface, the output routing subcommands
664663 affect where output is sent. The following values are allowed for
665664 each of these subcommands:
666665
686685
687686 @table @asis
688687 @item ERRORS
689 Applies to error and warning messages. The default is BOTH.
688 Applies to error and warning messages. The default is @subcmd{BOTH}.
690689
691690 @item MESSAGES
692 Applies to notes. The default is BOTH.
691 Applies to notes. The default is @subcmd{BOTH}.
693692
694693 @item PRINTBACK
695694 Determines whether the syntax used for input is printed back as part
696 of the output. The default is NONE.
695 of the output. The default is @subcmd{NONE}.
697696
698697 @item RESULTS
699698 Applies to everything not in one of the above categories, such as the
700 results of statistical procedures. The default is BOTH.
701 @end table
702
703 These subcommands have no effect on output in the PSPP GUI
699 results of statistical procedures. The default is @subcmd{BOTH}.
700 @end table
701
702 These subcommands have no effect on output in the @pspp{} GUI
704703 environment.
705704
706705 Output driver option subcommands affect output drivers' settings. These
712711 @itemx MORE
713712 @itemx WIDTH
714713 @itemx TNUMBERS
715 The TNUMBERS option sets the way in which values are displayed in output tables.
716 The valid settings are VALUES, LABELS and BOTH.
717 If TNUMBERS is set to VALUES, then all values are displayed with their literal value
714 The @subcmd{TNUMBERS} option sets the way in which values are displayed in output tables.
715 The valid settings are @subcmd{VALUES}, @subcmd{LABELS} and @subcmd{BOTH}.
716 If @subcmd{TNUMBERS} is set to @subcmd{VALUES}, then all values are displayed with their literal value
718717 (which for a numeric value is a number and for a string value an alphanumeric string).
719 If TNUMBERS is set to LABELS, then values are displayed using their assigned labels if any.
718 If @subcmd{TNUMBERS} is set to @subcmd{LABELS}, then values are displayed using their assigned labels if any.
720719 (@xref{VALUE LABELS}.)
721720 If the a value has no label, then it will be displayed using its literal value.
722 If TNUMBERS is set to BOTH, then values will be displayed with both their label
723 (if any) and their literal value in parenthesis.
721 If @subcmd{TNUMBERS} is set to @subcmd{BOTH}, then values will be displayed with both their label
722 (if any) and their literal value in parentheses.
723 @itemx TVARS
724 The @subcmd{TVARS} option sets the way in which variables are displayed in output tables.
725 The valid settings are @subcmd{NAMES}, @subcmd{LABELS} and @subcmd{BOTH}.
726 If @subcmd{TVARS} is set to @subcmd{NAMES}, then all variables are displayed using their names.
727 If @subcmd{TVARS} is set to @subcmd{LABELS}, then variables are displayed using their label if one
728 has been set. If no label has been set, then the name will be used.
729 (@xref{VARIABLE LABELS}.)
730 If @subcmd{TVARS} is set to @subcmd{BOTH}, then variables will be displayed with both their label
731 (if any) and their name in parentheses.
724732 @end table
725733
726734 @cindex headers
738746 @item JOURNAL
739747 @itemx LOG
740748 These subcommands, which are synonyms, control the journal. The
741 default is ON, which causes commands entered interactively to be
749 default is @subcmd{ON}, which causes commands entered interactively to be
742750 written to the journal file. Commands included from syntax files that
743 are included interactively and error messages printed by PSPP are also
744 written to the journal file, prefixed by @samp{>}. OFF disables use
751 are included interactively and error messages printed by @pspp{} are also
752 written to the journal file, prefixed by @samp{>}. @subcmd{OFF} disables use
745753 of the journal.
746754
747755 The journal is named @file{pspp.jnl} by default. A different name may
749757 @end table
750758
751759 System file subcommands affect the default format of system files
752 produced by PSPP. These subcommands are
760 produced by @pspp{}. These subcommands are
753761
754762 @table @asis
755763 @item COMPRESSION
757765
758766 @item SCOMPRESSION
759767 Whether system files created by @cmd{SAVE} or @cmd{XSAVE} are
760 compressed by default. The default is ON.
768 compressed by default. The default is @subcmd{ON}.
761769 @end table
762770
763771 Security subcommands affect the operations that commands are allowed to
769777
770778 @itemize @bullet
771779 @item
772 The ERASE command.
780 The @cmd{ERASE} command.
773781 @item
774 The HOST command.
782 The @cmd{HOST} command.
775783 @item
776 The PERMISSIONS command.
784 The @cmd{PERMISSIONS} command.
777785 @item
778786 Pipes (file names beginning or ending with @samp{|}).
779787 @end itemize
793801 If given as a locale name, only the character encoding of the
794802 locale is relevant.
795803
796 System files written by PSPP will use this encoding.
797 System files read by PSPP, for which the encoding is unknown, will be
804 System files written by @pspp{} will use this encoding.
805 System files read by @pspp{}, for which the encoding is unknown, will be
798806 interpreted using this encoding.
799807
800808 The full list of valid encodings and locale names/alias are operating system
802810 The following are all examples of acceptable syntax on common GNU/Linux
803811 systems.
804812 @example
805
806813 SET LOCALE='iso-8859-1'.
807814
808815 SET LOCALE='ru_RU.cp1251'.
809816
810817 SET LOCALE='japanese'.
811
812818 @end example
813819
814820 Contrary to the intuition, this command does not affect any aspect
816822 @end table
817823
818824 @node SHOW
819 @comment node-name, next, previous, up
820825 @section SHOW
821826 @vindex SHOW
822827
839844 [MXERRS]
840845 [MXLOOPS]
841846 [MXWARNS]
847 [N]
842848 [SCOMPRESSION]
843849 [TEMPDIR]
844850 [UNDEFINED]
848854 [WIDTH]
849855 @end display
850856
851 @cmd{SHOW} can be used to display the current state of PSPP's execution
857 @cmd{SHOW} can be used to display the current state of @pspp{}'s execution
852858 parameters. Parameters that can be changed using @cmd{SET}
853859 (@pxref{SET}), can be examined using @cmd{SHOW} using the subcommand
854 with the same name. @code{SHOW} supports the following additional
860 with the same name. @cmd{SHOW} supports the following additional
855861 subcommands:
856862
857 @table @code
858 @item ALL
863 @table @bullet
864 @item @subcmd{ALL}
859865 Show all settings.
860 @item CC
861 Show all custom currency settings (CCA through CCE).
862 @item DIRECTORY
866 @item @subcmd{CC}
867 Show all custom currency settings (@subcmd{CCA} through @subcmd{CCE}).
868 @item @subcmd{DIRECTORY}
863869 Shows the current working directory.
864 @item ENVIRONMENT
870 @item @subcmd{ENVIRONMENT}
865871 Shows the operating system details.
866 @item TEMPDIR
872 @item @subcmd{N}
873 Reports the number of cases in the active dataset. The reported number is not
874 weighted. If no dataset is defined, then @samp{Unknown} will be reported.
875 @item @subcmd{TEMPDIR}
867876 Shows the path of the directory where temporary files will be stored.
868 @item VERSION
869 Shows the version of this installation of PSPP.
870 @item WARRANTY
871 Show details of the lack of warranty for PSPP.
872 @item COPYING / LICENSE
873 Display the terms of PSPP's copyright licence (@pxref{License}).
874 @end table
875
876 Specifying @cmd{SHOW} without any subcommands is equivalent to SHOW ALL.
877 @item @subcmd{VERSION}
878 Shows the version of this installation of @pspp{}.
879 @item @subcmd{WARRANTY}
880 Show details of the lack of warranty for @pspp{}.
881 @item @subcmd{COPYING} / @subcmd{LICENSE}
882 Display the terms of @pspp{}'s copyright licence (@pxref{License}).
883 @end table
884
885 Specifying @cmd{SHOW} without any subcommands is equivalent to @subcmd{SHOW ALL}.
877886
878887 @node SUBTITLE
879888 @section SUBTITLE
880889 @vindex SUBTITLE
881890
882891 @display
883 SUBTITLE 'subtitle_string'.
892 SUBTITLE '@var{subtitle_string}'.
884893 or
885 SUBTITLE subtitle_string.
886 @end display
887
888 @cmd{SUBTITLE} provides a subtitle to a particular PSPP
894 SUBTITLE @var{subtitle_string}.
895 @end display
896
897 @cmd{SUBTITLE} provides a subtitle to a particular @pspp{}
889898 run. This subtitle appears at the top of each output page below the
890899 title, if headers are enabled on the output device.
891900
898907 @vindex TITLE
899908
900909 @display
901 TITLE 'title_string'.
910 TITLE '@var{title_string}'.
902911 or
903 TITLE title_string.
904 @end display
905
906 @cmd{TITLE} provides a title to a particular PSPP run.
912 TITLE @var{title_string}.
913 @end display
914
915 @cmd{TITLE} provides a title to a particular @pspp{} run.
907916 This title appears at the top of each output page, if headers are enabled
908917 on the output device.
909918
3232
3333 @display
3434 ADD VALUE LABELS
35 /var_list value 'label' [value 'label']@dots{}
35 /@var{var_list} @var{value} '@var{label}' [@var{value} '@var{label}']@dots{}
3636 @end display
3737
3838 @cmd{ADD VALUE LABELS} has the same syntax and purpose as @cmd{VALUE
4444 @vindex DELETE VARIABLES
4545
4646 @display
47 DELETE VARIABLES var_list.
47 DELETE VARIABLES @var{var_list}.
4848 @end display
4949
5050 @cmd{DELETE VARIABLES} deletes the specified variables from the
6161 @vindex DISPLAY
6262
6363 @display
64 DISPLAY [SORTED] NAMES [[/VARIABLES=]var_list].
65 DISPLAY [SORTED] INDEX [[/VARIABLES=]var_list].
66 DISPLAY [SORTED] LABELS [[/VARIABLES=]var_list].
67 DISPLAY [SORTED] VARIABLES [[/VARIABLES=]var_list].
68 DISPLAY [SORTED] DICTIONARY [[/VARIABLES=]var_list].
69 DISPLAY [SORTED] SCRATCH [[/VARIABLES=]var_list].
70 DISPLAY [SORTED] ATTRIBUTES [[/VARIABLES=]var_list].
71 DISPLAY [SORTED] @@ATTRIBUTES [[/VARIABLES=]var_list].
64 DISPLAY [SORTED] NAMES [[/VARIABLES=]@var{var_list}].
65 DISPLAY [SORTED] INDEX [[/VARIABLES=]@var{var_list}].
66 DISPLAY [SORTED] LABELS [[/VARIABLES=]@var{var_list}].
67 DISPLAY [SORTED] VARIABLES [[/VARIABLES=]@var{var_list}].
68 DISPLAY [SORTED] DICTIONARY [[/VARIABLES=]@var{var_list}].
69 DISPLAY [SORTED] SCRATCH [[/VARIABLES=]@var{var_list}].
70 DISPLAY [SORTED] ATTRIBUTES [[/VARIABLES=]@var{var_list}].
71 DISPLAY [SORTED] @@ATTRIBUTES [[/VARIABLES=]@var{var_list}].
7272 DISPLAY [SORTED] VECTORS.
7373 @end display
7474
7878 The following keywords primarily cause information about variables to
7979 be displayed. With these keywords, by default information is
8080 displayed about all variable in the active dataset, in the order that
81 variables occur in the active dataset dictionary. The SORTED keyword
81 variables occur in the active dataset dictionary. The @subcmd{SORTED} keyword
8282 causes output to be sorted alphabetically by variable name. The
83 VARIABLES subcommand limits output to the specified variables.
83 @subcmd{VARIABLES} subcommand limits output to the specified variables.
8484
8585 @table @asis
8686 @item NAMES
114114 @end table
115115
116116 With the @code{VECTOR} keyword, @cmd{DISPLAY} lists all the currently
117 declared vectors. If the SORTED keyword is given, the vectors are
117 declared vectors. If the @subcmd{SORTED} keyword is given, the vectors are
118118 listed in alphabetical order; otherwise, they are listed in textual
119 order of definition within the PSPP syntax file.
119 order of definition within the @pspp{} syntax file.
120120
121121 For related commands, see @ref{DISPLAY DOCUMENTS} and @ref{DISPLAY
122122 FILE LABEL}.
126126 @vindex FORMATS
127127
128128 @display
129 FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
129 FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}.
130130 @end display
131131
132132 @cmd{FORMATS} set both print and write formats for the specified
149149 @vindex LEAVE
150150
151151 @display
152 LEAVE var_list.
152 LEAVE @var{var_list}.
153153 @end display
154154
155155 @cmd{LEAVE} prevents the specified variables from being
163163 After that, it retains its value between cases.
164164
165165 This becomes useful for counters. For instance, in the example below
166 the variable SUM maintains a running total of the values in the ITEM
166 the variable @code{SUM} maintains a running total of the values in the @code{ITEM}
167167 variable.
168168
169169 @example
198198 @vindex MISSING VALUES
199199
200200 @display
201 MISSING VALUES var_list (missing_values).
202
203 missing_values takes one of the following forms:
204 num1
205 num1, num2
206 num1, num2, num3
207 num1 THRU num2
208 num1 THRU num2, num3
209 string1
210 string1, string2
211 string1, string2, string3
212 As part of a range, LO or LOWEST may take the place of num1;
213 HI or HIGHEST may take the place of num2.
201 MISSING VALUES @var{var_list} (@var{missing_values}).
202
203 where @var{missing_values} takes one of the following forms:
204 @var{num1}
205 @var{num1}, @var{num2}
206 @var{num1}, @var{num2}, @var{num3}
207 @var{num1} THRU @var{num2}
208 @var{num1} THRU @var{num2}, @var{num3}
209 @var{string1}
210 @var{string1}, @var{string2}
211 @var{string1}, @var{string2}, @var{string3}
212 As part of a range, @subcmd{LO} or @subcmd{LOWEST} may take the place of @var{num1};
213 @subcmd{HI} or @subcmd{HIGHEST} may take the place of @var{num2}.
214214 @end display
215215
216216 @cmd{MISSING VALUES} sets user-missing values for numeric and string
222222 values in parentheses. Up to three discrete values may be given, or,
223223 for numeric variables only, a range of values optionally accompanied by
224224 a single discrete value. Ranges may be open-ended on one end, indicated
225 through the use of the keyword LO or LOWEST or HI or HIGHEST.
225 through the use of the
226 keyword @subcmd{LO} or @subcmd{LOWEST} or @subcmd{HI} or @subcmd{HIGHEST}.
226227
227228 The @cmd{MISSING VALUES} command takes effect immediately. It is not
228229 affected by conditional and looping constructs such as @cmd{DO IF} or
234235
235236 @display
236237 MODIFY VARS
237 /REORDER=@{FORWARD,BACKWARD@} @{POSITIONAL,ALPHA@} (var_list)@dots{}
238 /RENAME=(old_names=new_names)@dots{}
239 /@{DROP,KEEP@}=var_list
238 /REORDER=@{FORWARD,BACKWARD@} @{POSITIONAL,ALPHA@} (@var{var_list})@dots{}
239 /RENAME=(@var{old_names}=@var{new_names})@dots{}
240 /@{DROP,KEEP@}=@var{var_list}
240241 /MAP
241242 @end display
242243
244245 active dataset.
245246
246247 At least one subcommand must be specified, and no subcommand may be
247 specified more than once. DROP and KEEP may not both be specified.
248
249 The REORDER subcommand changes the order of variables in the active
248 specified more than once. @subcmd{DROP} and @subcmd{KEEP} may not both
249 be specified.
250
251 The @subcmd{REORDER} subcommand changes the order of variables in the active
250252 dataset. Specify one or more lists of variable names in parentheses. By
251253 default, each list of variables is rearranged into the specified order.
252254 To put the variables into the reverse of the specified order, put
253 keyword BACKWARD before the parentheses. To put them into alphabetical
254 order in the dictionary, specify keyword ALPHA before the parentheses.
255 BACKWARD and ALPHA may also be combined.
256
257 To rename variables in the active dataset, specify RENAME, an equals sign
255 keyword @subcmd{BACKWARD} before the parentheses. To put them into alphabetical
256 order in the dictionary, specify keyword @subcmd{ALPHA} before the parentheses.
257 @subcmd{BACKWARD} and @subcmd{ALPHA} may also be combined.
258
259 To rename variables in the active dataset, specify @subcmd{RENAME}, an equals sign
258260 (@samp{=}), and lists of the old variable names and new variable names
259261 separated by another equals sign within parentheses. There must be the
260262 same number of old and new variable names. Each old variable is renamed to
261263 the corresponding new variable name. Multiple parenthesized groups of
262264 variables may be specified.
263265
264 The DROP subcommand deletes a specified list of variables from the
266 The @subcmd{DROP} subcommand deletes a specified list of variables from the
265267 active dataset.
266268
267 The KEEP subcommand keeps the specified list of variables in the active
269 The @subcmd{KEEP} subcommand keeps the specified list of variables in the active
268270 dataset. Any unlisted variables are deleted from the active dataset.
269271
270 MAP is currently ignored.
271
272 If either DROP or KEEP is specified, the data is read; otherwise it is
273 not.
272 @subcmd{MAP} is currently ignored.
273
274 If either @subcmd{DROP} or @subcmd{KEEP} is specified, the data is read;
275 otherwise it is not.
274276
275277 @cmd{MODIFY VARS} may not be specified following @cmd{TEMPORARY}
276278 (@pxref{TEMPORARY}).
281283
282284 @display
283285 MRSETS
284 /MDGROUP NAME=name VARIABLES=var_list VALUE=value
286 /MDGROUP NAME=@var{name} VARIABLES=@var{var_list} VALUE=@var{value}
285287 [CATEGORYLABELS=@{VARLABELS,COUNTEDVALUES@}]
286 [@{LABEL='label',LABELSOURCE=VARLABEL@}]
287
288 /MCGROUP NAME=name VARIABLES=var_list [LABEL='label']
289
290 /DELETE NAME=@{[names],ALL@}
291
292 /DISPLAY NAME=@{[names],ALL@}
288 [@{LABEL='@var{label}',LABELSOURCE=VARLABEL@}]
289
290 /MCGROUP NAME=@var{name} VARIABLES=@var{var_list} [LABEL='@var{label}']
291
292 /DELETE NAME=@{[@var{names}],ALL@}
293
294 /DISPLAY NAME=@{[@var{names}],ALL@}
293295 @end display
294296
295297 @cmd{MRSETS} creates, modifies, deletes, and displays multiple
312314
313315 Any number of subcommands may be specified in any order.
314316
315 The MDGROUP subcommand creates a new multiple dichotomy set or
316 replaces an existing multiple response set. The NAME, VARIABLES, and
317 VALUE specifications are required. The others are optional:
317 The @subcmd{MDGROUP} subcommand creates a new multiple dichotomy set or
318 replaces an existing multiple response set. The @subcmd{NAME},
319 @subcmd{VARIABLES}, and
320 @subcmd{VALUE} specifications are required. The others are optional:
318321
319322 @itemize @bullet
320323 @item
321 NAME specifies the name used in syntax for the new multiple dichotomy
324 @var{NAME} specifies the name used in syntax for the new multiple dichotomy
322325 set. The name must begin with @samp{$}; it must otherwise follow the
323326 rules for identifiers (@pxref{Tokens}).
324327
325328 @item
326 VARIABLES specifies the variables that belong to the set. At least
329 @subcmd{VARIABLES} specifies the variables that belong to the set. At least
327330 two variables must be specified. The variables must be all string or
328331 all numeric.
329332
330333 @item
331 VALUE specifies the counted value. If the variables are numeric, the
334 @subcmd{VALUE} specifies the counted value. If the variables are numeric, the
332335 value must be an integer. If the variables are strings, then the
333336 value must be a string that is no longer than the shortest of the
334337 variables in the set (ignoring trailing spaces).
335338
336339 @item
337 CATEGORYLABELS optionally specifies the source of the labels for each
340 @subcmd{CATEGORYLABELS} optionally specifies the source of the labels for each
338341 category in the set:
339342
340343 @itemize @minus
341344 @item
342 VARLABELS, the default, uses variable labels or, for variables without
343 variable labels, variable names. PSPP warns if two variables have the
345 @subcmd{VARLABELS}, the default, uses variable labels or, for variables without
346 variable labels, variable names. @pspp{} warns if two variables have the
344347 same variable label, since these categories cannot be distinguished in
345348 output.
346349
347350 @item
348 COUNTEDVALUES instead uses each variable's value label for the counted
349 value. PSPP warns if two variables have the same value label for the
351 @subcmd{COUNTEDVALUES} instead uses each variable's value label for the counted
352 value. @pspp{} warns if two variables have the same value label for the
350353 counted value or if one of the variables lacks a value label, since
351354 such categories cannot be distinguished in output.
352355 @end itemize
353356
354357 @item
355 LABEL optionally specifies a label for the multiple response set. If
356 neither LABEL nor LABELSOURCE=VARLABEL is specified, the set is
358 @subcmd{LABEL} optionally specifies a label for the multiple response set. If
359 neither @subcmd{LABEL} nor @subcmd{LABELSOURCE=VARLABEL} is specified, the set is
357360 unlabeled.
358361
359362 @item
360 LABELSOURCE=VARLABEL draws the multiple response set's label from the
363 @subcmd{LABELSOURCE=VARLABEL} draws the multiple response set's label from the
361364 first variable label among the variables in the set; if none of the
362365 variables has a label, the name of the first variable is used.
363 LABELSOURCE=VARLABEL must be used with CATEGORYLABELS=COUNTEDVALUES.
364 It is mutually exclusive with LABEL.
366 @subcmd{LABELSOURCE=VARLABEL} must be used with @subcmd{CATEGORYLABELS=COUNTEDVALUES}.
367 It is mutually exclusive with @subcmd{LABEL}.
365368 @end itemize
366369
367 The MCGROUP subcommand creates a new multiple category set or
368 replaces an existing multiple response set. The NAME and VARIABLES
369 specifications are required, and LABEL is optional. Their meanings
370 are as described above to MDGROUP. PSPP warns if two variables in the
370 The @subcmd{MCGROUP} subcommand creates a new multiple category set or
371 replaces an existing multiple response set. The @subcmd{NAME} and @subcmd{VARIABLES}
372 specifications are required, and @subcmd{LABEL} is optional. Their meanings
373 are as described above in @subcmd{MDGROUP}. @pspp{} warns if two variables in the
371374 set have different value labels for a single value, since each of the
372375 variables in the set should have the same possible categories.
373376
374 The DELETE subcommand deletes multiple response groups. A list of
377 The @subcmd{DELETE} subcommand deletes multiple response groups. A list of
375378 groups may be named within a set of required square brackets, or ALL
376379 may be used to delete all groups.
377380
378 The DISPLAY subcommand displays information about defined multiple
379 response sets. Its syntax is the same as the DELETE subcommand.
381 The @subcmd{DISPLAY} subcommand displays information about defined multiple
382 response sets. Its syntax is the same as the @subcmd{DELETE} subcommand.
380383
381384 Multiple response sets are saved to and read from system files by,
382385 e.g., the @cmd{SAVE} and @cmd{GET} command. Otherwise, multiple
387390 @vindex NUMERIC
388391
389392 @display
390 NUMERIC /var_list [(fmt_spec)].
393 NUMERIC /@var{var_list} [(@var{fmt_spec})].
391394 @end display
392395
393396 @cmd{NUMERIC} explicitly declares new numeric variables, optionally
406409 @vindex PRINT FORMATS
407410
408411 @display
409 PRINT FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
412 PRINT FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}.
410413 @end display
411414
412415 @cmd{PRINT FORMATS} sets the print formats for the specified
420423 @vindex RENAME VARIABLES
421424
422425 @display
423 RENAME VARIABLES (old_names=new_names)@dots{} .
426 RENAME VARIABLES (@var{old_names}=@var{new_names})@dots{} .
424427 @end display
425428
426429 @cmd{RENAME VARIABLES} changes the names of variables in the active
442445
443446 @display
444447 VALUE LABELS
445 /var_list value 'label' [value 'label']@dots{}
448 /@var{var_list} @var{value} '@var{label}' [@var{value} '@var{label}']@dots{}
446449 @end display
447450
448451 @cmd{VALUE LABELS} allows values of numeric and short string
467470 @vindex STRING
468471
469472 @display
470 STRING /var_list (fmt_spec).
473 STRING /@var{var_list} (@var{fmt_spec}).
471474 @end display
472475
473476 @cmd{STRING} creates new string variables for use in
487490
488491 @display
489492 VARIABLE ATTRIBUTE
490 VARIABLES=var_list
491 ATTRIBUTE=name('value') [name('value')]@dots{}
492 ATTRIBUTE=name@b{[}index@b{]}('value') [name@b{[}index@b{]}('value')]@dots{}
493 DELETE=name [name]@dots{}
494 DELETE=name@b{[}index@b{]} [name@b{[}index@b{]}]@dots{}
493 VARIABLES=@var{var_list}
494 ATTRIBUTE=@var{name}('@var{value}') [@var{name}('@var{value}')]@dots{}
495 ATTRIBUTE=@var{name}@b{[}@var{index}@b{]}('@var{value}') [@var{name}@b{[}@var{index}@b{]}('@var{value}')]@dots{}
496 DELETE=@var{name} [@var{name}]@dots{}
497 DELETE=@var{name}@b{[}@var{index}@b{]} [@var{name}@b{[}@var{index}@b{]}]@dots{}
495498 @end display
496499
497500 @cmd{VARIABLE ATTRIBUTE} adds, modifies, or removes user-defined
498501 attributes associated with variables in the active dataset. Custom
499 variable attributes are not interpreted by PSPP, but they are saved as
502 variable attributes are not interpreted by @pspp{}, but they are saved as
500503 part of system files and may be used by other software that reads
501504 them.
502505
503 The required VARIABLES subcommand must come first. Specify the
504 variables to which the following ATTRIBUTE or DELETE subcommand
506 The required @subcmd{VARIABLES} subcommand must come first. Specify the
507 variables to which the following @subcmd{ATTRIBUTE} or @subcmd{DELETE} subcommand
505508 should apply.
506509
507 Use the ATTRIBUTE subcommand to add or modify custom variable
510 Use the @subcmd{ATTRIBUTE} subcommand to add or modify custom variable
508511 attributes. Specify the name of the attribute as an identifier
509512 (@pxref{Tokens}), followed by the desired value, in parentheses, as a
510513 quoted string. The specified attributes are then added or modified in
511 the variables specified on VARIABLES. Attribute names that begin with
512 @code{$} are reserved for PSPP's internal use, and attribute names
513 that begin with @code{@@} or @code{$@@} are not displayed by most PSPP
514 the variables specified on @subcmd{VARIABLES}. Attribute names that begin with
515 @code{$} are reserved for @pspp{}'s internal use, and attribute names
516 that begin with @code{@@} or @code{$@@} are not displayed by most @pspp{}
514517 commands that display other attributes. Other attribute names are not
515518 treated specially.
516519
520523 indexes start at 1, not 0. An attribute array that has a single
521524 element (number 1) is not distinguished from a non-array attribute.
522525
523 Use the DELETE subcommand to delete an attribute from the variable
524 specified on VARIABLES. Specify an attribute name by itself to delete
526 Use the @subcmd{DELETE} subcommand to delete an attribute from the variable
527 specified on @subcmd{VARIABLES}. Specify an attribute name by itself to delete
525528 an entire attribute, including all array elements for attribute
526529 arrays. Specify an attribute name followed by an array index in
527530 square brackets to delete a single element of an attribute array. In
541544
542545 @display
543546 VARIABLE LABELS
544 var_list 'var_label'
545 [ /var_list 'var_label']
546 .
547 .
548 .
549 [ /var_list 'var_label']
547 @var{var_list} '@var{var_label}'
548 [ /@var{var_list} '@var{var_label}']
549 .
550 .
551 .
552 [ /@var{var_list} '@var{var_label}']
550553 @end display
551554
552555 @cmd{VARIABLE LABELS} associates explanatory names
560563
561564
562565 @node VARIABLE ALIGNMENT
563 @comment node-name, next, previous, u
564566 @section VARIABLE ALIGNMENT
565567 @vindex VARIABLE ALIGNMENT
566568
567569 @display
568570 VARIABLE ALIGNMENT
569 var_list ( LEFT | RIGHT | CENTER )
570 [ /var_list ( LEFT | RIGHT | CENTER ) ]
571 .
572 .
573 .
574 [ /var_list ( LEFT | RIGHT | CENTER ) ]
571 @var{var_list} ( LEFT | RIGHT | CENTER )
572 [ /@var{var_list} ( LEFT | RIGHT | CENTER ) ]
573 .
574 .
575 .
576 [ /@var{var_list} ( LEFT | RIGHT | CENTER ) ]
575577 @end display
576578
577579 @cmd{VARIABLE ALIGNMENT} sets the alignment of variables for display editing
578580 purposes. This only has effect for third party software. It does not affect
579 the display of variables in the PSPP output.
581 the display of variables in the @pspp{} output.
580582
581583
582584
583585
584586 @node VARIABLE WIDTH
585 @comment node-name, next, previous, up
586587 @section VARIABLE WIDTH
587588 @vindex VARIABLE WIDTH
588589 @display
589590 VARIABLE WIDTH
590 var_list (width)
591 [ /var_list (width) ]
592 .
593 .
594 .
595 [ /var_list (width) ]
591 @var{var_list} (width)
592 [ /@var{var_list} (width) ]
593 .
594 .
595 .
596 [ /@var{var_list} (width) ]
596597 @end display
597598
598599 @cmd{VARIABLE WIDTH} sets the column width of variables for display editing
599600 purposes. This only affects third party software. It does not affect
600 the display of variables in the PSPP output.
601 the display of variables in the @pspp{} output.
601602
602603
603604 @node VARIABLE LEVEL
604 @comment node-name, next, previous, up
605605 @section VARIABLE LEVEL
606606 @vindex VARIABLE LEVEL
607607 @display
608608 VARIABLE LEVEL
609 var_list ( SCALE | NOMINAL | ORDINAL )
610 [ /var_list ( SCALE | NOMINAL | ORDINAL ) ]
611 .
612 .
613 .
614 [ /var_list ( SCALE | NOMINAL | ORDINAL ) ]
609 @var{var_list} ( SCALE | NOMINAL | ORDINAL )
610 [ /@var{var_list} ( SCALE | NOMINAL | ORDINAL ) ]
611 .
612 .
613 .
614 [ /@var{var_list} ( SCALE | NOMINAL | ORDINAL ) ]
615615 @end display
616616
617617 @cmd{VARIABLE LEVEL} sets the measurement level of variables.
624624
625625 @display
626626 Two possible syntaxes:
627 VECTOR vec_name=var_list.
628 VECTOR vec_name_list(count [format]).
627 VECTOR @var{vec_name}=@var{var_list}.
628 VECTOR @var{vec_name_list}(@var{count} [@var{format}]).
629629 @end display
630630
631631 @cmd{VECTOR} allows a group of variables to be accessed as if they
659659 @vindex WRITE FORMATS
660660
661661 @display
662 WRITE FORMATS var_list (fmt_spec) [var_list (fmt_spec)]@dots{}.
662 WRITE FORMATS @var{var_list} (@var{fmt_spec}) [@var{var_list} (@var{fmt_spec})]@dots{}.
663663 @end display
664664
665665 @cmd{WRITE FORMATS} sets the write formats for the specified variables
666666 to the specified format specification. Its syntax is identical to
667 that of FORMATS (@pxref{FORMATS}), but @cmd{WRITE FORMATS} sets only
667 that of @cmd{FORMATS} (@pxref{FORMATS}), but @cmd{WRITE FORMATS} sets only
668668 write formats, not print formats.
24112411 GdkPoint old_max_position;
24122412 gint handle_size;
24132413 gint border_width = GTK_CONTAINER (xpaned)->border_width;
2414 float fX;
2415 float fY;
24162414
24172415 g_return_if_fail (GTK_IS_XPANED (xpaned));
24182416
24222420 old_min_position.y = xpaned->min_position.y;
24232421 old_max_position.x = xpaned->max_position.x;
24242422 old_max_position.y = xpaned->max_position.y;
2425
2426 fX = 100.0f * (float) old_position.x / (float) allocation->width;
2427 fY = 100.0f * (float) old_position.y / (float) allocation->height;
24282423
24292424 xpaned->min_position.x = xpaned->top_left_child_shrink ? 0 : top_left_child_req->width;
24302425 xpaned->min_position.y = xpaned->top_left_child_shrink ? 0 : top_left_child_req->height;
25732568
25742569 xpaned->last_allocation.width = allocation->width;
25752570 xpaned->last_allocation.height = allocation->height;
2576
2577 fX = 100.0f * (float) old_position.x / (float) allocation->width;
2578 fY = 100.0f * (float) old_position.y / (float) allocation->height;
25792571 }
25802572
25812573 static void gtk_xpaned_set_saved_focus (GtkXPaned* xpaned, GtkWidget* widget)
+981
-1915
po/ca.po less more
66 # Javier Gómez Serrano, 2009.
77 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2010.
88 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
9 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
9 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2012.
1010 msgid ""
1111 msgstr ""
12 "Project-Id-Version: pspp-0.7.8\n"
12 "Project-Id-Version: pspp-0.7.9\n"
1313 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
14 "POT-Creation-Date: 2012-02-26 16:39+0100\n"
15 "PO-Revision-Date: 2011-08-17 11:48+0200\n"
14 "POT-Creation-Date: 2012-02-03 19:12-0800\n"
15 "PO-Revision-Date: 2012-04-26 01:09+0200\n"
1616 "Last-Translator: Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>\n"
1717 "Language-Team: Catalan <ca@dodds.net>\n"
1818 "Language: ca\n"
2525 msgid "Sorry. The help system hasn't yet been implemented."
2626 msgstr "Disculpeu. El sistema d'ajuda encara no ha estat implementat."
2727
28 #: src/ui/gui/psppire-buttonbox.c:329
28 #: src/ui/gui/psppire-buttonbox.c:329 src/ui/gui/psppire-buttonbox.c:487
2929 msgid "Continue"
3030 msgstr "Continuar"
3131
32 #: src/ui/gui/psppire-dictview.c:469 src/language/dictionary/split-file.c:82
32 #: src/ui/gui/psppire-buttonbox.c:485
33 msgid "OK"
34 msgstr "OK"
35
36 #: src/ui/gui/psppire-buttonbox.c:486
37 msgid "Go To"
38 msgstr "Anar a"
39
40 #: src/ui/gui/psppire-buttonbox.c:488
41 msgid "Cancel"
42 msgstr "Cancel·lar"
43
44 #: src/ui/gui/psppire-buttonbox.c:489
45 msgid "Help"
46 msgstr "Ajuda"
47
48 #: src/ui/gui/psppire-buttonbox.c:490
49 msgid "Reset"
50 msgstr "Reiniciar"
51
52 #: src/ui/gui/psppire-buttonbox.c:491
53 msgid "Paste"
54 msgstr "Enganxa"
55
56 #: src/ui/gui/psppire-dictview.c:466 src/language/dictionary/split-file.c:82
3357 #: src/language/dictionary/sys-file-info.c:148
34 #: src/language/dictionary/sys-file-info.c:332
35 #: src/language/dictionary/sys-file-info.c:646
58 #: src/language/dictionary/sys-file-info.c:331
59 #: src/language/dictionary/sys-file-info.c:645
3660 #: src/language/stats/descriptives.c:895
3761 #: src/language/data-io/data-parser.c:683
3862 #: src/language/data-io/data-parser.c:722 src/language/data-io/print.c:403
3963 msgid "Variable"
4064 msgstr "Variable"
4165
42 #: src/ui/gui/psppire-dictview.c:506
66 #: src/ui/gui/psppire-dictview.c:503
4367 msgid "Prefer variable labels"
4468 msgstr "Prefereixo les etiquetes de variable"
4569
46 #: src/ui/gui/psppire-var-view.c:201
70 #: src/ui/gui/psppire-var-view.c:192
4771 #, c-format
4872 msgid "Var%d"
4973 msgstr "Var%d"
5377 msgid "An error occurred while opening `%s': %s."
5478 msgstr "S'ha produït un error en obrir `%s': %s."
5579
56 #: src/data/any-reader.c:111
80 #: src/data/any-reader.c:105
5781 #, c-format
5882 msgid "`%s' is not a system or portable file."
5983 msgstr "`%s' no és un arxiu del sistema o portàtil."
6084
61 #: src/data/any-reader.c:117 src/data/any-writer.c:67
85 #: src/data/any-reader.c:111 src/data/any-writer.c:67
6286 msgid "The inline file is not allowed here."
6387 msgstr "L'arxiu en línia no està permès aquí."
6488
7599 #: src/data/calendar.c:119
76100 #, c-format
77101 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
78 msgstr ""
79 "La data %04d-%d-%d és anterior de la data acceptada més antiga, 1582-10-15."
102 msgstr "La data %04d-%d-%d és anterior de la data acceptada més antiga, 1582-10-15."
80103
81104 #: src/data/casereader-filter.c:221
82 msgid ""
83 "At least one case in the data read had a weight value that was user-missing, "
84 "system-missing, zero, or negative. These case(s) were ignored."
85 msgstr ""
86 "Almenys un cas a la lectura de dades tenia un valor de ponderació que és "
87 "perdut d'usuari, de sistema, zero o negatiu. Aquest(s) cas(os) van ser "
88 "ignorat(s)."
105 msgid "At least one case in the data read had a weight value that was user-missing, system-missing, zero, or negative. These case(s) were ignored."
106 msgstr "Almenys un cas a la lectura de dades tenia un valor de ponderació que és perdut d'usuari, de sistema, zero o negatiu. Aquest(s) cas(os) van ser ignorat(s)."
89107
90108 #. TRANSLATORS: this fragment will be interpolated into messages in fh_lock()
91109 #. that identify types of files.
93111 msgid "CSV file"
94112 msgstr "arxiu CSV"
95113
96 #: src/data/csv-file-writer.c:161 src/data/sys-file-writer.c:227
114 #: src/data/csv-file-writer.c:161 src/data/sys-file-writer.c:225
97115 #, c-format
98116 msgid "Error opening `%s' for writing as a system file: %s."
99117 msgstr "Error en obrir `%s' per gravar com arxiu de sistema: %s."
166184 msgstr "A la data s'espera un delimitador entre els camps."
167185
168186 #: src/data/data-in.c:901
169 msgid ""
170 "Unrecognized month format. Months may be specified as Arabic or Roman "
171 "numerals or as at least 3 letters of their English names."
172 msgstr ""
173 "Format de mes no reconegut. Els mesos poden ser especificats com a números "
174 "Aràbics o Romans, o com a mínim 3 lletres dels seus noms en Anglès."
187 msgid "Unrecognized month format. Months may be specified as Arabic or Roman numerals or as at least 3 letters of their English names."
188 msgstr "Format de mes no reconegut. Els mesos poden ser especificats com a números Aràbics o Romans, o com a mínim 3 lletres dels seus noms en Anglès."
175189
176190 #: src/data/data-in.c:928
177191 #, c-format
212226 msgstr "Minut (%ld) ha de ser entre 0 i 59."
213227
214228 #: src/data/data-in.c:1070
215 msgid ""
216 "Unrecognized weekday name. At least the first two letters of an English "
217 "weekday name must be specified."
218 msgstr ""
219 "Dia de la setmana no reconegut. Al menys s'han d'especificar les dues "
220 "primeres lletres del nom en anglès."
229 msgid "Unrecognized weekday name. At least the first two letters of an English weekday name must be specified."
230 msgstr "Dia de la setmana no reconegut. Al menys s'han d'especificar les dues primeres lletres del nom en anglès."
221231
222232 #: src/data/data-in.c:1196
223233 #, c-format
236246
237247 #: src/data/dataset-reader.c:54
238248 #, c-format
239 msgid ""
240 "Cannot read from dataset %s because no dictionary or data has been written "
241 "to it yet."
242 msgstr ""
243 "No es pot llegir de l'arxius de dades actiu %s perquè no s'ha omplert encara "
244 "amb cap diccionari o dades."
249 msgid "Cannot read from dataset %s because no dictionary or data has been written to it yet."
250 msgstr "No es pot llegir de l'arxius de dades actiu %s perquè no s'ha omplert encara amb cap diccionari o dades."
245251
246252 #. TRANSLATORS: this fragment will be interpolated into
247253 #. messages in fh_lock() that identify types of files.
262268 msgstr "zero"
263269
264270 #: src/data/dictionary.c:1004
265 msgid ""
266 "At least one case in the data file had a weight value that was user-missing, "
267 "system-missing, zero, or negative. These case(s) were ignored."
268 msgstr ""
269 "Almenys un cas a l'arxiu de dades tenia un valor de ponderació que és perdut "
270 "d'usuari, de sistema, zero o negatiu. Aquest(s) cas(os) van ser ignorat(s)."
271
272 #: src/data/dictionary.c:1333
271 msgid "At least one case in the data file had a weight value that was user-missing, system-missing, zero, or negative. These case(s) were ignored."
272 msgstr "Almenys un cas a l'arxiu de dades tenia un valor de ponderació que és perdut d'usuari, de sistema, zero o negatiu. Aquest(s) cas(os) van ser ignorat(s)."
273
274 #: src/data/dictionary.c:1330
273275 #, c-format
274276 msgid "Truncating document line to %d bytes."
275277 msgstr "Línia de document tallada a %d bytes."
281283 #: src/data/file-handle-def.c:465
282284 #, c-format
283285 msgid "Can't read from %s as a %s because it is already being read as a %s."
284 msgstr ""
285 "No es pot llegir de %s com una %s perquè ja està sent llegit com una %s."
286 msgstr "No es pot llegir de %s com una %s perquè ja està sent llegit com una %s."
286287
287288 #: src/data/file-handle-def.c:469
288289 #, c-format
297298 #: src/data/file-name.c:173
298299 #, c-format
299300 msgid "Not opening pipe file `%s' because SAFER option set."
300 msgstr ""
301 "No obrir l'arxiu de transferència '%s' perquè l'opció SAFER està activada."
301 msgstr "No obrir l'arxiu de transferència '%s' perquè l'opció SAFER està activada."
302302
303303 #: src/data/format.c:320
304304 msgid "Input format"
321321 #: src/data/format.c:345
322322 #, c-format
323323 msgid "%s %s specifies width %d, but %s requires a width between %d and %d."
324 msgstr ""
325 "%s %s especifica amplada %d, però %s requereix una amplada entre %d i %d."
324 msgstr "%s %s especifica amplada %d, però %s requereix una amplada entre %d i %d."
326325
327326 #: src/data/format.c:354
328327 #, c-format
329328 msgid "%s %s specifies %d decimal place, but %s does not allow any decimals."
330 msgid_plural ""
331 "%s %s specifies %d decimal places, but %s does not allow any decimals."
329 msgid_plural "%s %s specifies %d decimal places, but %s does not allow any decimals."
332330 msgstr[0] "%s %s especifica %d lloc decimal, però %s no en permet cap."
333331 msgstr[1] "%s %s especifica %d llocs decimals, però %s no en permet cap."
334332
335333 #: src/data/format.c:365
336334 #, c-format
337 msgid ""
338 "%s %s specifies %d decimal place, but the given width allows at most %d "
339 "decimals."
340 msgid_plural ""
341 "%s %s specifies %d decimal places, but the given width allows at most %d "
342 "decimals."
343 msgstr[0] ""
344 "%s %s especifica %d lloc decimal, però l'amplada donada permet com a molt %d "
345 "decimals."
346 msgstr[1] ""
347 "%s %s especifica %d llocs decimals, però l'amplada donada permet com a molt "
348 "%d decimals."
335 msgid "%s %s specifies %d decimal place, but the given width allows at most %d decimals."
336 msgid_plural "%s %s specifies %d decimal places, but the given width allows at most %d decimals."
337 msgstr[0] "%s %s especifica %d lloc decimal, però l'amplada donada permet com a molt %d decimals."
338 msgstr[1] "%s %s especifica %d llocs decimals, però l'amplada donada permet com a molt %d decimals."
349339
350340 #: src/data/format.c:372
351341 #, c-format
352 msgid ""
353 "%s %s specifies %d decimal place, but the given width does not allow for any "
354 "decimals."
355 msgid_plural ""
356 "%s %s specifies %d decimal places, but the given width does not allow for "
357 "any decimals."
358 msgstr[0] ""
359 "%s %s especifica %d lloc decimal, però l'amplada donada no en permet cap."
360 msgstr[1] ""
361 "%s %s especifica %d llocs decimals, però l'amplada donada no en permet cap."
342 msgid "%s %s specifies %d decimal place, but the given width does not allow for any decimals."
343 msgid_plural "%s %s specifies %d decimal places, but the given width does not allow for any decimals."
344 msgstr[0] "%s %s especifica %d lloc decimal, però l'amplada donada no en permet cap."
345 msgstr[1] "%s %s especifica %d llocs decimals, però l'amplada donada no en permet cap."
362346
363347 #: src/data/format.c:411
364348 #, c-format
375359 msgid "Numeric"
376360 msgstr "Numèric"
377361
378 #: src/data/format.c:413 src/data/sys-file-reader.c:1713
379 #: src/data/sys-file-reader.c:1715 src/language/xforms/recode.c:506
362 #: src/data/format.c:413 src/data/sys-file-reader.c:1674
363 #: src/data/sys-file-reader.c:1676 src/language/xforms/recode.c:506
380364 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
381365 #: src/language/xforms/recode.c:520
382366 #: src/language/dictionary/apply-dictionary.c:77
384368 msgid "numeric"
385369 msgstr "numèric"
386370
387 #: src/data/format.c:413 src/data/sys-file-reader.c:1713
388 #: src/data/sys-file-reader.c:1715 src/language/xforms/recode.c:506
371 #: src/data/format.c:413 src/data/sys-file-reader.c:1674
372 #: src/data/sys-file-reader.c:1676 src/language/xforms/recode.c:506
389373 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
390374 #: src/language/xforms/recode.c:520
391375 #: src/language/dictionary/apply-dictionary.c:77
423407 msgstr "Usuari"
424408
425409 #: src/data/gnumeric-reader.c:35 src/data/ods-reader.c:38
426 #, fuzzy, c-format
410 #, c-format
427411 msgid "Support for %s files was not compiled into this installation of PSPP"
428 msgstr ""
429 "Suport per a arxius Gnumeric no va ser compilat en aquesta instal·lació de "
430 "PSPP"
412 msgstr "Aquesta instal·lació de PSPP no s'ha compilat amb suport per a arxius %s "
431413
432414 #: src/data/gnumeric-reader.c:289
433415 #, c-format
439421 msgid "Invalid cell range `%s'"
440422 msgstr "Interval de cel·la `%s' invàlid"
441423
442 #: src/data/gnumeric-reader.c:447 src/data/ods-reader.c:432
443 #: src/data/ods-reader.c:547
424 #: src/data/gnumeric-reader.c:447 src/data/ods-reader.c:430
425 #: src/data/ods-reader.c:545
444426 #, c-format
445427 msgid "Selected sheet or range of spreadsheet `%s' is empty."
446428 msgstr "El full o fulls de càlcul seleccionats `%s' és buit."
457439 #: src/data/identifier2.c:92
458440 #, c-format
459441 msgid "`%s' may not be used as an identifier because it is a reserved word."
460 msgstr ""
461 "'%s' no pot ser utilitzat com a identificador perquè es una paraula "
462 "reservada."
442 msgstr "'%s' no pot ser utilitzat com a identificador perquè es una paraula reservada."
463443
464444 #: src/data/identifier2.c:103
465445 #, c-format
466 msgid ""
467 "`%s' may not be used as an identifier because it contains ill-formed UTF-8 "
468 "at byte offset %tu."
469 msgstr ""
470 "'%s' no pot ser utilitzat com a identificador perquè conté malformació UTF-8 "
471 "al byte en posició %tu."
446 msgid "`%s' may not be used as an identifier because it contains ill-formed UTF-8 at byte offset %tu."
447 msgstr "'%s' no pot ser utilitzat com a identificador perquè conté malformació UTF-8 al byte en posició %tu."
472448
473449 #: src/data/identifier2.c:114
474450 #, c-format
475 msgid ""
476 "Character %s (in `%s') may not appear as the first character in a identifier."
477 msgstr ""
478 "El caracter %s (a `%s') no pot aparèixer com a primer caracter a un "
479 "identificador."
451 msgid "Character %s (in `%s') may not appear as the first character in a identifier."
452 msgstr "El caracter %s (a `%s') no pot aparèixer com a primer caracter a un identificador."
480453
481454 #: src/data/identifier2.c:126
482455 #, c-format
520493
521494 #: src/data/mrset.c:83
522495 #, c-format
523 msgid ""
524 "%s is not a valid name for a multiple response set. Multiple response set "
525 "names must begin with `$'."
526 msgstr ""
527 "%s no és un nom vàlid de variable per a un conjunt de resposta múltiple. Els "
528 "conjunts de resposta múltiple han de començar amb `$'."
496 msgid "%s is not a valid name for a multiple response set. Multiple response set names must begin with `$'."
497 msgstr "%s no és un nom vàlid de variable per a un conjunt de resposta múltiple. Els conjunts de resposta múltiple han de començar amb `$'."
529498
530499 #: src/data/ods-reader.c:359
531 #, fuzzy, c-format
500 #, c-format
532501 msgid "Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."
533 msgstr "Error en obrir `%s' per a la lectura com a arxiu Gnumeric: %s."
502 msgstr "Error en obrir `%s' per a la lectura com a arxiu full de càlcul OpenDocument: %s."
534503
535504 #: src/data/ods-reader.c:368
536505 #, c-format
537506 msgid "Could not extract OpenDocument spreadsheet from file `%s': %s."
538 msgstr ""
507 msgstr "NO ha estat possible extraure el full de càlcul OpenDocument de l'arxiu `%s': %s."
539508
540509 #: src/data/por-file-reader.c:101
541510 #, c-format
564533
565534 #: src/data/por-file-reader.c:283
566535 #, c-format
567 msgid ""
568 "An error occurred while opening `%s' for reading as a portable file: %s."
536 msgid "An error occurred while opening `%s' for reading as a portable file: %s."
569537 msgstr "Error en obrir `%s' per a la lectura com a arxiu portàtil: %s."
570538
571539 #: src/data/por-file-reader.c:304
611579
612580 #: src/data/por-file-reader.c:601
613581 #, c-format
614 msgid ""
615 "%s: Bad format specifier byte (%d). Variable will be assigned a default "
616 "format."
617 msgstr ""
618 "%s: Byte especificador de format invàlid (%d). S'assignarà el format "
619 "predeterminat a la variable."
582 msgid "%s: Bad format specifier byte (%d). Variable will be assigned a default format."
583 msgstr "%s: Byte especificador de format invàlid (%d). S'assignarà el format predeterminat a la variable."
620584
621585 #: src/data/por-file-reader.c:622
622586 #, c-format
626590 #: src/data/por-file-reader.c:626
627591 #, c-format
628592 msgid "String variable %s with width %d has invalid format specifier %s."
629 msgstr ""
630 "La variable en cadena %s amb longitud %d té una especificació de format "
631 "invàlida %s."
593 msgstr "La variable en cadena %s amb longitud %d té una especificació de format invàlida %s."
632594
633595 #: src/data/por-file-reader.c:650
634596 msgid "Expected variable count record."
658620 msgid "Invalid variable name `%s' in position %d."
659621 msgstr "Nom de la variable invàlid `%s' en la posició %d."
660622
661 #: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:997
623 #: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:963
662624 #, c-format
663625 msgid "Bad width %d for variable %s."
664626 msgstr "Amplada %d incorrecte per a la variable %s."
680642
681643 #: src/data/por-file-reader.c:804
682644 #, c-format
683 msgid ""
684 "Cannot assign value labels to %s and %s, which have different variable types."
685 msgstr ""
686 "No es pot assignar etiquetes de valor a %s i %s, que tenen diferent tipus de "
687 "variables."
645 msgid "Cannot assign value labels to %s and %s, which have different variable types."
646 msgstr "No es pot assignar etiquetes de valor a %s i %s, que tenen diferent tipus de variables."
688647
689648 #: src/data/por-file-writer.c:140
690649 #, c-format
696655 msgid "Error opening `%s' for writing as a portable file: %s."
697656 msgstr "Error al obrir `%s' per a escriure com a arxiu portàtil: %s."
698657
699 #: src/data/por-file-writer.c:503
658 #: src/data/por-file-writer.c:502
700659 #, c-format
701660 msgid "An I/O error occurred writing portable file `%s'."
702661 msgstr "Error E/S en escriure l'arxiu portàtil `%s'."
703662
704663 #: src/data/psql-reader.c:47
705 msgid ""
706 "Support for reading postgres databases was not compiled into this "
707 "installation of PSPP"
708 msgstr ""
709 "El suport per a la lectura de les bases de dades postgres no va ser compilat "
710 "en aquesta instal·lació de PSPP"
664 msgid "Support for reading postgres databases was not compiled into this installation of PSPP"
665 msgstr "El suport per a la lectura de les bases de dades postgres no va ser compilat en aquesta instal·lació de PSPP"
711666
712667 #: src/data/psql-reader.c:241
713668 msgid "Memory error whilst opening psql source"
720675
721676 #: src/data/psql-reader.c:262
722677 #, c-format
723 msgid ""
724 "Postgres server is version %s. Reading from versions earlier than 8.0 is not "
725 "supported."
726 msgstr ""
727 "La versió del servidor Postgres és la %s. No es possible la lectura des de "
728 "versions anteriors a la 8.0."
678 msgid "Postgres server is version %s. Reading from versions earlier than 8.0 is not supported."
679 msgstr "La versió del servidor Postgres és la %s. No es possible la lectura des de versions anteriors a la 8.0."
729680
730681 #: src/data/psql-reader.c:282
731 msgid ""
732 "Connection is unencrypted, but unencrypted connections have not been "
733 "permitted."
734 msgstr ""
735 "La connexió no està xifrada, però les connexions sense xifrar no estan "
736 "permeses."
682 msgid "Connection is unencrypted, but unencrypted connections have not been permitted."
683 msgstr "La connexió no està xifrada, però les connexions sense xifrar no estan permeses."
737684
738685 #: src/data/psql-reader.c:318 src/data/psql-reader.c:343
739686 #: src/data/psql-reader.c:353
747694 msgstr "OID %d no admès. Valors SYSMIS seran inserits."
748695
749696 #: src/data/settings.c:390
750 msgid ""
751 "MXWARNS set to zero. No further warnings will be given even when "
752 "potentially problematic situations are encountered."
753 msgstr ""
754 "S'assigna zero a MXWARNS. No es proporcionaran més avisos tot, i que "
755 "podrien trobar-se situacions problemàtiques posteriors."
697 msgid "MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."
698 msgstr "S'assigna zero a MXWARNS. No es proporcionaran més avisos tot, i que podrien trobar-se situacions problemàtiques posteriors."
756699
757700 #: src/data/settings.c:397
758701 #, c-format
759 msgid ""
760 "Warnings re-enabled. %d warnings will be issued before aborting syntax "
761 "processing."
762 msgstr ""
763 "Avisos activats de nou. Es tindran en compte %d avisos abans d'abortar el "
764 "procés."
702 msgid "Warnings re-enabled. %d warnings will be issued before aborting syntax processing."
703 msgstr "Avisos activats de nou. Es tindran en compte %d avisos abans d'abortar el procés."
765704
766705 #: src/data/settings.c:605
767706 #, c-format
768 msgid ""
769 "%s: Custom currency string `%s' does not contain exactly three periods or "
770 "commas (or it contains both)."
771 msgstr ""
772 "%s: Cadena de moneda personalitzada '%s' no conté exactament tres punts o "
773 "comes (o els conté ambdós)."
707 msgid "%s: Custom currency string `%s' does not contain exactly three periods or commas (or it contains both)."
708 msgstr "%s: Cadena de moneda personalitzada '%s' no conté exactament tres punts o comes (o els conté ambdós)."
774709
775710 #. TRANSLATORS: this fragment will be interpolated into
776711 #. messages in fh_lock() that identify types of files.
777 #: src/data/sys-file-reader.c:359 src/data/sys-file-writer.c:215
712 #: src/data/sys-file-reader.c:324 src/data/sys-file-writer.c:213
778713 msgid "system file"
779714 msgstr "arxiu de sistema"
780715
781 #: src/data/sys-file-reader.c:366
716 #: src/data/sys-file-reader.c:331
782717 #, c-format
783718 msgid "Error opening `%s' for reading as a system file: %s."
784719 msgstr "Error en obrir `%s' per a la lectura com arxiu de sistema: %s."
785720
786 #: src/data/sys-file-reader.c:418
721 #: src/data/sys-file-reader.c:388
787722 msgid "Misplaced type 4 record."
788723 msgstr "Registre de tipus 4 fora de lloc."
789724
790 #: src/data/sys-file-reader.c:422
725 #: src/data/sys-file-reader.c:392
791726 msgid "Duplicate type 6 (document) record."
792727 msgstr "Registre de tipus 6 (document) duplicat."
793728
794 #: src/data/sys-file-reader.c:431 src/data/sys-file-reader.c:921
795 #, c-format
796 msgid ""
797 "Unrecognized record type 7, subtype %d. Please send a copy of this file, "
798 "and the syntax which created it to %s."
799 msgstr ""
800 "Registre de tipus 7, subtipus %d no reconegut. Si us plau envieu una còpia "
801 "d'aquest arxiu, així com de la sintaxi que el va crear a %s."
802
803 #: src/data/sys-file-reader.c:440
804 #, c-format
805 msgid ""
806 "Record type 7, subtype %d found here has the same type as the record found "
807 "near offset 0x%llx. Please send a copy of this file, and the syntax which "
808 "created it to %s."
809 msgstr ""
810 "Registre de tipus 7, subtipus %d que te el mateix tipus que el registre "
811 "trobat prop de la posició 0x%llx. Si us plau envieu una còpia d'aquest "
812 "arxiu, així com de la sintaxi que el va crear a %s."
813
814 #: src/data/sys-file-reader.c:453
729 #: src/data/sys-file-reader.c:401 src/data/sys-file-reader.c:900
730 #, c-format
731 msgid "Unrecognized record type 7, subtype %d. Please send a copy of this file, and the syntax which created it to %s."
732 msgstr "Registre de tipus 7, subtipus %d no reconegut. Si us plau envieu una còpia d'aquest arxiu, així com de la sintaxi que el va crear a %s."
733
734 #: src/data/sys-file-reader.c:410
735 #, c-format
736 msgid "Record type 7, subtype %d found here has the same type as the record found near offset 0x%llx. Please send a copy of this file, and the syntax which created it to %s."
737 msgstr "Registre de tipus 7, subtipus %d que te el mateix tipus que el registre trobat prop de la posició 0x%llx. Si us plau envieu una còpia d'aquest arxiu, així com de la sintaxi que el va crear a %s."
738
739 #: src/data/sys-file-reader.c:423
815740 #, c-format
816741 msgid "Unrecognized record type %d."
817742 msgstr "Tipus de registre %d no reconegut."
818743
819 #: src/data/sys-file-reader.c:500
744 #: src/data/sys-file-reader.c:467
820745 #, c-format
821746 msgid "Weighting variable must be numeric (not string variable `%s')."
822 msgstr ""
823 "Variable de ponderació ha de ser numèrica (no la variable de text `%s')."
824
825 #: src/data/sys-file-reader.c:535
747 msgstr "Variable de ponderació ha de ser numèrica (no la variable de text `%s')."
748
749 #: src/data/sys-file-reader.c:502
826750 #, c-format
827751 msgid "File header claims %d variable positions but %zu were read from file."
828 msgstr ""
829 "Capçalera de l'arxiu requereix %d posicions de variable, però s'han llegit "
830 "%zu des de l'arxiu."
831
832 #: src/data/sys-file-reader.c:581
752 msgstr "Capçalera de l'arxiu requereix %d posicions de variable, però s'han llegit %zu des de l'arxiu."
753
754 #: src/data/sys-file-reader.c:542
833755 #, c-format
834756 msgid "Error closing system file `%s': %s."
835757 msgstr "Error en tancar l'arxiu de sistema `%s': %s."
836758
837 #: src/data/sys-file-reader.c:634 src/data/sys-file-reader.c:644
759 #: src/data/sys-file-reader.c:604 src/data/sys-file-reader.c:614
838760 msgid "This is not an SPSS system file."
839761 msgstr "Això no és un arxiu de sistema de SPSS."
840762
841 #: src/data/sys-file-reader.c:667
842 msgid ""
843 "Compression bias is not the usual value of 100, or system file uses "
844 "unrecognized floating-point format."
845 msgstr ""
846 "El biaix de compressió no és el valor habitual de 100, o l'arxiu de sistema "
847 "utilitza un format de punt flotant no reconegut."
848
849 #: src/data/sys-file-reader.c:733
763 #: src/data/sys-file-reader.c:636
764 msgid "Compression bias is not the usual value of 100, or system file uses unrecognized floating-point format."
765 msgstr "El biaix de compressió no és el valor habitual de 100, o l'arxiu de sistema utilitza un format de punt flotant no reconegut."
766
767 #: src/data/sys-file-reader.c:712
850768 msgid "Variable label indicator field is not 0 or 1."
851769 msgstr "Camp indicador d'etiqueta de variable no és 0 o 1."
852770
853 #: src/data/sys-file-reader.c:743
771 #: src/data/sys-file-reader.c:722
854772 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
855 msgstr ""
856 "Camp d'indicador de valors perduts numèrics no és -3, -2, 0, 1, 2 o 3."
857
858 #: src/data/sys-file-reader.c:750
773 msgstr "Camp d'indicador de valors perduts numèrics no és -3, -2, 0, 1, 2 o 3."
774
775 #: src/data/sys-file-reader.c:729
859776 msgid "String missing value indicator field is not 0, 1, 2, or 3."
860777 msgstr "Camp d'indicador de valors perduts de cadena no és 0, 1, 2 o 3."
861778
862 #: src/data/sys-file-reader.c:770
779 #: src/data/sys-file-reader.c:749
863780 #, c-format
864781 msgid "Invalid number of labels %zu."
865782 msgstr "Nombre invàlid d'etiquetes %zu."
866783
867 #: src/data/sys-file-reader.c:795
868 msgid ""
869 "Variable index record (type 4) does not immediately follow value label "
870 "record (type 3) as it should."
871 msgstr ""
872 "Registre d'índex de variable (tipus 4) no és seguit immediatament pel "
873 "registre d'etiquetes de valors (tipus 3) com hauria."
784 #: src/data/sys-file-reader.c:774
785 msgid "Variable index record (type 4) does not immediately follow value label record (type 3) as it should."
786 msgstr "Registre d'índex de variable (tipus 4) no és seguit immediatament pel registre d'etiquetes de valors (tipus 3) com hauria."
787
788 #: src/data/sys-file-reader.c:782
789 #, c-format
790 msgid "Number of variables associated with a value label (%zu) is not between 1 and the number of variables (%zu)."
791 msgstr "Nombre de variables associades amb una etiqueta de valors (%zu) no està entre 1 i el nombre de variables (%zu)."
874792
875793 #: src/data/sys-file-reader.c:803
876794 #, c-format
877 msgid ""
878 "Number of variables associated with a value label (%zu) is not between 1 and "
879 "the number of variables (%zu)."
880 msgstr ""
881 "Nombre de variables associades amb una etiqueta de valors (%zu) no està "
882 "entre 1 i el nombre de variables (%zu)."
883
884 #: src/data/sys-file-reader.c:824
885 #, c-format
886795 msgid "Number of document lines (%d) must be greater than 0 and less than %d."
887 msgstr ""
888 "Nombre de línies de document (%d) ha de ser més gran que 0 i més petit que "
889 "%d."
890
891 #: src/data/sys-file-reader.c:897
796 msgstr "Nombre de línies de document (%d) ha de ser més gran que 0 i més petit que %d."
797
798 #: src/data/sys-file-reader.c:876
892799 #, c-format
893800 msgid "Record type 7, subtype %d has bad size %zu (expected %d)."
894801 msgstr "Registre de tipus 7, subtipus %d te mida incorrecta %zu (s'espera %d)."
895802
896 #: src/data/sys-file-reader.c:901
803 #: src/data/sys-file-reader.c:880
897804 #, c-format
898805 msgid "Record type 7, subtype %d has bad count %zu (expected %d)."
899 msgstr ""
900 "Registre de tipus 7, subtipus %d te recompte incorrecte %zu (s'espera %d)."
901
902 #: src/data/sys-file-reader.c:993
806 msgstr "Registre de tipus 7, subtipus %d te recompte incorrecte %zu (s'espera %d)."
807
808 #: src/data/sys-file-reader.c:959
903809 #, c-format
904810 msgid "Invalid variable name `%s'."
905811 msgstr "Nom de variable '%s' no vàlid."
906812
907 #: src/data/sys-file-reader.c:1001
813 #: src/data/sys-file-reader.c:967
908814 #, c-format
909815 msgid "Duplicate variable name `%s'."
910816 msgstr "Nom de la variable `%s' duplicat."
911817
912 #: src/data/sys-file-reader.c:1072
818 #: src/data/sys-file-reader.c:1038
913819 msgid "Missing string continuation record."
914820 msgstr "Manca de registre de continuació de cadena."
915821
916 #: src/data/sys-file-reader.c:1114
917 #, fuzzy, c-format
822 #: src/data/sys-file-reader.c:1080
823 #, c-format
918824 msgid "Variable %s with width %d has invalid print format 0x%x."
919 msgstr ""
920 "La variable en cadena %s amb longitud %d té una especificació de format "
921 "invàlida %s."
922
923 #: src/data/sys-file-reader.c:1118
924 #, fuzzy, c-format
825 msgstr "La variable %s amb longitud %d té una especificació de format invàlida 0x%x."
826
827 #: src/data/sys-file-reader.c:1084
828 #, c-format
925829 msgid "Variable %s with width %d has invalid write format 0x%x."
926 msgstr ""
927 "La variable en cadena %s amb longitud %d té una especificació de format "
928 "invàlida %s."
929
930 #: src/data/sys-file-reader.c:1123
830 msgstr "La variable %s amb longitud %d té una especificació de format invàlida 0x%x."
831
832 #: src/data/sys-file-reader.c:1089
931833 msgid "Suppressing further invalid format warnings."
932834 msgstr "Es desactiven les alertes posteriors de format no vàlid."
933835
934 #: src/data/sys-file-reader.c:1175
935 #, c-format
936 msgid ""
937 "Floating-point representation indicated by system file (%d) differs from "
938 "expected (%d)."
939 msgstr ""
940 "Representació del punt flotant indicat per l'arxiu de sistema (%d) difereix "
941 "de l'esperat (%d)."
942
943 #: src/data/sys-file-reader.c:1189
944 #, c-format
945 msgid ""
946 "Integer format indicated by system file (%d) differs from expected (%d)."
947 msgstr ""
948 "Format enter indicat per l'arxiu de sistema (%d) difereix de l'esperat (%d)."
949
950 #: src/data/sys-file-reader.c:1253 src/data/sys-file-reader.c:1257
951 #: src/data/sys-file-reader.c:1261
836 #: src/data/sys-file-reader.c:1141
837 #, c-format
838 msgid "Floating-point representation indicated by system file (%d) differs from expected (%d)."
839 msgstr "Representació del punt flotant indicat per l'arxiu de sistema (%d) difereix de l'esperat (%d)."
840
841 #: src/data/sys-file-reader.c:1155
842 #, c-format
843 msgid "Integer format indicated by system file (%d) differs from expected (%d)."
844 msgstr "Format enter indicat per l'arxiu de sistema (%d) difereix de l'esperat (%d)."
845
846 #: src/data/sys-file-reader.c:1214 src/data/sys-file-reader.c:1218
847 #: src/data/sys-file-reader.c:1222
952848 #, c-format
953849 msgid "File specifies unexpected value %g as %s."
954850 msgstr "L'arxiu especifica un valor inesperat %g com a %s."
955851
956 #: src/data/sys-file-reader.c:1294
852 #: src/data/sys-file-reader.c:1255
957853 #, c-format
958854 msgid "`%s' does not begin with `$' at offset %zu in MRSETS record."
959855 msgstr "`%s' not comença amb `$' a la posició %zu d'un registre MRSETS."
960856
961 #: src/data/sys-file-reader.c:1305 src/data/sys-file-reader.c:1324
857 #: src/data/sys-file-reader.c:1266 src/data/sys-file-reader.c:1285
962858 #, c-format
963859 msgid "Missing space following `%c' at offset %zu in MRSETS record."
964860 msgstr "Espai perdut darrera `%c' a la posició %zu al registre MRSETS."
965861
966 #: src/data/sys-file-reader.c:1334
967 #, c-format
968 msgid ""
969 "Unexpected label source value `%s' following `E' at offset %zu in MRSETS "
970 "record."
971 msgstr ""
972 "Valor d'etiqueta no esperat `%s' darrera `E' a la posició %zu del registre "
973 "MRSETS."
974
975 #: src/data/sys-file-reader.c:1341
862 #: src/data/sys-file-reader.c:1295
863 #, c-format
864 msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record."
865 msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició %zu del registre MRSETS."
866
867 #: src/data/sys-file-reader.c:1302
976868 #, c-format
977869 msgid "Missing `C', `D', or `E' at offset %zu in MRSETS record."
978870 msgstr "Manca `C', `D' o `E' a la posició %zu d'un registre MRSETS."
979871
980 #: src/data/sys-file-reader.c:1373
872 #: src/data/sys-file-reader.c:1334
981873 #, c-format
982874 msgid "Missing new-line parsing variable names at offset %zu in MRSETS record."
983 msgstr ""
984 "Manquen noms de variable de nova línia en la posició %zu d'un registre "
985 "MRSETS."
986
987 #: src/data/sys-file-reader.c:1389
875 msgstr "Manquen noms de variable de nova línia en la posició %zu d'un registre MRSETS."
876
877 #: src/data/sys-file-reader.c:1350
988878 #, c-format
989879 msgid "Duplicate variable name %s at offset %zu in MRSETS record."
990880 msgstr "Nom de la variable %s duplicat a la posició %zu d'un registre MRSETS."
991881
992 #: src/data/sys-file-reader.c:1405
882 #: src/data/sys-file-reader.c:1366
993883 #, c-format
994884 msgid "MRSET %s contains both string and numeric variables."
995885 msgstr "MRSET %s contè variables textuals i numeriques."
996886
997 #: src/data/sys-file-reader.c:1421
887 #: src/data/sys-file-reader.c:1382
998888 #, c-format
999889 msgid "MRSET %s has only %zu variables."
1000890 msgstr "MRSET %s nomès te %zu variables."
1001891
1002 #: src/data/sys-file-reader.c:1467
892 #: src/data/sys-file-reader.c:1428
1003893 #, c-format
1004894 msgid "Extension 11 has bad count %zu (for %zu variables)."
1005895 msgstr "Extensió 11 té un recompte invàlid %zu (per a %zu variables)."
1006896
1007 #: src/data/sys-file-reader.c:1501
1008 #, c-format
1009 msgid ""
1010 "Invalid variable display parameters for variable %zu (%s). Default "
1011 "parameters substituted."
1012 msgstr ""
1013 "Paràmetres de visualització de variable no vàlids per a la variable %zu "
1014 "(%s). Substitució pels paràmetres per defecte."
1015
1016 #: src/data/sys-file-reader.c:1598
897 #: src/data/sys-file-reader.c:1462
898 #, c-format
899 msgid "Invalid variable display parameters for variable %zu (%s). Default parameters substituted."
900 msgstr "Paràmetres de visualització de variable no vàlids per a la variable %zu (%s). Substitució pels paràmetres per defecte."
901
902 #: src/data/sys-file-reader.c:1559
1017903 #, c-format
1018904 msgid "Long variable mapping from %s to invalid variable name `%s'."
1019 msgstr ""
1020 "Identificació de variable llarga des de %s cap a un nom de variable invàlid "
1021 "'%s'."
1022
1023 #: src/data/sys-file-reader.c:1609
905 msgstr "Identificació de variable llarga des de %s cap a un nom de variable invàlid '%s'."
906
907 #: src/data/sys-file-reader.c:1570
1024908 #, c-format
1025909 msgid "Duplicate long variable name `%s'."
1026910 msgstr "Nom de la variable llarga `%s' duplicat."
1027911
1028 #: src/data/sys-file-reader.c:1642
912 #: src/data/sys-file-reader.c:1603
1029913 #, c-format
1030914 msgid "%s listed as string of invalid length %s in very long string record."
1031 msgstr ""
1032 "%s figura com a cadena de longitud no vàlida %s a un registre de cadena molt "
1033 "llarg."
1034
1035 #: src/data/sys-file-reader.c:1653
1036 #, c-format
1037 msgid ""
1038 "%s listed in very long string record with width %s, which requires only one "
1039 "segment."
1040 msgstr ""
1041 "%s figura en el registre de cadena molt llarga amb longitud %s, que "
1042 "requereix només un segment."
1043
1044 #: src/data/sys-file-reader.c:1660
915 msgstr "%s figura com a cadena de longitud no vàlida %s a un registre de cadena molt llarg."
916
917 #: src/data/sys-file-reader.c:1614
918 #, c-format
919 msgid "%s listed in very long string record with width %s, which requires only one segment."
920 msgstr "%s figura en el registre de cadena molt llarga amb longitud %s, que requereix només un segment."
921
922 #: src/data/sys-file-reader.c:1621
1045923 #, c-format
1046924 msgid "Very long string %s overflows dictionary."
1047925 msgstr "Cadena molt llarga %s desborda el diccionari."
1048926
1049 #: src/data/sys-file-reader.c:1675
1050 #, c-format
1051 msgid ""
1052 "Very long string with width %ld has segment %d of width %d (expected %d)."
1053 msgstr ""
1054 "Cadena molt llarga amb una mida de %ld conté segment %d de longitud %d "
1055 "(s'espera %d)."
1056
1057 #: src/data/sys-file-reader.c:1709
1058 #, c-format
1059 msgid ""
1060 "Variables associated with value label are not all of identical type. "
1061 "Variable %s is %s, but variable %s is %s."
1062 msgstr ""
1063 "Les variables associades amb etiqueta de valors no són totes del mateix "
1064 "tipus. La variable %s és %s, però la variable %s és %s."
1065
1066 #: src/data/sys-file-reader.c:1726
1067 #, c-format
1068 msgid ""
1069 "Value labels may not be added to long string variables (e.g. %s) using "
1070 "records types 3 and 4."
1071 msgstr ""
1072 "No es pot afegir etiquetes dels valors a les variables de cadena llarga (e."
1073 "g. %s) utilitzant els tipus de registres 3 i 4."
1074
1075 #: src/data/sys-file-reader.c:1745
927 #: src/data/sys-file-reader.c:1636
928 #, c-format
929 msgid "Very long string with width %ld has segment %d of width %d (expected %d)."
930 msgstr "Cadena molt llarga amb una mida de %ld conté segment %d de longitud %d (s'espera %d)."
931
932 #: src/data/sys-file-reader.c:1670
933 #, c-format
934 msgid "Variables associated with value label are not all of identical type. Variable %s is %s, but variable %s is %s."
935 msgstr "Les variables associades amb etiqueta de valors no són totes del mateix tipus. La variable %s és %s, però la variable %s és %s."
936
937 #: src/data/sys-file-reader.c:1687
938 #, c-format
939 msgid "Value labels may not be added to long string variables (e.g. %s) using records types 3 and 4."
940 msgstr "No es pot afegir etiquetes dels valors a les variables de cadena llarga (e.g. %s) utilitzant els tipus de registres 3 i 4."
941
942 #: src/data/sys-file-reader.c:1706
1076943 #, c-format
1077944 msgid "Duplicate value label for %g on %s."
1078945 msgstr "Etiqueta de valors duplicats per %g en %s."
1079946
1080 #: src/data/sys-file-reader.c:1749 src/data/sys-file-reader.c:1991
947 #: src/data/sys-file-reader.c:1710 src/data/sys-file-reader.c:1952
1081948 #, c-format
1082949 msgid "Duplicate value label for `%.*s' on %s."
1083950 msgstr "Etiqueta de valor duplicat per a `%.*s' a %s."
1084951
1085 #: src/data/sys-file-reader.c:1774
952 #: src/data/sys-file-reader.c:1735
1086953 #, c-format
1087954 msgid "Variable index %d not in valid range 1...%zu."
1088955 msgstr "Índex de la variable %d fora de l'interval vàlid de 1...%zu."
1089956
1090 #: src/data/sys-file-reader.c:1783
957 #: src/data/sys-file-reader.c:1744
1091958 #, c-format
1092959 msgid "Variable index %d refers to long string continuation."
1093 msgstr ""
1094 "Índex de la variable %d es refereix a una continuació de cadena llarga."
1095
1096 #: src/data/sys-file-reader.c:1819
960 msgstr "Índex de la variable %d es refereix a una continuació de cadena llarga."
961
962 #: src/data/sys-file-reader.c:1780
1097963 #, c-format
1098964 msgid "Error parsing attribute value %s[%d]."
1099965 msgstr "Error en analitzar el valor de l'atribut %s[%d]."
1100966
1101 #: src/data/sys-file-reader.c:1833
967 #: src/data/sys-file-reader.c:1794
1102968 #, c-format
1103969 msgid "Attribute value %s[%d] is not quoted: %s."
1104970 msgstr "El valor de l'atribut %s[%d] no esta entre cometes: %s."
1105971
972 #: src/data/sys-file-reader.c:1847
973 msgid "Long string value label record ends unexpectedly."
974 msgstr "Etiqueta de valor d'un registre de text molt llarg finalitza inesperadament."
975
1106976 #: src/data/sys-file-reader.c:1886
1107 msgid "Long string value label record ends unexpectedly."
1108 msgstr ""
1109 "Etiqueta de valor d'un registre de text molt llarg finalitza inesperadament."
1110
1111 #: src/data/sys-file-reader.c:1925
1112977 #, c-format
1113978 msgid "Ignoring long string value record for unknown variable %s."
1114 msgstr ""
1115 "Ignorant el registre del valor de cadena llarga per a la variable "
1116 "desconeguda %s."
1117
1118 #: src/data/sys-file-reader.c:1930
979 msgstr "Ignorant el registre del valor de cadena llarga per a la variable desconeguda %s."
980
981 #: src/data/sys-file-reader.c:1891
1119982 #, c-format
1120983 msgid "Ignoring long string value record for numeric variable %s."
1121 msgstr ""
1122 "Ignorant el registre del valor de cadena llarga per a la variable numèrica "
1123 "%s."
1124
1125 #: src/data/sys-file-reader.c:1937
1126 #, c-format
1127 msgid ""
1128 "Ignoring long string value record for variable %s because the record's width "
1129 "(%d) does not match the variable's width (%d)."
1130 msgstr ""
1131 "Ignorant el registre del valor de cadena llarga %s ja que la mida del "
1132 "registre (%d) no coincideix amb la mida de la variable (%d)."
1133
1134 #: src/data/sys-file-reader.c:1966
1135 #, c-format
1136 msgid ""
1137 "Ignoring long string value %zu for variable %s, with width %d, that has bad "
1138 "value width %zu."
1139 msgstr ""
1140 "Ignorant el valor de cadena llarga %zu per a la variable %s, d'amplada %d, "
1141 "que té una amplada de valor incorrecta %zu."
1142
1143 #: src/data/sys-file-reader.c:2070
984 msgstr "Ignorant el registre del valor de cadena llarga per a la variable numèrica %s."
985
986 #: src/data/sys-file-reader.c:1898
987 #, c-format
988 msgid "Ignoring long string value record for variable %s because the record's width (%d) does not match the variable's width (%d)."
989 msgstr "Ignorant el registre del valor de cadena llarga %s ja que la mida del registre (%d) no coincideix amb la mida de la variable (%d)."
990
991 #: src/data/sys-file-reader.c:1927
992 #, c-format
993 msgid "Ignoring long string value %zu for variable %s, with width %d, that has bad value width %zu."
994 msgstr "Ignorant el valor de cadena llarga %zu per a la variable %s, d'amplada %d, que té una amplada de valor incorrecta %zu."
995
996 #: src/data/sys-file-reader.c:2031
1144997 msgid "File ends in partial case."
1145998 msgstr "L'arxiu acaba en un cas parcial."
1146999
1147 #: src/data/sys-file-reader.c:2078
1000 #: src/data/sys-file-reader.c:2039
11481001 #, c-format
11491002 msgid "Error reading case from file %s."
11501003 msgstr "Error llegint un cas de l'arxiu %s."
11511004
1152 #: src/data/sys-file-reader.c:2180
1153 msgid ""
1154 "Possible compressed data corruption: compressed spaces appear in numeric "
1155 "field."
1156 msgstr ""
1157 "Possible corrupció de dades comprimides: apareixen espais comprimits a un "
1158 "camp numeric."
1159
1160 #: src/data/sys-file-reader.c:2234
1161 #, c-format
1162 msgid ""
1163 "Possible compressed data corruption: string contains compressed integer "
1164 "(opcode %d)."
1165 msgstr ""
1166 "Possible corrupció de dades comprimides: una cadena textual contè un enter "
1167 "comprimit (opcode %d)."
1168
1169 #: src/data/sys-file-reader.c:2328
1005 #: src/data/sys-file-reader.c:2141
1006 msgid "Possible compressed data corruption: compressed spaces appear in numeric field."
1007 msgstr "Possible corrupció de dades comprimides: apareixen espais comprimits a un camp numeric."
1008
1009 #: src/data/sys-file-reader.c:2195
1010 #, c-format
1011 msgid "Possible compressed data corruption: string contains compressed integer (opcode %d)."
1012 msgstr "Possible corrupció de dades comprimides: una cadena textual contè un enter comprimit (opcode %d)."
1013
1014 #: src/data/sys-file-reader.c:2289
11701015 #, c-format
11711016 msgid "Suppressed %d additional related warnings."
11721017 msgstr "Suprimides %d advertències addicionals."
11731018
1174 #: src/data/sys-file-reader.c:2374 src/data/sys-file-reader.c:2391
1019 #: src/data/sys-file-reader.c:2335 src/data/sys-file-reader.c:2352
11751020 #, c-format
11761021 msgid "Dictionary record refers to unknown variable %s."
11771022 msgstr "El registre diccionari es refereix a la variable desconeguda %s."
11781023
1179 #: src/data/sys-file-reader.c:2453
1024 #: src/data/sys-file-reader.c:2414
11801025 #, c-format
11811026 msgid "Expecting digit at offset %zu in MRSETS record."
11821027 msgstr "S'espera un dígit a la posició %zu d'un registre MRSETS."
11831028
1184 #: src/data/sys-file-reader.c:2461
1029 #: src/data/sys-file-reader.c:2422
11851030 #, c-format
11861031 msgid "Expecting space at offset %zu in MRSETS record."
11871032 msgstr "S'espera un espai a la posició %zu d'un registre MRSETS."
11881033
1189 #: src/data/sys-file-reader.c:2469
1034 #: src/data/sys-file-reader.c:2430
11901035 #, c-format
11911036 msgid "%zu-byte string starting at offset %zu exceeds record length %zu."
1192 msgstr ""
1193 "El text de %zu-bytes que comença en la posició %zu excedeix la mida del "
1194 "registre %zu."
1195
1196 #: src/data/sys-file-reader.c:2479
1037 msgstr "El text de %zu-bytes que comença en la posició %zu excedeix la mida del registre %zu."
1038
1039 #: src/data/sys-file-reader.c:2440
11971040 #, c-format
11981041 msgid "Expecting space at offset %zu following %zu-byte string."
11991042 msgstr "S'espera un espai en la posició %zu darrera d'un text de %zu-bytes."
12001043
1201 #: src/data/sys-file-reader.c:2520
1044 #: src/data/sys-file-reader.c:2481
12021045 #, c-format
12031046 msgid "`%s' near offset 0x%llx: "
12041047 msgstr "`%s' prop de la posició 0x%llx: "
12051048
1206 #: src/data/sys-file-reader.c:2523
1049 #: src/data/sys-file-reader.c:2484
12071050 #, c-format
12081051 msgid "`%s': "
12091052 msgstr "`%s': "
12101053
1211 #: src/data/sys-file-reader.c:2580
1054 #: src/data/sys-file-reader.c:2541
12121055 #, c-format
12131056 msgid "System error: %s."
12141057 msgstr "Error de sistema: %s."
12151058
1216 #: src/data/sys-file-reader.c:2582
1059 #: src/data/sys-file-reader.c:2543
12171060 msgid "Unexpected end of file."
12181061 msgstr "Final d'arxiu inesperat."
12191062
1220 #: src/data/sys-file-writer.c:188
1063 #: src/data/sys-file-writer.c:186
12211064 #, c-format
12221065 msgid "Unknown system file version %d. Treating as version %d."
12231066 msgstr "Versió d'arxiu de sistema %d desconeguda. Es tractarà com a versió %d."
12241067
1225 #: src/data/sys-file-writer.c:1110
1068 #: src/data/sys-file-writer.c:1086
12261069 #, c-format
12271070 msgid "An I/O error occurred writing system file `%s'."
12281071 msgstr "S'ha produït un error de E/S en desar l'arxiu de sistema `%s'."
12321075 msgid "Truncating variable label for variable `%s' to %d bytes."
12331076 msgstr "Truncant la etiqueta de variable `%s' a %d caràcters."
12341077
1235 #: src/data/variable.c:679 src/language/dictionary/sys-file-info.c:501
1078 #: src/data/variable.c:679 src/language/dictionary/sys-file-info.c:500
12361079 #: src/ui/gui/psppire-var-sheet.c:112
12371080 msgid "Nominal"
12381081 msgstr "Nominal"
12391082
1240 #: src/data/variable.c:682 src/language/dictionary/sys-file-info.c:502
1083 #: src/data/variable.c:682 src/language/dictionary/sys-file-info.c:501
12411084 #: src/ui/gui/psppire-var-sheet.c:113
12421085 msgid "Ordinal"
12431086 msgstr "Ordinal"
12441087
1245 #: src/data/variable.c:685 src/language/dictionary/sys-file-info.c:503
1088 #: src/data/variable.c:685 src/language/dictionary/sys-file-info.c:502
12461089 #: src/language/stats/ks-one-sample.c:327 src/ui/gui/psppire-var-sheet.c:114
12471090 msgid "Scale"
12481091 msgstr "Escala"
12491092
1250 #: src/data/variable.c:761 src/language/dictionary/sys-file-info.c:507
1093 #: src/data/variable.c:761 src/language/dictionary/sys-file-info.c:506
12511094 #: src/ui/gui/psppire-var-sheet.c:105
12521095 msgid "Left"
12531096 msgstr "Esquerra"
12541097
1255 #: src/data/variable.c:764 src/language/dictionary/sys-file-info.c:509
1098 #: src/data/variable.c:764 src/language/dictionary/sys-file-info.c:508
12561099 #: src/ui/gui/psppire-var-sheet.c:106
12571100 msgid "Right"
12581101 msgstr "Dreta"
12591102
1260 #: src/data/variable.c:767 src/language/dictionary/sys-file-info.c:508
1103 #: src/data/variable.c:767 src/language/dictionary/sys-file-info.c:507
12611104 #: src/ui/gui/psppire-var-sheet.c:107
12621105 msgid "Center"
12631106 msgstr "Centre"
12641107
12651108 #: src/language/command.c:196 src/language/expressions/parse.c:1293
1266 #: src/language/utilities/set.q:223
1109 #: src/language/utilities/set.q:220
12671110 #, c-format
12681111 msgid "%s is not yet implemented."
12691112 msgstr "%s encara no està implementat."
13081151 msgstr "%s només es permet dins de FILE TYPE."
13091152
13101153 #: src/language/command.c:388 src/language/command.c:392
1311 #, fuzzy, c-format
1312 msgid ""
1313 "%s is allowed only before the active dataset has been defined or inside %s."
1314 msgstr ""
1315 "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins de "
1316 "FILE TYPE."
1154 #, c-format
1155 msgid "%s is allowed only before the active dataset has been defined or inside %s."
1156 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins de %s."
13171157
13181158 #: src/language/command.c:396 src/language/command.c:400
1319 #, fuzzy, c-format
1320 msgid ""
1321 "%s is allowed only after the active dataset has been defined or inside %s."
1322 msgstr ""
1323 "%s només es permet després que l'arxiu de dades actiu s'ha definit, o dins "
1324 "de FILE TYPE."
1159 #, c-format
1160 msgid "%s is allowed only after the active dataset has been defined or inside %s."
1161 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, o dins de %s."
13251162
13261163 #: src/language/command.c:404
13271164 #, c-format
13301167
13311168 #: src/language/command.c:409
13321169 #, c-format
1333 msgid ""
1334 "%s is allowed only after the active dataset has been defined, inside INPUT "
1335 "PROGRAM, or inside FILE TYPE."
1336 msgstr ""
1337 "%s només es permet després que l'arxiu de dades actiu s'ha definit, dins de "
1338 "INPUT PROGRAM, o FILE TYPE."
1170 msgid "%s is allowed only after the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
1171 msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, dins de INPUT PROGRAM, o FILE TYPE."
13391172
13401173 #: src/language/command.c:414
13411174 #, c-format
1342 msgid ""
1343 "%s is allowed only before the active dataset has been defined, inside INPUT "
1344 "PROGRAM, or inside FILE TYPE."
1345 msgstr ""
1346 "%s només es permet abans que l'arxiu de dades actiu s'ha definit, dins de "
1347 "INPUT PROGRAM, o FILE TYPE."
1175 msgid "%s is allowed only before the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
1176 msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit, dins de INPUT PROGRAM, o FILE TYPE."
13481177
13491178 #: src/language/command.c:432 src/language/command.c:435
13501179 #, c-format
13721201 msgstr "esperant %s o %s"
13731202
13741203 #: src/language/lexer/lexer.c:303
1375 #, fuzzy, c-format
1204 #, c-format
13761205 msgid "expecting %s, %s, or %s"
1377 msgstr "esperant %s o %s"
1206 msgstr "esperant %s, %s o %s"
13781207
13791208 #: src/language/lexer/lexer.c:308
1380 #, fuzzy, c-format
1209 #, c-format
13811210 msgid "expecting %s, %s, %s, or %s"
1382 msgstr "s'espera %s, %s o %s darrera %s"
1211 msgstr "s'espera %s, %s, %s o %s"
13831212
13841213 #: src/language/lexer/lexer.c:313
1385 #, fuzzy, c-format
1214 #, c-format
13861215 msgid "expecting %s, %s, %s, %s, or %s"
1387 msgstr "s'espera %s, %s o %s darrera %s"
1216 msgstr "s'espera %s, %s, %s, %s o %s"
13881217
13891218 #: src/language/lexer/lexer.c:318
1390 #, fuzzy, c-format
1219 #, c-format
13911220 msgid "expecting %s, %s, %s, %s, %s, or %s"
1392 msgstr "s'espera %s, %s o %s darrera %s"
1221 msgstr "s'espera %s, %s, %s, %s, %s o %s"
13931222
13941223 #: src/language/lexer/lexer.c:324
1395 #, fuzzy, c-format
1224 #, c-format
13961225 msgid "expecting %s, %s, %s, %s, %s, %s, or %s"
1397 msgstr "s'espera %s, %s o %s darrera %s"
1226 msgstr "s'espera %s, %s, %s, %s, %s, %s o %s"
13981227
13991228 #: src/language/lexer/lexer.c:330
1400 #, fuzzy, c-format
1229 #, c-format
14011230 msgid "expecting %s, %s, %s, %s, %s, %s, %s, or %s"
1402 msgstr "s'espera %s, %s o %s darrera %s"
1231 msgstr "s'espera %s, %s, %s, %s, %s, %s, %s o %s"
14031232
14041233 #: src/language/lexer/lexer.c:350
14051234 #, c-format
14071236 msgstr "Subcomando %s només es pot especificar un cop."
14081237
14091238 #: src/language/lexer/lexer.c:362
1410 #, fuzzy, c-format
1239 #, c-format
14111240 msgid "Required subcommand %s was not specified."
1412 msgstr "Subcomando %s només es pot especificar un cop."
1241 msgstr "El subcomando %s requerit no s'ha especificat."
14131242
14141243 #: src/language/lexer/lexer.c:370
1415 #, fuzzy, c-format
1244 #, c-format
14161245 msgid "%s may only be specified once within subcommand %s"
1417 msgstr "Subcomando %s només es pot especificar un cop."
1246 msgstr "%s només es pot especificar un cop dins del subcomando %s"
14181247
14191248 #: src/language/lexer/lexer.c:379
1420 #, fuzzy, c-format
1249 #, c-format
14211250 msgid "Required %s specification missing from %s subcommand"
1422 msgstr "Manca la especificació %s requerida pel subcomando %s."
1251 msgstr "Manca la especificació %s requerida pel subcomando %s"
14231252
14241253 #: src/language/lexer/lexer.c:398
14251254 msgid "Syntax error at end of input"
14261255 msgstr "Error de sintaxi al final de l'entrada"
14271256
14281257 #: src/language/lexer/lexer.c:419 src/language/xforms/select-if.c:60
1429 #: src/language/stats/autorecode.c:206 src/language/stats/npar.c:504
1258 #: src/language/stats/autorecode.c:206 src/language/stats/npar.c:478
14301259 #: src/language/data-io/print-space.c:72
14311260 msgid "expecting end of command"
14321261 msgstr "s'espera el final de l'ordre"
14631292 #: src/language/lexer/lexer.c:1476
14641293 #, c-format
14651294 msgid "String of hex digits has %d characters, which is not a multiple of 2"
1466 msgstr ""
1467 "La cadena de dígits hexadecimals té %d caràcters, que no és un múltiple de 2."
1295 msgstr "La cadena de dígits hexadecimals té %d caràcters, que no és un múltiple de 2."
14681296
14691297 #: src/language/lexer/lexer.c:1483
14701298 #, c-format
14731301
14741302 #: src/language/lexer/lexer.c:1488
14751303 #, c-format
1476 msgid ""
1477 "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 "
1478 "bytes"
1479 msgstr ""
1480 "Cadena Unicode conté %d bytes, que está fora del rang vàlid entre 1 y 8 bytes"
1304 msgid "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 bytes"
1305 msgstr "Cadena Unicode conté %d bytes, que está fora del rang vàlid entre 1 y 8 bytes"
14811306
14821307 #: src/language/lexer/lexer.c:1494
14831308 #, c-format
15201345 #: src/language/lexer/subcommand-list.c:118
15211346 #, c-format
15221347 msgid "No more than %d %s subcommands allowed."
1523 msgstr ""
1348 msgstr "No es permet més de %d subcomandos %s."
15241349
15251350 #: src/language/lexer/format-parser.c:77
15261351 msgid "expecting valid format specifier"
15391364
15401365 #: src/language/lexer/value-parser.c:65
15411366 #, c-format
1542 msgid ""
1543 "Low end of range (%g) is below high end (%g). The range will be treated as "
1544 "reversed."
1545 msgstr ""
1546 "El límit inferior de l'interval (%g) està per sota del límit superior (%g). "
1547 "L' interval serà invertit."
1367 msgid "Low end of range (%g) is below high end (%g). The range will be treated as reversed."
1368 msgstr "El límit inferior de l'interval (%g) està per sota del límit superior (%g). L' interval serà invertit."
15481369
15491370 #: src/language/lexer/value-parser.c:73
15501371 #, c-format
15741395
15751396 #: src/language/lexer/variable-parser.c:180
15761397 #, c-format
1577 msgid ""
1578 "%s is not a numeric variable. It will not be included in the variable list."
1579 msgstr ""
1580 "%s no és una variable numèrica. No serà inclosa a la llista de variables."
1398 msgid "%s is not a numeric variable. It will not be included in the variable list."
1399 msgstr "%s no és una variable numèrica. No serà inclosa a la llista de variables."
15811400
15821401 #: src/language/lexer/variable-parser.c:183
15831402 #, c-format
1584 msgid ""
1585 "%s is not a string variable. It will not be included in the variable list."
1586 msgstr ""
1587 "%s no és una variable de cadena. No serà inclosa a la llista de variables."
1403 msgid "%s is not a string variable. It will not be included in the variable list."
1404 msgstr "%s no és una variable de cadena. No serà inclosa a la llista de variables."
15881405
15891406 #: src/language/lexer/variable-parser.c:187
15901407 #, c-format
15931410
15941411 #: src/language/lexer/variable-parser.c:191
15951412 #, c-format
1596 msgid ""
1597 "%s and %s are not the same type. All variables in this variable list must "
1598 "be of the same type. %s will be omitted from the list."
1599 msgstr ""
1600 "%s i %s no són del mateix tipus. Totes les variables d'aquesta llista han de "
1601 "ser del mateix tipus. %s serà omesa de la llista."
1413 msgid "%s and %s are not the same type. All variables in this variable list must be of the same type. %s will be omitted from the list."
1414 msgstr "%s i %s no són del mateix tipus. Totes les variables d'aquesta llista han de ser del mateix tipus. %s serà omesa de la llista."
16021415
16031416 #: src/language/lexer/variable-parser.c:197
16041417 #, c-format
1605 msgid ""
1606 "%s and %s are string variables with different widths. All variables in this "
1607 "variable list must have the same width. %s will be omitted from the list."
1608 msgstr ""
1609 "%s i %s són variables de cadena amb tamanys diferents. Totes les variables "
1610 "d'aquesta llista han de tenir la mateixa amplada. %s serà omesa de la llista."
1418 msgid "%s and %s are string variables with different widths. All variables in this variable list must have the same width. %s will be omitted from the list."
1419 msgstr "%s i %s són variables de cadena amb tamanys diferents. Totes les variables d'aquesta llista han de tenir la mateixa amplada. %s serà omesa de la llista."
16111420
16121421 #: src/language/lexer/variable-parser.c:202
16131422 #: src/language/lexer/variable-parser.c:404
16181427 #: src/language/lexer/variable-parser.c:315
16191428 #, c-format
16201429 msgid "%s TO %s is not valid syntax since %s precedes %s in the dictionary."
1621 msgstr ""
1622 "%s TO %s no és una sintaxi vàlida atès que %s precedeix %s en el diccionari."
1430 msgstr "%s TO %s no és una sintaxi vàlida atès que %s precedeix %s en el diccionari."
16231431
16241432 #: src/language/lexer/variable-parser.c:323
16251433 #, c-format
1626 msgid ""
1627 "When using the TO keyword to specify several variables, both variables must "
1628 "be from the same variable dictionaries, of either ordinary, scratch, or "
1629 "system variables. %s is a %s variable, whereas %s is %s."
1630 msgstr ""
1631 "Quan s'utilitza la paraula clau TO per especificar diverses variables, "
1632 "ambdues han de ser del mateix diccionari de variables, ja siguin ordinals, "
1633 "scratch, o variables de sistema. %s és una variable %s, atès que %s és %s."
1434 msgid "When using the TO keyword to specify several variables, both variables must be from the same variable dictionaries, of either ordinary, scratch, or system variables. %s is a %s variable, whereas %s is %s."
1435 msgstr "Quan s'utilitza la paraula clau TO per especificar diverses variables, ambdues han de ser del mateix diccionari de variables, ja siguin ordinals, scratch, o variables de sistema. %s és una variable %s, atès que %s és %s."
16341436
16351437 #: src/language/lexer/variable-parser.c:381
16361438 #, c-format
16561458
16571459 #: src/language/xforms/compute.c:149 src/language/xforms/compute.c:204
16581460 #, c-format
1659 msgid ""
1660 "When executing COMPUTE: SYSMIS is not a valid value as an index into vector "
1661 "%s."
1662 msgstr ""
1663 "Quan s'executa COMPUTE: SYSMIS no és un valor vàlid com a índex en el vector "
1664 "%s."
1461 msgid "When executing COMPUTE: SYSMIS is not a valid value as an index into vector %s."
1462 msgstr "Quan s'executa COMPUTE: SYSMIS no és un valor vàlid com a índex en el vector %s."
16651463
16661464 #: src/language/xforms/compute.c:153 src/language/xforms/compute.c:211
16671465 #, c-format
1668 msgid ""
1669 "When executing COMPUTE: %g is not a valid value as an index into vector %s."
1670 msgstr ""
1671 "Quan s'executa COMPUTE: %g no és un valor vàlid com a índex en el vector %s."
1466 msgid "When executing COMPUTE: %g is not a valid value as an index into vector %s."
1467 msgstr "Quan s'executa COMPUTE: %g no és un valor vàlid com a índex en el vector %s."
16721468
16731469 #: src/language/xforms/compute.c:355
16741470 #, c-format
16891485 msgstr "No es pot fer una mostra de %d observacions d'una població de %d."
16901486
16911487 #: src/language/xforms/recode.c:255
1692 msgid ""
1693 "Inconsistent target variable types. Target variables must be all numeric or "
1694 "all string."
1695 msgstr ""
1696 "Tipus inconsistent de variables objectiu. Les variables objectiu han de ser "
1697 "totes, o bé de cadena o bé numèriques."
1488 msgid "Inconsistent target variable types. Target variables must be all numeric or all string."
1489 msgstr "Tipus inconsistent de variables objectiu. Les variables objectiu han de ser totes, o bé de cadena o bé numèriques."
16981490
16991491 #: src/language/xforms/recode.c:276
17001492 msgid "CONVERT requires string input values and numeric output values."
1701 msgstr ""
1702 "CONVERT requereix valors d'entrada de cadena i valors de sortida numèrics. "
1493 msgstr "CONVERT requereix valors d'entrada de cadena i valors de sortida numèrics. "
17031494
17041495 #: src/language/xforms/recode.c:333
17051496 msgid "THRU is not allowed with string variables."
17111502
17121503 #: src/language/xforms/recode.c:473
17131504 #, c-format
1714 msgid ""
1715 "%zu variable(s) cannot be recoded into %zu variable(s). Specify the same "
1716 "number of variables as source and target variables."
1717 msgstr ""
1718 "%zu variable(s) no poden ser recodificades a %zu variable(s). Especifiqueu "
1719 "el mateix nombre de variables com a origen i destinació."
1505 msgid "%zu variable(s) cannot be recoded into %zu variable(s). Specify the same number of variables as source and target variables."
1506 msgstr "%zu variable(s) no poden ser recodificades a %zu variable(s). Especifiqueu el mateix nombre de variables com a origen i destinació."
17201507
17211508 #: src/language/xforms/recode.c:488
17221509 #, c-format
1723 msgid ""
1724 "There is no variable named %s. (All string variables specified on INTO must "
1725 "already exist. Use the STRING command to create a string variable.)"
1726 msgstr ""
1727 "No existeix cap variable anomenada %s. (Totes les variables de cadena "
1728 "especificades a INTO ja han d'existir. Utilitzeu el comandament STRING per "
1729 "crear una variable de cadena.)"
1510 msgid "There is no variable named %s. (All string variables specified on INTO must already exist. Use the STRING command to create a string variable.)"
1511 msgstr "No existeix cap variable anomenada %s. (Totes les variables de cadena especificades a INTO ja han d'existir. Utilitzeu el comandament STRING per crear una variable de cadena.)"
17301512
17311513 #: src/language/xforms/recode.c:504
17321514 #, c-format
17581540 #: src/language/control/control-stack.c:59
17591541 #, c-format
17601542 msgid "This command must appear inside %s...%s, without intermediate %s...%s."
1761 msgstr ""
1762 "Aquesta ordre ha d'aparèixer dins de %s...%s, sense intermediaris %s...%s."
1543 msgstr "Aquesta ordre ha d'aparèixer dins de %s...%s, sense intermediaris %s...%s."
17631544
17641545 #: src/language/control/control-stack.c:76
17651546 #, c-format
17771558 #: src/language/control/repeat.c:116
17781559 #, c-format
17791560 msgid "Dummy variable name `%s' hides dictionary variable `%s'."
1780 msgstr ""
1781 "El nom de la variable fictícia `%s' oculta la variable de diccionari `%s'."
1561 msgstr "El nom de la variable fictícia `%s' oculta la variable de diccionari `%s'."
17821562
17831563 #: src/language/control/repeat.c:120
17841564 #, c-format
17871567
17881568 #: src/language/control/repeat.c:163
17891569 #, c-format
1790 msgid ""
1791 "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were "
1792 "specified."
1793 msgstr ""
1794 "La variable fictícia `%.s' té %zu substitucions, així que `%s' també "
1795 "n'hauria de tenir-les, però es van especificar %zu."
1570 msgid "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were specified."
1571 msgstr "La variable fictícia `%.s' té %zu substitucions, així que `%s' també n'hauria de tenir-les, però es van especificar %zu."
17961572
17971573 #: src/language/control/repeat.c:377
17981574 msgid "Ranges may only have integer bounds."
18081584 msgstr "DO REPEAT no coincideix."
18091585
18101586 #: src/language/control/temporary.c:45
1811 msgid ""
1812 "This command may only appear once between procedures and procedure-like "
1813 "commands."
1814 msgstr ""
1815 "Aquesta ordre només pot aparèixer una vegada entre les ordres de "
1816 "procediments i quasi-procediments."
1587 msgid "This command may only appear once between procedures and procedure-like commands."
1588 msgstr "Aquesta ordre només pot aparèixer una vegada entre les ordres de procediments i quasi-procediments."
18171589
18181590 #: src/language/dictionary/attributes.c:104
18191591 msgid "Attribute array index must be between 1 and 65535."
18221594 #: src/language/dictionary/apply-dictionary.c:74
18231595 #, c-format
18241596 msgid "Variable %s is %s in target file, but %s in source file."
1825 msgstr ""
1826 "La variable %s és %s en l'arxiu de destinació, però %s en l'arxiu d'origen."
1597 msgstr "La variable %s és %s en l'arxiu de destinació, però %s en l'arxiu d'origen."
18271598
18281599 #: src/language/dictionary/apply-dictionary.c:110
18291600 msgid "No matching variables found between the source and target files."
1830 msgstr ""
1831 "No s'han trobat coincidències de variables entre els arxius d'origen i de "
1832 "destinació."
1601 msgstr "No s'han trobat coincidències de variables entre els arxius d'origen i de destinació."
18331602
18341603 #: src/language/dictionary/delete-variables.c:40
1835 msgid ""
1836 "DELETE VARIABLES may not be used after TEMPORARY. Temporary transformations "
1837 "will be made permanent."
1838 msgstr ""
1839 "DELETE VARIABLES no pot ser utilitzat després de TEMPORARY. Les "
1840 "transformacions temporals seran permanents."
1604 msgid "DELETE VARIABLES may not be used after TEMPORARY. Temporary transformations will be made permanent."
1605 msgstr "DELETE VARIABLES no pot ser utilitzat després de TEMPORARY. Les transformacions temporals seran permanents."
18411606
18421607 #: src/language/dictionary/delete-variables.c:47
1843 msgid ""
1844 "DELETE VARIABLES may not be used to delete all variables from the active "
1845 "dataset dictionary. Use NEW FILE instead."
1846 msgstr ""
1847 "DELETE VARIABLES no pot ser utilitzar per esborrar totes les variables de "
1848 "l'arxiu de dades de diccionari actiu. Utilitzeu NEW FILE en el seu lloc."
1608 msgid "DELETE VARIABLES may not be used to delete all variables from the active dataset dictionary. Use NEW FILE instead."
1609 msgstr "DELETE VARIABLES no pot ser utilitzar per esborrar totes les variables de l'arxiu de dades de diccionari actiu. Utilitzeu NEW FILE en el seu lloc."
18491610
18501611 #: src/language/dictionary/missing-values.c:70
18511612 #, c-format
1852 msgid ""
1853 "Cannot mix numeric variables (e.g. %s) and string variables (e.g. %s) within "
1854 "a single list."
1855 msgstr ""
1856 "No es poden barrejar les variables numèriques (e.g. %s) i les variables de "
1857 "cadena (e.g. %s) dins d'una llista única."
1613 msgid "Cannot mix numeric variables (e.g. %s) and string variables (e.g. %s) within a single list."
1614 msgstr "No es poden barrejar les variables numèriques (e.g. %s) i les variables de cadena (e.g. %s) dins d'una llista única."
18581615
18591616 #: src/language/dictionary/missing-values.c:119
18601617 #, c-format
18641621 #: src/language/dictionary/missing-values.c:142
18651622 #, c-format
18661623 msgid "Missing values provided are too long to assign to variable of width %d."
1867 msgstr ""
1868 "Els valors perduts donats són massa llargs per assignar a la variable "
1869 "d'amplada %d."
1624 msgstr "Els valors perduts donats són massa llargs per assignar a la variable d'amplada %d."
18701625
18711626 #: src/language/dictionary/modify-variables.c:91
1872 msgid ""
1873 "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will "
1874 "be made permanent."
1875 msgstr ""
1876 "MODIFY VARS no pot ser utilitzar després de TEMPORARY. Les transformacions "
1877 "temporals seran permanents."
1627 msgid "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will be made permanent."
1628 msgstr "MODIFY VARS no pot ser utilitzar després de TEMPORARY. Les transformacions temporals seran permanents."
18781629
18791630 #: src/language/dictionary/modify-variables.c:136
18801631 msgid "Cannot specify ALL after specifying a set of variables."
1881 msgstr ""
1882 "No es pot especificar ALL després de l'especificació d'un conjunt de "
1883 "variables."
1632 msgstr "No es pot especificar ALL després de l'especificació d'un conjunt de variables."
18841633
18851634 #: src/language/dictionary/modify-variables.c:206
18861635 #: src/language/dictionary/rename-variables.c:71
18871636 #, c-format
1888 msgid ""
1889 "Differing number of variables in old name list (%zu) and in new name list "
1890 "(%zu)."
1891 msgstr ""
1892 "Diferent nombre de variables en la llista de noms antiga (%zu) i en la "
1893 "llista de noms nova (%zu)."
1637 msgid "Differing number of variables in old name list (%zu) and in new name list (%zu)."
1638 msgstr "Diferent nombre de variables en la llista de noms antiga (%zu) i en la llista de noms nova (%zu)."
18941639
18951640 #: src/language/dictionary/modify-variables.c:231
1896 msgid ""
1897 "KEEP subcommand may be given at most once. It may not be given in "
1898 "conjunction with the DROP subcommand."
1899 msgstr ""
1900 "El subcomando KEEP pot ser emès més d'una vegada. Pot ser que no sigui "
1901 "facilitada en relació amb el subcomando DROP."
1641 msgid "KEEP subcommand may be given at most once. It may not be given in conjunction with the DROP subcommand."
1642 msgstr "El subcomando KEEP pot ser emès més d'una vegada. Pot ser que no sigui facilitada en relació amb el subcomando DROP."
19021643
19031644 #: src/language/dictionary/modify-variables.c:274
1904 msgid ""
1905 "DROP subcommand may be given at most once. It may not be given in "
1906 "conjunction with the KEEP subcommand."
1907 msgstr ""
1908 "El subcomando DROP pot ser utilitzat només una vegada. No pot ser utilitzat "
1909 "conjuntament amb el subcomando KEEP."
1645 msgid "DROP subcommand may be given at most once. It may not be given in conjunction with the KEEP subcommand."
1646 msgstr "El subcomando DROP pot ser utilitzat només una vegada. No pot ser utilitzat conjuntament amb el subcomando KEEP."
19101647
19111648 #: src/language/dictionary/modify-variables.c:300
19121649 #, c-format
19191656
19201657 #: src/language/dictionary/mrsets.c:116
19211658 #, c-format
1922 msgid ""
1923 "VARIABLES specified only variable %s on %s, but at least two variables are "
1924 "required."
1925 msgstr ""
1926 "VARIABLES especifica només la variable %s a %s, però es requereixen al menys "
1927 "dues variables."
1659 msgid "VARIABLES specified only variable %s on %s, but at least two variables are required."
1660 msgstr "VARIABLES especifica només la variable %s a %s, però es requereixen al menys dues variables."
19281661
19291662 #: src/language/dictionary/mrsets.c:149
19301663 msgid "Numeric VALUE must be an integer."
19321665
19331666 #: src/language/dictionary/mrsets.c:229 src/language/dictionary/mrsets.c:267
19341667 #, c-format
1935 msgid ""
1936 "MDGROUP subcommand for group %s specifies a string VALUE, but the variables "
1937 "specified for this group are numeric."
1938 msgstr ""
1939 "El subcomando MDGROUPS pel grup %s especifica un VALUE textual, però les "
1940 "variables especificades per aquest grup son numèriques."
1668 msgid "MDGROUP subcommand for group %s specifies a string VALUE, but the variables specified for this group are numeric."
1669 msgstr "El subcomando MDGROUPS pel grup %s especifica un VALUE textual, però les variables especificades per aquest grup son numèriques."
19411670
19421671 #: src/language/dictionary/mrsets.c:253
19431672 #, c-format
1944 msgid ""
1945 "VALUE string on MDGROUP subcommand for group %s is %d bytes long, but it "
1946 "must be no longer than the narrowest variable in the group, which is %s with "
1947 "a width of %d bytes."
1948 msgstr ""
1949 "El VALUE textual al subcomando MDGROUP pel grup %s té %d bytes, però no pot "
1950 "ser més llarg que la variable més curta al grup, que és %s amb llargada %d "
1951 "bytes."
1673 msgid "VALUE string on MDGROUP subcommand for group %s is %d bytes long, but it must be no longer than the narrowest variable in the group, which is %s with a width of %d bytes."
1674 msgstr "El VALUE textual al subcomando MDGROUP pel grup %s té %d bytes, però no pot ser més llarg que la variable més curta al grup, que és %s amb llargada %d bytes."
19521675
19531676 #: src/language/dictionary/mrsets.c:279
19541677 #, c-format
1955 msgid ""
1956 "MDGROUP subcommand for group %s specifies LABELSOURCE=VARLABEL but not "
1957 "CATEGORYLABELS=COUNTEDVALUES. Ignoring LABELSOURCE."
1958 msgstr ""
1959 "El subcomando MDGROUP pel grup %s espeficifica LABELSOURCE=VARLABEL però no "
1960 "CATEGORYLABELS=COUNTEDVALUES. S'ignorarà LABELSOURCE."
1678 msgid "MDGROUP subcommand for group %s specifies LABELSOURCE=VARLABEL but not CATEGORYLABELS=COUNTEDVALUES. Ignoring LABELSOURCE."
1679 msgstr "El subcomando MDGROUP pel grup %s espeficifica LABELSOURCE=VARLABEL però no CATEGORYLABELS=COUNTEDVALUES. S'ignorarà LABELSOURCE."
19611680
19621681 #: src/language/dictionary/mrsets.c:285
19631682 #, c-format
1964 msgid ""
1965 "MDGROUP subcommand for group %s specifies both LABEL and LABELSOURCE, but "
1966 "only one of these subcommands may be used at a time. Ignoring LABELSOURCE."
1967 msgstr ""
1968 "El subcomando MDGROUP pel grup %s espeficifica LABEL i LABELSOURCE, però "
1969 "només un d'aquests subcomandos pot ser utilitzat alhora. S'ignorarà "
1970 "LABELSOURCE."
1683 msgid "MDGROUP subcommand for group %s specifies both LABEL and LABELSOURCE, but only one of these subcommands may be used at a time. Ignoring LABELSOURCE."
1684 msgstr "El subcomando MDGROUP pel grup %s espeficifica LABEL i LABELSOURCE, però només un d'aquests subcomandos pot ser utilitzat alhora. S'ignorarà LABELSOURCE."
19711685
19721686 #: src/language/dictionary/mrsets.c:325
19731687 #, c-format
1974 msgid ""
1975 "Variables %s and %s specified as part of multiple dichotomy group %s have "
1976 "the same variable label. Categories represented by these variables will not "
1977 "be distinguishable in output."
1978 msgstr ""
1979 "Les variables %s i %s especificades com a part del grup dicotòmic múltiple "
1980 "%s tenen la mateixa etiqueta de variable. Les categories representades per "
1981 "aquestes variables no seran distingibles als resultats."
1688 msgid "Variables %s and %s specified as part of multiple dichotomy group %s have the same variable label. Categories represented by these variables will not be distinguishable in output."
1689 msgstr "Les variables %s i %s especificades com a part del grup dicotòmic múltiple %s tenen la mateixa etiqueta de variable. Les categories representades per aquestes variables no seran distingibles als resultats."
19821690
19831691 #: src/language/dictionary/mrsets.c:355
19841692 #, c-format
1985 msgid ""
1986 "Variable %s specified as part of multiple dichotomy group %s (which has "
1987 "CATEGORYLABELS=COUNTEDVALUES) has no value label for its counted value. "
1988 "This category will not be distinguishable in output."
1989 msgstr ""
1990 "La variable %s especificada com a part del grup dicotòmic múltiple %s (que "
1991 "té CATEGORYLABELS=COUNTEDVALUES) no en té etiqueta de valor pel seu valor de "
1992 "recompte. Aquesta categoria no serà distingible als resultats."
1693 msgid "Variable %s specified as part of multiple dichotomy group %s (which has CATEGORYLABELS=COUNTEDVALUES) has no value label for its counted value. This category will not be distinguishable in output."
1694 msgstr "La variable %s especificada com a part del grup dicotòmic múltiple %s (que té CATEGORYLABELS=COUNTEDVALUES) no en té etiqueta de valor pel seu valor de recompte. Aquesta categoria no serà distingible als resultats."
19931695
19941696 #: src/language/dictionary/mrsets.c:368
19951697 #, c-format
1996 msgid ""
1997 "Variables %s and %s specified as part of multiple dichotomy group %s (which "
1998 "has CATEGORYLABELS=COUNTEDVALUES) have the same value label for the the "
1999 "group's counted value. These categories will not be distinguishable in "
2000 "output."
2001 msgstr ""
2002 "Les variables %s i %s especificades com a part del grup dicotòmic múltiple "
2003 "%s (que té CATEGORYLABELS=COUNTEDVALUES) té la mateixa etiqueta de valor pel "
2004 "valor de recompte del grup. Aquestes categories no seran distingible als "
2005 "resultats."
1698 msgid "Variables %s and %s specified as part of multiple dichotomy group %s (which has CATEGORYLABELS=COUNTEDVALUES) have the same value label for the the group's counted value. These categories will not be distinguishable in output."
1699 msgstr "Les variables %s i %s especificades com a part del grup dicotòmic múltiple %s (que té CATEGORYLABELS=COUNTEDVALUES) té la mateixa etiqueta de valor pel valor de recompte del grup. Aquestes categories no seran distingible als resultats."
20061700
20071701 #: src/language/dictionary/mrsets.c:425
20081702 #, c-format
2009 msgid ""
2010 "Variables specified on MCGROUP should have the same categories, but %s and "
2011 "%s (and possibly others) in multiple category group %s have different value "
2012 "labels for value %s."
2013 msgstr ""
2014 "Variables especificades a MDGROUP han de tenir les mateixes categories, però "
2015 "%s i %s (i posiblement d'altres) al grup de caterories múltiple %s té "
2016 "diferents etiquetes de valors pel valor %s."
1703 msgid "Variables specified on MCGROUP should have the same categories, but %s and %s (and possibly others) in multiple category group %s have different value labels for value %s."
1704 msgstr "Variables especificades a MDGROUP han de tenir les mateixes categories, però %s i %s (i posiblement d'altres) al grup de caterories múltiple %s té diferents etiquetes de valors pel valor %s."
20171705
20181706 #: src/language/dictionary/mrsets.c:483
20191707 #, c-format
20211709 msgstr "Cap conjunt multiresposta anomenat %s."
20221710
20231711 #: src/language/dictionary/mrsets.c:537
2024 msgid ""
2025 "The active dataset dictionary does not contain any multiple response sets."
2026 msgstr ""
2027 "El diccionari de l'arxiu de dades actiu no conté cap conjunt de multi-"
2028 "resposta. "
1712 msgid "The active dataset dictionary does not contain any multiple response sets."
1713 msgstr "El diccionari de l'arxiu de dades actiu no conté cap conjunt de multi-resposta. "
20291714
20301715 #: src/language/dictionary/mrsets.c:547
20311716 msgid "Multiple Response Sets"
20541739
20551740 #: src/language/dictionary/mrsets.c:567
20561741 #: src/language/dictionary/split-file.c:84
2057 #: src/language/dictionary/sys-file-info.c:336
2058 #: src/language/dictionary/sys-file-info.c:575
1742 #: src/language/dictionary/sys-file-info.c:335
1743 #: src/language/dictionary/sys-file-info.c:574
20591744 #: src/ui/gui/psppire-var-sheet.c:535 src/ui/gui/psppire-var-store.c:772
20601745 #: src/ui/gui/compute.ui:467
20611746 msgid "Label"
21051790 msgstr "Tipus de format %s no pot ser utilitzat amb una variable de cadena. "
21061791
21071792 #: src/language/dictionary/rename-variables.c:48
2108 msgid ""
2109 "RENAME VARS may not be used after TEMPORARY. Temporary transformations will "
2110 "be made permanent."
2111 msgstr ""
2112 "RENAME VARS no pot ser utilitzat després de TEMPORARY. Les transformacions "
2113 "temporals seran permanents."
1793 msgid "RENAME VARS may not be used after TEMPORARY. Temporary transformations will be made permanent."
1794 msgstr "RENAME VARS no pot ser utilitzat després de TEMPORARY. Les transformacions temporals seran permanents."
21141795
21151796 #: src/language/dictionary/rename-variables.c:89
21161797 #, c-format
21181799 msgstr "Canviar el nom duplicaria el nom de la variable %s."
21191800
21201801 #: src/language/dictionary/split-file.c:83
2121 #: src/language/dictionary/sys-file-info.c:421
2122 #: src/language/dictionary/sys-file-info.c:574
2123 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:759
2124 #: src/language/stats/reliability.c:770 src/language/stats/crosstabs.q:1233
1802 #: src/language/dictionary/sys-file-info.c:420
1803 #: src/language/dictionary/sys-file-info.c:573
1804 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:753
1805 #: src/language/stats/reliability.c:764 src/language/stats/crosstabs.q:1233
21251806 #: src/language/stats/crosstabs.q:1260 src/language/stats/crosstabs.q:1283
21261807 #: src/language/stats/crosstabs.q:1308 src/language/stats/examine.q:1840
21271808 #: src/language/stats/frequencies.q:821 src/ui/gui/count.ui:244
22341915 msgstr "Conjunt de caràcters:"
22351916
22361917 #: src/language/dictionary/sys-file-info.c:149
2237 #: src/language/dictionary/sys-file-info.c:336
1918 #: src/language/dictionary/sys-file-info.c:335
22381919 msgid "Description"
22391920 msgstr "Descripció"
22401921
22411922 #: src/language/dictionary/sys-file-info.c:150
2242 #: src/language/dictionary/sys-file-info.c:338
2243 #: src/language/dictionary/sys-file-info.c:645
1923 #: src/language/dictionary/sys-file-info.c:337
1924 #: src/language/dictionary/sys-file-info.c:644
22441925 msgid "Position"
22451926 msgstr "Posició"
22461927
2247 #: src/language/dictionary/sys-file-info.c:198
1928 #: src/language/dictionary/sys-file-info.c:197
22481929 msgid "The active dataset does not have a file label."
22491930 msgstr "L'arxiu de dades actiu no té etiqueta d'arxiu."
22501931
2251 #: src/language/dictionary/sys-file-info.c:200
1932 #: src/language/dictionary/sys-file-info.c:199
22521933 #, c-format
22531934 msgid "File label: %s"
22541935 msgstr "Etiqueta d'arxiu: %s"
22551936
2256 #: src/language/dictionary/sys-file-info.c:274
1937 #: src/language/dictionary/sys-file-info.c:273
22571938 msgid "No variables to display."
22581939 msgstr "Cap variable per mostrar."
22591940
2260 #: src/language/dictionary/sys-file-info.c:288
1941 #: src/language/dictionary/sys-file-info.c:287
22611942 msgid "Macros not supported."
22621943 msgstr "Macros no disponibles."
22631944
2264 #: src/language/dictionary/sys-file-info.c:297
1945 #: src/language/dictionary/sys-file-info.c:296
22651946 msgid "The active dataset dictionary does not contain any documents."
22661947 msgstr "El diccionari de l'arxiu de dades actiu no conté cap document. "
22671948
2268 #: src/language/dictionary/sys-file-info.c:304
1949 #: src/language/dictionary/sys-file-info.c:303
22691950 msgid "Documents in the active dataset:"
22701951 msgstr "Documents a l'arxiu de dades actiu:"
22711952
2272 #: src/language/dictionary/sys-file-info.c:420
1953 #: src/language/dictionary/sys-file-info.c:419
22731954 msgid "Attribute"
22741955 msgstr "Atribut"
22751956
2276 #: src/language/dictionary/sys-file-info.c:476
1957 #: src/language/dictionary/sys-file-info.c:475
22771958 #, c-format
22781959 msgid "Format: %s"
22791960 msgstr "Format: %s"
22801961
2281 #: src/language/dictionary/sys-file-info.c:483
1962 #: src/language/dictionary/sys-file-info.c:482
22821963 #, c-format
22831964 msgid "Print Format: %s"
22841965 msgstr "Format d'Impressió: %s"
22851966
2286 #: src/language/dictionary/sys-file-info.c:487
1967 #: src/language/dictionary/sys-file-info.c:486
22871968 #, c-format
22881969 msgid "Write Format: %s"
22891970 msgstr "Format d'Escriptura: %s"
22901971
2291 #: src/language/dictionary/sys-file-info.c:500
1972 #: src/language/dictionary/sys-file-info.c:499
22921973 #, c-format
22931974 msgid "Measure: %s"
22941975 msgstr "Mesura: %s"
22951976
2296 #: src/language/dictionary/sys-file-info.c:506
1977 #: src/language/dictionary/sys-file-info.c:505
22971978 #, c-format
22981979 msgid "Display Alignment: %s"
22991980 msgstr "Alineació de la mostra: %s"
23001981
2301 #: src/language/dictionary/sys-file-info.c:512
1982 #: src/language/dictionary/sys-file-info.c:511
23021983 #, c-format
23031984 msgid "Display Width: %d"
23041985 msgstr "Amplada de la mostra: %d"
23051986
2306 #: src/language/dictionary/sys-file-info.c:526
1987 #: src/language/dictionary/sys-file-info.c:525
23071988 msgid "Missing Values: "
23081989 msgstr "Valors perduts:"
23091990
2310 #: src/language/dictionary/sys-file-info.c:625
1991 #: src/language/dictionary/sys-file-info.c:624
23111992 msgid "No vectors defined."
23121993 msgstr "Vectors no definits."
23131994
2314 #: src/language/dictionary/sys-file-info.c:644
1995 #: src/language/dictionary/sys-file-info.c:643
23151996 msgid "Vector"
23161997 msgstr "Vector"
23171998
2318 #: src/language/dictionary/sys-file-info.c:647
1999 #: src/language/dictionary/sys-file-info.c:646
23192000 msgid "Print Format"
23202001 msgstr "Format d'Impressió"
23212002
23362017
23372018 #: src/language/dictionary/vector.c:97
23382019 msgid "A slash must separate each vector specification in VECTOR's long form."
2339 msgstr ""
2340 "Una barra ha de separar cada especificació de vector en la forma llarga de "
2341 "VECTOR."
2020 msgstr "Una barra ha de separar cada especificació de vector en la forma llarga de VECTOR."
23422021
23432022 #: src/language/dictionary/vector.c:130
23442023 msgid "Vectors must have at least one element."
24982177 msgstr "Darrer valor no-perdut"
24992178
25002179 #: src/language/stats/aggregate.c:257
2501 msgid ""
2502 "When PRESORTED is specified, specifying sorting directions with (A) or (D) "
2503 "has no effect. Output data will be sorted the same way as the input data."
2504 msgstr ""
2505 "Quan s'especifica PRESORTED, donar directives d'ordenació amb (A) o (D) no "
2506 "té efecte. Les dades de sortida seran ordenades de la mateixa manera que les "
2507 "d'entrada."
2180 msgid "When PRESORTED is specified, specifying sorting directions with (A) or (D) has no effect. Output data will be sorted the same way as the input data."
2181 msgstr "Quan s'especifica PRESORTED, donar directives d'ordenació amb (A) o (D) no té efecte. Les dades de sortida seran ordenades de la mateixa manera que les d'entrada."
25082182
25092183 #: src/language/stats/aggregate.c:447
25102184 msgid "expecting aggregation function"
25232197 #: src/language/stats/aggregate.c:522
25242198 #, c-format
25252199 msgid "Arguments to %s must be of same type as source variables."
2526 msgstr ""
2527 "Els arguments per a %s han de ser del mateix tipus que les variables "
2528 "d'origen."
2200 msgstr "Els arguments per a %s han de ser del mateix tipus que les variables d'origen."
25292201
25302202 #: src/language/stats/aggregate.c:541
25312203 #, c-format
2532 msgid ""
2533 "Number of source variables (%zu) does not match number of target variables "
2534 "(%zu)."
2535 msgstr ""
2536 "Nombre de variables d'origen (%zu) no coincideix amb el nombre de variables "
2537 "de destinació (%zu)."
2204 msgid "Number of source variables (%zu) does not match number of target variables (%zu)."
2205 msgstr "Nombre de variables d'origen (%zu) no coincideix amb el nombre de variables de destinació (%zu)."
25382206
25392207 #: src/language/stats/aggregate.c:557
25402208 #, c-format
2541 msgid ""
2542 "The value arguments passed to the %s function are out-of-order. They will "
2543 "be treated as if they had been specified in the correct order."
2544 msgstr ""
2545 "El valor dels arguments passats a la funció %s estan fora d'ordre. Seran "
2546 "tractats com si haguessin estat especificats en l'ordre correcte."
2209 msgid "The value arguments passed to the %s function are out-of-order. They will be treated as if they had been specified in the correct order."
2210 msgstr "El valor dels arguments passats a la funció %s estan fora d'ordre. Seran tractats com si haguessin estat especificats en l'ordre correcte."
25472211
25482212 #: src/language/stats/aggregate.c:631
25492213 #, c-format
2550 msgid ""
2551 "Variable name %s is not unique within the aggregate file dictionary, which "
2552 "contains the aggregate variables and the break variables."
2553 msgstr ""
2554 "El nom de variable %s no és únic dins l'arxiu de diccionari agregat, que "
2555 "conté les variables agregades i les variables de tall."
2214 msgid "Variable name %s is not unique within the aggregate file dictionary, which contains the aggregate variables and the break variables."
2215 msgstr "El nom de variable %s no és únic dins l'arxiu de diccionari agregat, que conté les variables agregades i les variables de tall."
25562216
25572217 #: src/language/stats/autorecode.c:156
25582218 #, c-format
25592219 msgid "Source variable count (%zu) does not match target variable count (%zu)."
2560 msgstr ""
2561 "El recompte de la variable d'origen (%zu) no coincideix amb el recompte de "
2562 "la variable de destí (%zu)."
2220 msgstr "El recompte de la variable d'origen (%zu) no coincideix amb el recompte de la variable de destí (%zu)."
25632221
25642222 #: src/language/stats/autorecode.c:168
25652223 #, c-format
25862244 #: src/language/stats/binomial.c:219 src/language/stats/chisquare.c:177
25872245 #: src/language/stats/chisquare.c:236 src/language/stats/factor.c:1511
25882246 #: src/language/stats/glm.c:851 src/language/stats/kruskal-wallis.c:292
2589 #: src/language/stats/mann-whitney.c:188 src/language/stats/means.c:1040
2247 #: src/language/stats/mann-whitney.c:188 src/language/stats/means.c:1055
25902248 #: src/language/stats/oneway.c:946 src/language/stats/oneway.c:1117
2591 #: src/language/stats/reliability.c:539 src/language/stats/sign.c:95
2249 #: src/language/stats/reliability.c:533 src/language/stats/sign.c:95
25922250 #: src/language/stats/wilcoxon.c:255 src/ui/gui/crosstabs-dialog.c:60
25932251 #: src/language/stats/crosstabs.q:831 src/language/stats/crosstabs.q:1175
25942252 #: src/language/stats/crosstabs.q:1559 src/language/stats/examine.q:1104
26052263 #: src/language/stats/correlations.c:120 src/language/stats/correlations.c:228
26062264 #: src/language/stats/friedman.c:275 src/language/stats/kruskal-wallis.c:257
26072265 #: src/language/stats/ks-one-sample.c:293
2608 #: src/language/stats/jonckheere-terpstra.c:380
26092266 #: src/language/stats/mann-whitney.c:190 src/language/stats/means.c:408
2610 #: src/language/stats/means.c:1049 src/language/stats/mcnemar.c:259
2611 #: src/language/stats/median.c:417 src/language/stats/npar-summary.c:123
2612 #: src/language/stats/oneway.c:1016 src/language/stats/reliability.c:542
2267 #: src/language/stats/means.c:1064 src/language/stats/mcnemar.c:259
2268 #: src/language/stats/median.c:419 src/language/stats/npar-summary.c:123
2269 #: src/language/stats/oneway.c:1016 src/language/stats/reliability.c:536
26132270 #: src/language/stats/sign.c:74 src/language/stats/t-test-indep.c:211
26142271 #: src/language/stats/t-test-one-sample.c:158
26152272 #: src/language/stats/t-test-paired.c:179
26352292
26362293 #: src/language/stats/chisquare.c:150
26372294 #, c-format
2638 msgid ""
2639 "CHISQUARE test specified %d expected values, but %d distinct values were "
2640 "encountered in variable %s."
2641 msgstr ""
2642 "Prova CHISQUARE especifica %d valors esperats, però %d diferents valors es "
2643 "van trobar a la variable %s."
2295 msgid "CHISQUARE test specified %d expected values, but %d distinct values were encountered in variable %s."
2296 msgstr "Prova CHISQUARE especifica %d valors esperats, però %d diferents valors es van trobar a la variable %s."
26442297
26452298 #: src/language/stats/chisquare.c:161 src/language/stats/chisquare.c:200
26462299 msgid "Observed N"
26562309 msgstr "Residual"
26572310
26582311 #: src/language/stats/chisquare.c:195 src/language/stats/cochran.c:159
2659 #: src/language/stats/median.c:319 src/language/stats/sign.c:62
2312 #: src/language/stats/median.c:321 src/language/stats/sign.c:62
26602313 #: src/ui/gui/frequencies.ui:9 src/ui/gui/frequencies.ui:669
26612314 msgid "Frequencies"
26622315 msgstr "Freqüències"
26642317 #: src/language/stats/chisquare.c:249 src/language/stats/cochran.c:208
26652318 #: src/language/stats/friedman.c:272 src/language/stats/kruskal-wallis.c:310
26662319 #: src/language/stats/mann-whitney.c:251 src/language/stats/mcnemar.c:240
2667 #: src/language/stats/median.c:407 src/language/stats/sign.c:114
2320 #: src/language/stats/median.c:409 src/language/stats/sign.c:114
26682321 #: src/language/stats/wilcoxon.c:304
26692322 msgid "Test Statistics"
26702323 msgstr "Proves Estad."
26712324
26722325 #: src/language/stats/chisquare.c:263 src/language/stats/friedman.c:282
2673 #: src/language/stats/kruskal-wallis.c:313 src/language/stats/median.c:423
2326 #: src/language/stats/kruskal-wallis.c:313 src/language/stats/median.c:425
26742327 msgid "Chi-Square"
26752328 msgstr "Chi-quadrat"
26762329
26772330 #: src/language/stats/chisquare.c:264 src/language/stats/cochran.c:217
26782331 #: src/language/stats/factor.c:1873 src/language/stats/friedman.c:285
26792332 #: src/language/stats/glm.c:752 src/language/stats/kruskal-wallis.c:316
2680 #: src/language/stats/median.c:426 src/language/stats/oneway.c:923
2333 #: src/language/stats/median.c:428 src/language/stats/oneway.c:923
26812334 #: src/language/stats/oneway.c:1328 src/language/stats/t-test-indep.c:291
26822335 #: src/language/stats/t-test-one-sample.c:95
26832336 #: src/language/stats/t-test-paired.c:306 src/language/stats/crosstabs.q:1234
26872340
26882341 #: src/language/stats/chisquare.c:265 src/language/stats/cochran.c:220
26892342 #: src/language/stats/friedman.c:288 src/language/stats/kruskal-wallis.c:319
2690 #: src/language/stats/median.c:429
2343 #: src/language/stats/median.c:431
26912344 msgid "Asymp. Sig."
26922345 msgstr "Sig. Asimpt."
26932346
26942347 #: src/language/stats/cochran.c:109
26952348 msgid "More than two values encountered. Cochran Q test will not be run."
2696 msgstr ""
2697 "S'han trobat més de dos valors. El Test Q de Cochran no es pot executar."
2349 msgstr "S'han trobat més de dos valors. El Test Q de Cochran no es pot executar."
26982350
26992351 #: src/language/stats/cochran.c:172
27002352 #, c-format
28532505 msgstr "esperant nom de l'estadístic: torna a aplicar el defecte"
28542506
28552507 #: src/language/stats/descriptives.c:539
2856 msgid ""
2857 "Ran out of generic names for Z-score variables. There are only 126 generic "
2858 "names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
2859 msgstr ""
2860 "S'han esgotat els noms genèrics per les variables Z. Només hi ha 126 noms "
2861 "genèrics: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
2508 msgid "Ran out of generic names for Z-score variables. There are only 126 generic names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
2509 msgstr "S'han esgotat els noms genèrics per les variables Z. Només hi ha 126 noms genèrics: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
28622510
28632511 #: src/language/stats/descriptives.c:568
28642512 msgid "Mapping of variables to corresponding Z-scores."
29682616 msgstr "Determinant"
29692617
29702618 #: src/language/stats/factor.c:1733
2971 msgid ""
2972 "The dataset contains no complete observations. No analysis will be performed."
2973 msgstr ""
2974 "La matriu de dades conté observacions incompletes. No es pot realitzar cap "
2975 "anàlisi."
2619 msgid "The dataset contains no complete observations. No analysis will be performed."
2620 msgstr "La matriu de dades conté observacions incompletes. No es pot realitzar cap anàlisi."
29762621
29772622 #: src/language/stats/factor.c:1801
29782623 msgid "Analysis N"
29802625
29812626 #: src/language/stats/factor.c:1838
29822627 msgid "KMO and Bartlett's Test"
2983 msgstr ""
2628 msgstr "KMO i Prova de Bartlett"
29842629
29852630 #: src/language/stats/factor.c:1866
29862631 msgid "Kaiser-Meyer-Olkin Measure of Sampling Adequacy"
2987 msgstr ""
2632 msgstr "Mesura Kaiser-Meyer-Olkin d'Adequació de mostreig"
29882633
29892634 #: src/language/stats/factor.c:1870
29902635 msgid "Bartlett's Test of Sphericity"
2991 msgstr ""
2636 msgstr "Prova d'Esfericitat de Bartlett"
29922637
29932638 #: src/language/stats/factor.c:1872
2994 #, fuzzy
29952639 msgid "Approx. Chi-Square"
2996 msgstr "Chi-quadrat de Pearson"
2640 msgstr "Chi-quadrada Aprox."
29972641
29982642 #: src/language/stats/factor.c:1874 src/language/stats/glm.c:755
29992643 #: src/language/stats/oneway.c:1532 src/language/stats/t-test-indep.c:289
30022646 msgstr "Sig."
30032647
30042648 #: src/language/stats/factor.c:1912
3005 msgid ""
3006 "The FACTOR criteria result in zero factors extracted. Therefore no analysis "
3007 "will be performed."
3008 msgstr ""
3009 "El criteri FACTOR resulta en l'extracció de zero factors. No es pot "
3010 "realitzar cap anàlisi."
2649 msgid "The FACTOR criteria result in zero factors extracted. Therefore no analysis will be performed."
2650 msgstr "El criteri FACTOR resulta en l'extracció de zero factors. No es pot realitzar cap anàlisi."
30112651
30122652 #: src/language/stats/factor.c:1918
3013 msgid ""
3014 "The FACTOR criteria result in more factors than variables, which is not "
3015 "meaningful. No analysis will be performed."
3016 msgstr ""
3017 "El criteri FACTOR resulta en més factors que variables, i això no té cap "
3018 "sentit. No es realitza cap anàlisi."
2653 msgid "The FACTOR criteria result in more factors than variables, which is not meaningful. No analysis will be performed."
2654 msgstr "El criteri FACTOR resulta en més factors que variables, i això no té cap sentit. No es realitza cap anàlisi."
30192655
30202656 #: src/language/stats/factor.c:2001
30212657 msgid "Component Matrix"
30342670 msgstr "Matriu Rotada de Factors"
30352671
30362672 #: src/language/stats/flip.c:99
3037 msgid ""
3038 "FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
3039 msgstr ""
3040 "FLIP ignora TEMPORARY. Les transformacions temporals seran permanents."
2673 msgid "FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
2674 msgstr "FLIP ignora TEMPORARY. Les transformacions temporals seran permanents."
30412675
30422676 #: src/language/stats/flip.c:151
30432677 msgid "Could not create temporary file for FLIP."
31042738 msgstr "L'analisi multivariat encara no està implementat."
31052739
31062740 #: src/language/stats/glm.c:272
3107 #, fuzzy
31082741 msgid "Only types 1, 2 & 3 sums of squares are currently implemented"
3109 msgstr "Només USE ALL s'està aplicant actualment."
2742 msgstr "Només estan actualment implementades sumes quadratiques de tipus 1, 2 & 3"
31102743
31112744 #: src/language/stats/glm.c:737
31122745 msgid "Tests of Between-Subjects Effects"
31482781 msgstr "Total Corregit"
31492782
31502783 #: src/language/stats/ks-one-sample.c:282 src/ui/gui/ks-one-sample.ui:7
3151 #, fuzzy
31522784 msgid "One-Sample Kolmogorov-Smirnov Test"
3153 msgstr "Prova d'una mostra"
2785 msgstr "Prova Kolmogorov-Smirnov per a Una mostra"
31542786
31552787 #: src/language/stats/ks-one-sample.c:299
3156 #, fuzzy
31572788 msgid "Normal Parameters"
3158 msgstr "Puntuació Normal"
2789 msgstr "Paràmetres Normal"
31592790
31602791 #: src/language/stats/ks-one-sample.c:308
31612792 msgid "Uniform Parameters"
3162 msgstr ""
2793 msgstr "Paràmetres Uniforme"
31632794
31642795 #: src/language/stats/ks-one-sample.c:317
31652796 msgid "Poisson Parameters"
3166 msgstr ""
2797 msgstr "Paràmetres Poisson"
31672798
31682799 #: src/language/stats/ks-one-sample.c:320 src/ui/gui/crosstabs-dialog.c:44
31692800 #: src/language/stats/crosstabs.q:1943
31722803
31732804 #: src/language/stats/ks-one-sample.c:324
31742805 msgid "Exponential Parameters"
3175 msgstr ""
2806 msgstr "Paràmetres Exponencial"
31762807
31772808 #: src/language/stats/ks-one-sample.c:384
3178 #, fuzzy
31792809 msgid "Most Extreme Differences"
3180 msgstr "Diferències Positives"
2810 msgstr "Diferències Mes Extremes"
31812811
31822812 #: src/language/stats/ks-one-sample.c:387
31832813 msgid "Absolute"
3184 msgstr ""
2814 msgstr "Absolut"
31852815
31862816 #: src/language/stats/ks-one-sample.c:390 src/language/stats/roc.c:1076
31872817 msgid "Positive"
31932823
31942824 #: src/language/stats/ks-one-sample.c:396
31952825 msgid "Kolmogorov-Smirnov Z"
3196 msgstr ""
2826 msgstr "Z de Kolmogorov-Smirnov"
31972827
31982828 #: src/language/stats/ks-one-sample.c:399
3199 #: src/language/stats/jonckheere-terpstra.c:385
32002829 #: src/language/stats/mann-whitney.c:267 src/language/stats/runs.c:399
32012830 #: src/language/stats/wilcoxon.c:318 src/language/stats/crosstabs.q:1236
32022831 msgid "Asymp. Sig. (2-tailed)"
32032832 msgstr "Sig. Asimp. (2-cues)"
32042833
3205 #: src/language/stats/jonckheere-terpstra.c:364
3206 msgid "Jonckheere-Terpstra Test"
3207 msgstr ""
3208
3209 #: src/language/stats/jonckheere-terpstra.c:378
3210 #, fuzzy, c-format
3211 msgid "Number of levels in %s"
3212 msgstr "Nombre d'execucions"
3213
3214 #: src/language/stats/jonckheere-terpstra.c:381
3215 #, fuzzy
3216 msgid "Observed J-T Statistic"
3217 msgstr "Estatístic de Levene"
3218
3219 #: src/language/stats/jonckheere-terpstra.c:382
3220 #, fuzzy
3221 msgid "Mean J-T Statistic"
3222 msgstr "Estatístic de Levene"
3223
3224 #: src/language/stats/jonckheere-terpstra.c:383
3225 #, fuzzy
3226 msgid "Std. Deviation of J-T Statistic"
3227 msgstr "Desviació Est."
3228
3229 #: src/language/stats/jonckheere-terpstra.c:384
3230 #, fuzzy
3231 msgid "Std. J-T Statistic"
3232 msgstr "Proves Estad."
3233
32342834 #: src/language/stats/mann-whitney.c:202 src/language/stats/wilcoxon.c:240
32352835 msgid "Sum of Ranks"
32362836 msgstr "Suma de Rangs"
32582858 msgid "Point Probability"
32592859 msgstr "Punt de Probabilitat"
32602860
3261 #: src/language/stats/means.c:411 src/language/stats/median.c:420
2861 #: src/language/stats/means.c:411 src/language/stats/median.c:422
32622862 #: src/ui/gui/frequencies-dialog.c:53 src/language/stats/examine.q:1468
32632863 #: src/language/stats/frequencies.q:107
32642864 msgid "Median"
32652865 msgstr "Mediana"
32662866
32672867 #: src/language/stats/means.c:412
3268 #, fuzzy
32692868 msgid "Group Median"
3270 msgstr "Mediana"
2869 msgstr "Mediana de Grup"
32712870
32722871 #: src/language/stats/means.c:416
3273 #, fuzzy
32742872 msgid "Min"
3275 msgstr "Mediana"
2873 msgstr "Min."
32762874
32772875 #: src/language/stats/means.c:417
3278 #, fuzzy
32792876 msgid "Max"
3280 msgstr "Màxim"
2877 msgstr "Màx."
32812878
32822879 #: src/language/stats/means.c:424
3283 #, fuzzy
32842880 msgid "First"
3285 msgstr "Primer cas"
2881 msgstr "Primer"
32862882
32872883 #: src/language/stats/means.c:425
3288 #, fuzzy
32892884 msgid "Last"
3290 msgstr "Últim cas"
2885 msgstr "Últim"
32912886
32922887 #: src/language/stats/means.c:427
3293 #, fuzzy
32942888 msgid "Percent N"
3295 msgstr "Percentatge"
2889 msgstr "Percentatge N"
32962890
32972891 #: src/language/stats/means.c:428
3298 #, fuzzy
32992892 msgid "Percent Sum"
3300 msgstr "Percentatge"
2893 msgstr "Suma de Percentatge"
33012894
33022895 #: src/language/stats/means.c:430
33032896 msgid "Harmonic Mean"
3304 msgstr ""
2897 msgstr "Mitjana Harmònica"
33052898
33062899 #: src/language/stats/means.c:431
3307 #, fuzzy
33082900 msgid "Geom. Mean"
3309 msgstr "E.E. Mitj."
3310
3311 #: src/language/stats/means.c:1025 src/language/stats/reliability.c:507
2901 msgstr "Mitjana Geom."
2902
2903 #: src/language/stats/means.c:1040 src/language/stats/reliability.c:501
33122904 #: src/language/stats/examine.q:1158
33132905 msgid "Case Processing Summary"
33142906 msgstr "Resum de processament del Casos"
33152907
3316 #: src/language/stats/means.c:1036 src/language/stats/reliability.c:530
2908 #: src/language/stats/means.c:1051 src/language/stats/reliability.c:524
33172909 #: src/language/stats/crosstabs.q:828 src/language/stats/examine.q:1163
33182910 msgid "Cases"
33192911 msgstr "Casos"
33202912
3321 #: src/language/stats/means.c:1038
3322 #, fuzzy
2913 #: src/language/stats/means.c:1053
33232914 msgid "Included"
3324 msgstr "Exclós"
3325
3326 #: src/language/stats/means.c:1039 src/language/stats/reliability.c:536
2915 msgstr "Inclós"
2916
2917 #: src/language/stats/means.c:1054 src/language/stats/reliability.c:530
33272918 msgid "Excluded"
33282919 msgstr "Exclós"
33292920
3330 #: src/language/stats/means.c:1051 src/language/stats/crosstabs.q:839
2921 #: src/language/stats/means.c:1066 src/language/stats/crosstabs.q:839
33312922 #: src/language/stats/examine.q:1178 src/language/stats/frequencies.q:823
33322923 msgid "Percent"
33332924 msgstr "Percentatge"
33342925
3335 #: src/language/stats/means.c:1081 src/language/stats/means.c:1090
3336 #: src/language/stats/means.c:1099
2926 #: src/language/stats/means.c:1096 src/language/stats/means.c:1105
2927 #: src/language/stats/means.c:1114
33372928 #, c-format
33382929 msgid "%g%%"
3339 msgstr ""
3340
3341 #: src/language/stats/means.c:1131
2930 msgstr "%g%%"
2931
2932 #: src/language/stats/means.c:1147
33422933 msgid "Report"
3343 msgstr ""
2934 msgstr "Informe"
33442935
33452936 #: src/language/stats/mcnemar.c:143
33462937 msgid "The McNemar test is appropriate only for dichotomous variables"
3347 msgstr ""
2938 msgstr "La prova McNemar nomès es adequada per a variables dicotòmiques "
33482939
33492940 #: src/language/stats/mcnemar.c:265 src/language/stats/sign.c:136
33502941 #: src/language/stats/wilcoxon.c:323
33512942 msgid "Exact Sig. (1-tailed)"
33522943 msgstr "Sig. Exacta (1-cua)"
33532944
3354 #: src/language/stats/median.c:358
3355 #, fuzzy
2945 #: src/language/stats/median.c:360
33562946 msgid "> Median"
3357 msgstr "Mediana"
3358
3359 #: src/language/stats/median.c:361
3360 #, fuzzy
2947 msgstr "> Mediana"
2948
2949 #: src/language/stats/median.c:363
33612950 msgid "≤ Median"
3362 msgstr "Mediana"
3363
3364 #: src/language/stats/npar.c:537
2951 msgstr "≤ Mediana"
2952
2953 #: src/language/stats/npar.c:511
33652954 msgid "NPAR subcommand not currently implemented."
33662955 msgstr "Actualment no está implenetat el subcomandament NPAR."
33672956
3368 #: src/language/stats/npar.c:691
2957 #: src/language/stats/npar.c:665
33692958 msgid "Expecting MEAN, MEDIAN, MODE or number"
33702959 msgstr "S'espera MEAN, MEDIAN, MODE o un nombre"
33712960
3372 #: src/language/stats/npar.c:841
3373 #, c-format
3374 msgid ""
3375 "The specified value of HI (%d) is lower than the specified value of LO (%d)"
3376 msgstr ""
3377 "El valor especificatper a HI (%d) és menor que l'especificat per a LO (%d)"
3378
3379 #: src/language/stats/npar.c:891
3380 #, c-format
3381 msgid ""
3382 "%d expected values were given, but the specified range (%d-%d) requires "
3383 "exactly %d values."
3384 msgstr ""
3385 "S'han proporcionat %d valors esperats, però l'interval especificat (%d-%d) "
3386 "requereix exactament %d valors."
3387
3388 #: src/language/stats/npar.c:1104 src/language/stats/t-test-parser.c:163
3389 #, c-format
3390 msgid ""
3391 "PAIRED was specified but the number of variables preceding WITH (%zu) did "
3392 "not match the number following (%zu)."
3393 msgstr ""
3394 "S'ha especificat PAIRED però el nombre de variables abans de WITH (%zu) not "
3395 "conicideixen amb en nombre de variables seguents (%zu)."
2961 #: src/language/stats/npar.c:815
2962 #, c-format
2963 msgid "The specified value of HI (%d) is lower than the specified value of LO (%d)"
2964 msgstr "El valor especificatper a HI (%d) és menor que l'especificat per a LO (%d)"
2965
2966 #: src/language/stats/npar.c:865
2967 #, c-format
2968 msgid "%d expected values were given, but the specified range (%d-%d) requires exactly %d values."
2969 msgstr "S'han proporcionat %d valors esperats, però l'interval especificat (%d-%d) requereix exactament %d valors."
2970
2971 #: src/language/stats/npar.c:1078 src/language/stats/t-test-parser.c:163
2972 #, c-format
2973 msgid "PAIRED was specified but the number of variables preceding WITH (%zu) did not match the number following (%zu)."
2974 msgstr "S'ha especificat PAIRED però el nombre de variables abans de WITH (%zu) not conicideixen amb en nombre de variables seguents (%zu)."
33962975
33972976 #: src/language/stats/npar-summary.c:142 src/language/stats/examine.q:1995
33982977 #: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1057
34142993
34152994 #: src/language/stats/oneway.c:358
34162995 msgid "LSD"
3417 msgstr ""
2996 msgstr "LSD"
34182997
34192998 #: src/language/stats/oneway.c:359
3420 #, fuzzy
34212999 msgid "Tukey HSD"
3422 msgstr "Tukey"
3000 msgstr "HSD de Tukey"
34233001
34243002 #: src/language/stats/oneway.c:360
34253003 msgid "Bonferroni"
3426 msgstr ""
3004 msgstr "Bonferroni"
34273005
34283006 #: src/language/stats/oneway.c:361
34293007 msgid "Scheffé"
3430 msgstr ""
3008 msgstr "Scheffé"
34313009
34323010 #: src/language/stats/oneway.c:362
34333011 msgid "Games-Howell"
3434 msgstr ""
3012 msgstr "Games-Howell"
34353013
34363014 #: src/language/stats/oneway.c:363
34373015 msgid "Šidák"
3438 msgstr ""
3016 msgstr "Šidák"
34393017
34403018 #: src/language/stats/oneway.c:480
34413019 #, c-format
34423020 msgid "The post hoc analysis method %s is not supported."
3443 msgstr ""
3021 msgstr "El mètode d'anàlisi post-hoc %s no està implementat encara."
34443022
34453023 #: src/language/stats/oneway.c:781
34463024 #, c-format
3447 msgid ""
3448 "Dependent variable %s has no non-missing values. No analysis for this "
3449 "variable will be done."
3450 msgstr ""
3025 msgid "Dependent variable %s has no non-missing values. No analysis for this variable will be done."
3026 msgstr "La variable dependent %s no en te cap valor no-perdut. No es realitza cap anàlisi per aquesta variable."
34513027
34523028 #: src/language/stats/oneway.c:858
34533029 #, c-format
3454 msgid ""
3455 "In contrast list %zu, the number of coefficients (%zu) does not equal the "
3456 "number of groups (%d). This contrast list will be ignored."
3457 msgstr ""
3030 msgid "In contrast list %zu, the number of coefficients (%zu) does not equal the number of groups (%d). This contrast list will be ignored."
3031 msgstr "A la llista de contrast %zu, el nombre de coeficients (%zu) no equival al nombre de grups (%d). Aquesta llista de contrast serà ignorada."
34583032
34593033 #: src/language/stats/oneway.c:869
34603034 #, c-format
35553129 msgstr "No s'assumeix igualtat"
35563130
35573131 #: src/language/stats/oneway.c:1525
3558 #, fuzzy
35593132 msgid "Multiple Comparisons"
3560 msgstr "Conjunts Multi-Resposta"
3133 msgstr "Comparacions Múltiples"
35613134
35623135 #: src/language/stats/oneway.c:1527
35633136 #, c-format
35643137 msgid "(I) %s"
3565 msgstr ""
3138 msgstr "(I) %s"
35663139
35673140 #: src/language/stats/oneway.c:1528
35683141 #, c-format
35693142 msgid "(J) %s"
3570 msgstr ""
3143 msgstr "(J) %s"
35713144
35723145 #: src/language/stats/oneway.c:1529 src/language/stats/t-test-indep.c:293
35733146 #: src/language/stats/t-test-one-sample.c:97
35763149
35773150 #: src/language/stats/oneway.c:1530
35783151 msgid "(I - J)"
3579 msgstr ""
3152 msgstr "(I - J)"
35803153
35813154 #: src/language/stats/oneway.c:1535
3582 #, fuzzy, c-format
3155 #, c-format
35833156 msgid "%g%% Confidence Interval"
3584 msgstr "Interval de Confiança del 95%%"
3157 msgstr "Interval de Confiança del %g%%"
35853158
35863159 #: src/language/stats/quick-cluster.c:361
35873160 msgid "Number of clusters may not be larger than the number of cases."
36043177 msgid "Number of Cases in each Cluster"
36053178 msgstr "Nombre de cassos a cada Agrupament"
36063179
3607 #: src/language/stats/quick-cluster.c:476 src/language/stats/reliability.c:533
3180 #: src/language/stats/quick-cluster.c:476 src/language/stats/reliability.c:527
36083181 #: src/language/stats/crosstabs.q:829 src/language/stats/examine.q:1102
36093182 #: src/language/stats/frequencies.q:1042
36103183 msgid "Valid"
36123185
36133186 #: src/language/stats/rank.c:207
36143187 msgid "Cannot create new rank variable. All candidates in use."
3615 msgstr ""
3616 "No es pot crear la nova variable de rangs. Tots els candidats estan en ús."
3188 msgstr "No es pot crear la nova variable de rangs. Tots els candidats estan en ús."
36173189
36183190 #: src/language/stats/rank.c:326
36193191 #, c-format
36623234 msgid "Reliability on a single variable is not useful."
36633235 msgstr "L'anàlisi de fiabilitat d'una única variable és inútil."
36643236
3665 #: src/language/stats/reliability.c:268
3666 #, fuzzy
3667 msgid "The split point must be less than the number of variables"
3668 msgstr "El nombre d'agrupament no pot ser més gran que el nombre de cassos."
3669
3670 #: src/language/stats/reliability.c:481
3671 #, fuzzy, c-format
3672 msgid "Scale: %s"
3673 msgstr "Escala:"
3674
3675 #: src/language/stats/reliability.c:544
3237 #: src/language/stats/reliability.c:538
36763238 msgid "%"
36773239 msgstr "%"
36783240
3679 #: src/language/stats/reliability.c:589
3241 #: src/language/stats/reliability.c:583
36803242 msgid "Item-Total Statistics"
36813243 msgstr "Estadístiques de total d'Items"
36823244
3683 #: src/language/stats/reliability.c:611
3245 #: src/language/stats/reliability.c:605
36843246 msgid "Scale Mean if Item Deleted"
36853247 msgstr "Escalar la mitjana si s'esborra l'element"
36863248
3687 #: src/language/stats/reliability.c:614
3249 #: src/language/stats/reliability.c:608
36883250 msgid "Scale Variance if Item Deleted"
36893251 msgstr "Escalar la variança si s'esborra l'element"
36903252
3691 #: src/language/stats/reliability.c:617
3253 #: src/language/stats/reliability.c:611
36923254 msgid "Corrected Item-Total Correlation"
36933255 msgstr "Correlació total-item corregida"
36943256
3695 #: src/language/stats/reliability.c:620
3257 #: src/language/stats/reliability.c:614
36963258 msgid "Cronbach's Alpha if Item Deleted"
36973259 msgstr "Cronbach's Alpha si s'esborra l'element"
36983260
3699 #: src/language/stats/reliability.c:694
3261 #: src/language/stats/reliability.c:688
37003262 msgid "Reliability Statistics"
37013263 msgstr "Estadístiques de fiabilitat"
37023264
3703 #: src/language/stats/reliability.c:734 src/language/stats/reliability.c:753
3265 #: src/language/stats/reliability.c:728 src/language/stats/reliability.c:747
37043266 msgid "Cronbach's Alpha"
37053267 msgstr "Alfa de Cronbach"
37063268
3707 #: src/language/stats/reliability.c:737 src/language/stats/reliability.c:762
3708 #: src/language/stats/reliability.c:773
3269 #: src/language/stats/reliability.c:731 src/language/stats/reliability.c:756
3270 #: src/language/stats/reliability.c:767
37093271 msgid "N of Items"
37103272 msgstr "N d'elements"
37113273
3712 #: src/language/stats/reliability.c:756
3274 #: src/language/stats/reliability.c:750
37133275 msgid "Part 1"
37143276 msgstr "Part 1"
37153277
3716 #: src/language/stats/reliability.c:767
3278 #: src/language/stats/reliability.c:761
37173279 msgid "Part 2"
37183280 msgstr "Part 2"
37193281
3720 #: src/language/stats/reliability.c:778
3282 #: src/language/stats/reliability.c:772
37213283 msgid "Total N of Items"
37223284 msgstr "N total d'elements"
37233285
3724 #: src/language/stats/reliability.c:781
3286 #: src/language/stats/reliability.c:775
37253287 msgid "Correlation Between Forms"
37263288 msgstr "Correlación entre formes"
37273289
3728 #: src/language/stats/reliability.c:785
3290 #: src/language/stats/reliability.c:779
37293291 msgid "Spearman-Brown Coefficient"
37303292 msgstr "Coeficient d'Spearman-Brown"
37313293
3732 #: src/language/stats/reliability.c:788
3294 #: src/language/stats/reliability.c:782
37333295 msgid "Equal Length"
37343296 msgstr "Ample igual"
37353297
3736 #: src/language/stats/reliability.c:791
3298 #: src/language/stats/reliability.c:785
37373299 msgid "Unequal Length"
37383300 msgstr "Ample desigual"
37393301
3740 #: src/language/stats/reliability.c:795
3302 #: src/language/stats/reliability.c:789
37413303 msgid "Guttman Split-Half Coefficient"
37423304 msgstr "Coeficient Gutman de DIvisió pel mig"
37433305
38103372
38113373 #: src/language/stats/runs.c:167
38123374 #, c-format
3813 msgid ""
3814 "Multiple modes exist for varible `%s'. Using %g as the threshold value."
3815 msgstr ""
3816 "Existeixen multiples modes per la variable `%s'. S'utilitza %g com a valor "
3817 "d'umbral."
3375 msgid "Multiple modes exist for varible `%s'. Using %g as the threshold value."
3376 msgstr "Existeixen multiples modes per la variable `%s'. S'utilitza %g com a valor d'umbral."
38183377
38193378 #: src/language/stats/runs.c:322 src/ui/gui/runs.ui:7
38203379 msgid "Runs Test"
38413400 msgstr "Casos < Valor de prova"
38423401
38433402 #: src/language/stats/runs.c:387
3844 #, fuzzy
38453403 msgid "Cases ≥ Test Value"
3846 msgstr "Casos < Valor de prova"
3404 msgstr "Casos ≥ Valor de la Prova"
38473405
38483406 #: src/language/stats/runs.c:390
38493407 msgid "Total Cases"
39713529 msgstr "Error Est. Mitjana"
39723530
39733531 #: src/language/stats/t-test-paired.c:329
3974 #, fuzzy, c-format
3532 #, c-format
39753533 msgid "%s - %s"
3976 msgstr "%s - Pàgina %d"
3534 msgstr "%s - %s"
39773535
39783536 #: src/language/stats/t-test-parser.c:123
3979 msgid ""
3980 "When applying GROUPS to a string variable, two values must be specified."
3981 msgstr ""
3982 "Quan s'aplica GROUPS a una variable alfabetica, s'han d'especificar dos "
3983 "valors."
3537 msgid "When applying GROUPS to a string variable, two values must be specified."
3538 msgstr "Quan s'aplica GROUPS a una variable alfabetica, s'han d'especificar dos valors."
39843539
39853540 #: src/language/stats/t-test-parser.c:135
39863541 #: src/language/stats/t-test-parser.c:231
39893544
39903545 #: src/language/stats/t-test-parser.c:293
39913546 msgid "Exactly one of TESTVAL, GROUPS and PAIRS subcommands must be specified."
3992 msgstr ""
3993 "Exactamente un dels subcomanaments TESTVAL, GROUPS y PAIRS ha "
3994 "d'especificarse."
3547 msgstr "Exactamente un dels subcomanaments TESTVAL, GROUPS y PAIRS ha d'especificarse."
39953548
39963549 #: src/language/stats/wilcoxon.c:252
39973550 msgid "Negative Ranks"
40033556
40043557 #: src/language/stats/wilcoxon.c:361
40053558 msgid "Too many pairs to calculate exact significance."
4006 msgstr ""
3559 msgstr "Massa parelles per calcular la significativitat exacta."
40073560
40083561 #: src/language/data-io/combine-files.c:212
40093562 msgid "Cannot specify the active dataset since none has been defined."
4010 msgstr ""
4011 "No es pot especificar l'arxiu de dades actiu ja que cap no ha estat definit."
3563 msgstr "No es pot especificar l'arxiu de dades actiu ja que cap no ha estat definit."
40123564
40133565 #: src/language/data-io/combine-files.c:218
4014 msgid ""
4015 "This command may not be used after TEMPORARY when the active dataset is an "
4016 "input source. Temporary transformations will be made permanent."
4017 msgstr ""
4018 "Aquest comando no pot ser utilitzat després de TEMPORARY quan l'arxiu de "
4019 "dades actiu és una font d'entrada. Les transformacions temporals seran "
4020 "permanents."
3566 msgid "This command may not be used after TEMPORARY when the active dataset is an input source. Temporary transformations will be made permanent."
3567 msgstr "Aquest comando no pot ser utilitzat després de TEMPORARY quan l'arxiu de dades actiu és una font d'entrada. Les transformacions temporals seran permanents."
40213568
40223569 #: src/language/data-io/combine-files.c:252
40233570 msgid "Multiple IN subcommands for a single FILE or TABLE."
40403587 msgstr "BY és necessari quan s'especifica %s."
40413588
40423589 #: src/language/data-io/combine-files.c:514
4043 msgid ""
4044 "Combining files with incompatible encodings. String data may not be "
4045 "represented correctly."
4046 msgstr ""
4047 "Combinant arxius amb codificacions incompatibles. Les dades de la cadena no "
4048 "podran estar representades correctament."
3590 msgid "Combining files with incompatible encodings. String data may not be represented correctly."
3591 msgstr "Combinant arxius amb codificacions incompatibles. Les dades de la cadena no podran estar representades correctament."
40493592
40503593 #: src/language/data-io/combine-files.c:555
40513594 #, c-format
4052 msgid ""
4053 "Variable %s in file %s has different type or width from the same variable in "
4054 "earlier file."
4055 msgstr ""
4056 "La variable %s a l'arxiu %s és de tipus o amplada diferent respecte de la "
4057 "mateixa variable en l'arxiu anterior. "
3595 msgid "Variable %s in file %s has different type or width from the same variable in earlier file."
3596 msgstr "La variable %s a l'arxiu %s és de tipus o amplada diferent respecte de la mateixa variable en l'arxiu anterior. "
40583597
40593598 #: src/language/data-io/combine-files.c:561
40603599 #, c-format
40743613 #: src/language/data-io/combine-files.c:572
40753614 #, c-format
40763615 msgid "In an earlier file, %s was a string variable with width %d."
4077 msgstr ""
4078 "En un arxiu anterior, %s era una variable cadena amb una amplada de %d."
3616 msgstr "En un arxiu anterior, %s era una variable cadena amb una amplada de %d."
40793617
40803618 #: src/language/data-io/combine-files.c:612
40813619 #, c-format
4082 msgid ""
4083 "Variable name %s specified on %s subcommand duplicates an existing variable "
4084 "name."
4085 msgstr ""
4086 "Nom de la variable %s especificat al subcomando %s duplica el nom de la "
4087 "variable existent."
3620 msgid "Variable name %s specified on %s subcommand duplicates an existing variable name."
3621 msgstr "Nom de la variable %s especificat al subcomando %s duplica el nom de la variable existent."
40883622
40893623 #: src/language/data-io/combine-files.c:774
40903624 #, c-format
41053639
41063640 #: src/language/data-io/data-list.c:245
41073641 msgid "Encoding should not be specified for inline data. It will be ignored."
4108 msgstr ""
4109 "La codificació no ha de ser especificada per les dades en línia. Serà "
4110 "ignorada."
3642 msgstr "La codificació no ha de ser especificada per les dades en línia. Serà ignorada."
41113643
41123644 #: src/language/data-io/data-list.c:254
41133645 msgid "The END subcommand may be used only with DATA LIST FIXED."
41363668 #: src/language/data-io/data-list.c:390
41373669 #, c-format
41383670 msgid "Cannot place variable %s on record %d when RECORDS=%d is specified."
4139 msgstr ""
4140 "No es pot posar la variable %s en el registre %d quan RECORDS=%d està "
4141 "especificat."
3671 msgstr "No es pot posar la variable %s en el registre %d quan RECORDS=%d està especificat."
41423672
41433673 #: src/language/data-io/data-parser.c:458
41443674 #: src/language/data-io/data-parser.c:467
41623692
41633693 #: src/language/data-io/data-parser.c:644
41643694 #, c-format
4165 msgid ""
4166 "Missing value(s) for all variables from %s onward. These will be filled "
4167 "with the system-missing value or blanks, as appropriate."
4168 msgstr ""
4169 "Valor(s) perdut(s) per a totes les variables des de %st. Aquests s'omplen "
4170 "amb el valor perdut del sistema o espais en blanc, segons correspongui."
3695 msgid "Missing value(s) for all variables from %s onward. These will be filled with the system-missing value or blanks, as appropriate."
3696 msgstr "Valor(s) perdut(s) per a totes les variables des de %st. Aquests s'omplen amb el valor perdut del sistema o espais en blanc, segons correspongui."
41713697
41723698 #: src/language/data-io/data-parser.c:664
41733699 msgid "Record ends in data not part of any field."
42123738 msgstr "No s'ha pogut obrir `%s' per a la lectura com a arxiu de dades: %s."
42133739
42143740 #: src/language/data-io/data-reader.c:198
4215 msgid ""
4216 "Missing END DATA while reading inline data. This probably indicates a "
4217 "missing or incorrectly formatted END DATA command. END DATA must appear by "
4218 "itself on a single line with exactly one space between words."
4219 msgstr ""
4220 "Manca END DATA quan es llegien dades en línia. Això probablement indica una "
4221 "pérdua o format erroni del comando END DATA. END DATA ha d'aparèixer per si "
4222 "mateix en una sola línia amb exactament un espai entre les paraules."
3741 msgid "Missing END DATA while reading inline data. This probably indicates a missing or incorrectly formatted END DATA command. END DATA must appear by itself on a single line with exactly one space between words."
3742 msgstr "Manca END DATA quan es llegien dades en línia. Això probablement indica una pérdua o format erroni del comando END DATA. END DATA ha d'aparèixer per si mateix en una sola línia amb exactament un espai entre les paraules."
42233743
42243744 #: src/language/data-io/data-reader.c:219
42253745 #, c-format
42653785 msgstr "Intent de llegir més enllà de END DATA."
42663786
42673787 #: src/language/data-io/data-reader.c:706
4268 msgid ""
4269 "This command is not valid here since the current input program does not "
4270 "access the inline file."
4271 msgstr ""
4272 "Aquesta ordre no es vàlida ja que el programa d'entrada actual no té accés a "
4273 "l'arxiu en línia."
3788 msgid "This command is not valid here since the current input program does not access the inline file."
3789 msgstr "Aquesta ordre no es vàlida ja que el programa d'entrada actual no té accés a l'arxiu en línia."
42743790
42753791 #: src/language/data-io/data-writer.c:73
42763792 #, c-format
42773793 msgid "An error occurred while opening `%s' for writing as a data file: %s."
4278 msgstr ""
4279 "S'ha produït un error en obrir `%s' per a escriure'l com a arxiu de dades: "
4280 "%s."
3794 msgstr "S'ha produït un error en obrir `%s' per a escriure'l com a arxiu de dades: %s."
42813795
42823796 #: src/language/data-io/data-writer.c:190
42833797 #, c-format
43083822
43093823 #: src/language/data-io/get-data.c:293
43103824 #, c-format
4311 msgid ""
4312 "%s is allowed only with %s arrangement, but %s arrangement was stated or "
4313 "implied earlier in this command."
4314 msgstr ""
4315 "%s només es permet amb configuració %s, però prèviament en aquest comando "
4316 "s'ha establit la configuració %s."
3825 msgid "%s is allowed only with %s arrangement, but %s arrangement was stated or implied earlier in this command."
3826 msgstr "%s només es permet amb configuració %s, però prèviament en aquest comando s'ha establit la configuració %s."
43173827
43183828 #: src/language/data-io/get-data.c:362
43193829 msgid "Value of FIRSTCASE must be 1 or greater."
43323842 msgstr "Valor de PERCENT ha de ser entre 1 i 100."
43333843
43343844 #: src/language/data-io/get-data.c:483
4335 msgid ""
4336 "In compatible syntax mode, the QUALIFIER string must contain exactly one "
4337 "character."
4338 msgstr ""
4339 "En el mode de sintaxi compatible, la cadena QUALIFIER ha de contenir "
4340 "exactament un caràcter."
3845 msgid "In compatible syntax mode, the QUALIFIER string must contain exactly one character."
3846 msgstr "En el mode de sintaxi compatible, la cadena QUALIFIER ha de contenir exactament un caràcter."
43413847
43423848 #: src/language/data-io/get-data.c:518
43433849 #: src/language/data-io/placement-parser.c:377
43443850 #, c-format
4345 msgid ""
4346 "The record number specified, %ld, is at or before the previous record, %d. "
4347 "Data fields must be listed in order of increasing record number."
4348 msgstr ""
4349 "El nombre de registre especificat, %ld, és a o abans del registre anterior, "
4350 "%d. Els camps de dades han de ser llistats en ordre incremental del número "
4351 "de registre."
3851 msgid "The record number specified, %ld, is at or before the previous record, %d. Data fields must be listed in order of increasing record number."
3852 msgstr "El nombre de registre especificat, %ld, és a o abans del registre anterior, %d. Els camps de dades han de ser llistats en ordre incremental del número de registre."
43523853
43533854 #: src/language/data-io/get-data.c:527
43543855 #, c-format
4355 msgid ""
4356 "The record number specified, %ld, exceeds the number of records per case "
4357 "specified on FIXCASE, %d."
4358 msgstr ""
4359 "El nombre de registre especificat , %ld, excedeix el nombre de registres per "
4360 "cas especificats a FIXCASE, %d."
3856 msgid "The record number specified, %ld, exceeds the number of records per case specified on FIXCASE, %d."
3857 msgstr "El nombre de registre especificat , %ld, excedeix el nombre de registres per cas especificats a FIXCASE, %d."
43613858
43623859 #: src/language/data-io/inpt-pgm.c:118
43633860 msgid "Unexpected end-of-file within INPUT PROGRAM."
43683865 msgstr "El programa d'entrada no va crear cap variable."
43693866
43703867 #: src/language/data-io/inpt-pgm.c:330
4371 msgid ""
4372 "REREAD: Column numbers must be positive finite numbers. Column set to 1."
4373 msgstr ""
4374 "REREAD: Els nombres de columna han de ser nombres positius finits. La "
4375 "columna s'estableix en 1."
3868 msgid "REREAD: Column numbers must be positive finite numbers. Column set to 1."
3869 msgstr "REREAD: Els nombres de columna han de ser nombres positius finits. La columna s'estableix en 1."
43763870
43773871 #: src/language/data-io/placement-parser.c:86
43783872 #, c-format
4379 msgid ""
4380 "Number of variables specified (%zu) differs from number of variable formats "
4381 "(%zu)."
4382 msgstr ""
4383 "Nombre de variables especificades (%zu) difereix del nombre de formats de la "
4384 "variable (%zu)."
3873 msgid "Number of variables specified (%zu) differs from number of variable formats (%zu)."
3874 msgstr "Nombre de variables especificades (%zu) difereix del nombre de formats de la variable (%zu)."
43853875
43863876 #: src/language/data-io/placement-parser.c:96
4387 msgid ""
4388 "SPSS-like or Fortran-like format specification expected after variable names."
4389 msgstr ""
4390 "Després del nom de les variables s'esperen especificacions en format tipus-"
4391 "SPSS o tipus-Fortran."
3877 msgid "SPSS-like or Fortran-like format specification expected after variable names."
3878 msgstr "Després del nom de les variables s'esperen especificacions en format tipus-SPSS o tipus-Fortran."
43923879
43933880 #: src/language/data-io/placement-parser.c:118
43943881 #, c-format
43953882 msgid "The %d columns %d-%d can't be evenly divided into %zu fields."
4396 msgstr ""
4397 "Les %d columnes %d-%d no poden ser uniformement dividides entre els camps "
4398 "%zu."
3883 msgstr "Les %d columnes %d-%d no poden ser uniformement dividides entre els camps %zu."
43993884
44003885 #: src/language/data-io/placement-parser.c:302
44013886 msgid "Column positions for fields must be positive."
44253910 #: src/language/data-io/print.c:267
44263911 #, c-format
44273912 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
4428 msgstr ""
4429 "Resultats obtinguts per a %d registres, però %zu especificats al subcomando "
4430 "RECORDS."
3913 msgstr "Resultats obtinguts per a %d registres, però %zu especificats al subcomando RECORDS."
44313914
44323915 #: src/language/data-io/print.c:436
44333916 #, c-format
44563939
44573940 #: src/language/data-io/trim.c:89
44583941 #, c-format
4459 msgid ""
4460 "Cannot rename %s as %s because there already exists a variable named %s. To "
4461 "rename variables with overlapping names, use a single RENAME subcommand such "
4462 "as `/RENAME (A=B)(B=C)(C=A)', or equivalently, `/RENAME (A B C=B C A)'."
4463 msgstr ""
4464 "No es pot canviar el nom %s per %s perquè ja existeix una variable anomenada "
4465 "%s. Per canviar el nom de les variables amb noms superposats, utilitzeu un "
4466 "únic subcomando RENAME com per exemple `/RENAME (A=B)(B=C)(C=A)', o "
4467 "equivalentment, `/RENAME (A B C=B C A)'."
3942 msgid "Cannot rename %s as %s because there already exists a variable named %s. To rename variables with overlapping names, use a single RENAME subcommand such as `/RENAME (A=B)(B=C)(C=A)', or equivalently, `/RENAME (A B C=B C A)'."
3943 msgstr "No es pot canviar el nom %s per %s perquè ja existeix una variable anomenada %s. Per canviar el nom de les variables amb noms superposats, utilitzeu un únic subcomando RENAME com per exemple `/RENAME (A=B)(B=C)(C=A)', o equivalentment, `/RENAME (A B C=B C A)'."
44683944
44693945 #: src/language/data-io/trim.c:123
44703946 #, c-format
4471 msgid ""
4472 "Number of variables on left side of `=' (%zu) does not match number of "
4473 "variables on right side (%zu), in parenthesized group %d of RENAME "
4474 "subcommand."
4475 msgstr ""
4476 "El nombre de variables en el costat esquerre de `=' (%zu) no coincideix amb "
4477 "el nombre de variables al costat dret (%zu), en el grup entre parèntesi %d "
4478 "del subcomando RENAME."
3947 msgid "Number of variables on left side of `=' (%zu) does not match number of variables on right side (%zu), in parenthesized group %d of RENAME subcommand."
3948 msgstr "El nombre de variables en el costat esquerre de `=' (%zu) no coincideix amb el nombre de variables al costat dret (%zu), en el grup entre parèntesi %d del subcomando RENAME."
44793949
44803950 #: src/language/data-io/trim.c:136
44813951 #, c-format
44963966 msgstr "Nom de la variable %s duplicat."
44973967
44983968 #: src/language/expressions/helpers.c:41
4499 msgid ""
4500 "One of the arguments to a DATE function is not an integer. The result will "
4501 "be system-missing."
4502 msgstr ""
4503 "Un dels arguments per a funció DATE no és un enter. El resultat serà perdut "
4504 "del sistema."
3969 msgid "One of the arguments to a DATE function is not an integer. The result will be system-missing."
3970 msgstr "Un dels arguments per a funció DATE no és un enter. El resultat serà perdut del sistema."
45053971
45063972 #: src/language/expressions/helpers.c:69
4507 msgid ""
4508 "The week argument to DATE.WKYR is not an integer. The result will be system-"
4509 "missing."
4510 msgstr ""
4511 "L'argument de setmana per DATE.WKYR no és un enter. El resultat serà perdut "
4512 "pel sistema."
3973 msgid "The week argument to DATE.WKYR is not an integer. The result will be system-missing."
3974 msgstr "L'argument de setmana per DATE.WKYR no és un enter. El resultat serà perdut pel sistema."
45133975
45143976 #: src/language/expressions/helpers.c:75
4515 msgid ""
4516 "The week argument to DATE.WKYR is outside the acceptable range of 1 to 53. "
4517 "The result will be system-missing."
4518 msgstr ""
4519 "L'argument de setmana per DATE.WKYR és fora de l'interval acceptable entre 1 "
4520 "i 53. El resultat serà perdut pel sistema."
3977 msgid "The week argument to DATE.WKYR is outside the acceptable range of 1 to 53. The result will be system-missing."
3978 msgstr "L'argument de setmana per DATE.WKYR és fora de l'interval acceptable entre 1 i 53. El resultat serà perdut pel sistema."
45213979
45223980 #: src/language/expressions/helpers.c:97
4523 msgid ""
4524 "The day argument to DATE.YRDAY is not an integer. The result will be system-"
4525 "missing."
4526 msgstr ""
4527 "L'argument de dia per DATE.YRDAY no és un enter. El resultat serà perdut "
4528 "pel sistema."
3981 msgid "The day argument to DATE.YRDAY is not an integer. The result will be system-missing."
3982 msgstr "L'argument de dia per DATE.YRDAY no és un enter. El resultat serà perdut pel sistema."
45293983
45303984 #: src/language/expressions/helpers.c:103
4531 msgid ""
4532 "The day argument to DATE.YRDAY is outside the acceptable range of 1 to 366. "
4533 "The result will be system-missing."
4534 msgstr ""
4535 "L'argument de dia per DATE.YRDAY és fora de l'interval acceptable entre 1 i "
4536 "366. El resultat serà perdut al sistema."
3985 msgid "The day argument to DATE.YRDAY is outside the acceptable range of 1 to 366. The result will be system-missing."
3986 msgstr "L'argument de dia per DATE.YRDAY és fora de l'interval acceptable entre 1 i 366. El resultat serà perdut al sistema."
45373987
45383988 #: src/language/expressions/helpers.c:125
4539 msgid ""
4540 "The year argument to YRMODA is greater than 47516. The result will be "
4541 "system-missing."
4542 msgstr ""
4543 "L'argument d'any per YRMODA és més gran que 47516. El resultat será perdut "
4544 "al sistema."
3989 msgid "The year argument to YRMODA is greater than 47516. The result will be system-missing."
3990 msgstr "L'argument d'any per YRMODA és més gran que 47516. El resultat será perdut al sistema."
45453991
45463992 #. TRANSLATORS: Don't translate the the actual unit names `weeks', `days' etc
45473993 #. They must remain in their original English.
45483994 #: src/language/expressions/helpers.c:180
45493995 #, c-format
4550 msgid ""
4551 "Unrecognized date unit `%.*s'. Valid date units are `years', `quarters', "
4552 "`months', `weeks', `days', `hours', `minutes', and `seconds'."
4553 msgstr ""
4554 "Unitat de dates `%.*s' no reconeguda. Les unitats de dates vàlides són "
4555 "`anys', `trimestres', `mesos' , `setmanes', `dies', `hores', `minuts', i "
4556 "`segons'."
3996 msgid "Unrecognized date unit `%.*s'. Valid date units are `years', `quarters', `months', `weeks', `days', `hours', `minutes', and `seconds'."
3997 msgstr "Unitat de dates `%.*s' no reconeguda. Les unitats de dates vàlides són `anys', `trimestres', `mesos' , `setmanes', `dies', `hores', `minuts', i `segons'."
45573998
45583999 #: src/language/expressions/helpers.c:330
45594000 msgid "Invalid DATESUM method. Valid choices are `closest' and `rollover'."
4560 msgstr ""
4561 "Mètode DATESUM invàlid. Les opcions vàlides són `closest' i `rollover\"."
4001 msgstr "Mètode DATESUM invàlid. Les opcions vàlides són `closest' i `rollover\"."
45624002
45634003 #: src/language/expressions/parse.c:260
45644004 #, c-format
4565 msgid ""
4566 "Type mismatch: expression has %s type, but a numeric value is required here."
4567 msgstr ""
4568 "Incompatibilitat de tipus: l'expressió té tipus %s, però aquí es demana un "
4569 "valor numèric."
4005 msgid "Type mismatch: expression has %s type, but a numeric value is required here."
4006 msgstr "Incompatibilitat de tipus: l'expressió té tipus %s, però aquí es demana un valor numèric."
45704007
45714008 #: src/language/expressions/parse.c:272
45724009 #, c-format
4573 msgid ""
4574 "Type mismatch: expression has %s type, but a string value is required here."
4575 msgstr ""
4576 "Incompatibilitat de tipus: l'expressió té tipus %s, però aquí es demana un "
4577 "valor de cadena."
4010 msgid "Type mismatch: expression has %s type, but a string value is required here."
4011 msgstr "Incompatibilitat de tipus: l'expressió té tipus %s, però aquí es demana un valor de cadena."
45784012
45794013 #: src/language/expressions/parse.c:434
45804014 #, c-format
45814015 msgid "Type mismatch while applying %s operator: cannot convert %s to %s."
4582 msgstr ""
4583 "Incompatibilitat dels tipus mentre que s'aplica l'operador %s: no es pot "
4584 "convertir %s a %s."
4016 msgstr "Incompatibilitat dels tipus mentre que s'aplica l'operador %s: no es pot convertir %s a %s."
45854017
45864018 #: src/language/expressions/parse.c:648
4587 msgid ""
4588 "Chaining relational operators (e.g. `a < b < c') will not produce the "
4589 "mathematically expected result. Use the AND logical operator to fix the "
4590 "problem (e.g. `a < b AND b < c'). If chaining is really intended, "
4591 "parentheses will disable this warning (e.g. `(a < b) < c'.)"
4592 msgstr ""
4593 "L'encadenament d'operadors relacionals (p.e. `a < b < c') no produirà el "
4594 "resultat esperat matemàticament. Utilitzeu l'operador lògic AND per "
4595 "solucionar el problema (p.e. `a < b AND b < c'). Si l'encadenament és "
4596 "realment intencionat, l'ús de parèntesis desactivarà aquesta alerta (p.e. `"
4597 "(a < b) < c'.)"
4019 msgid "Chaining relational operators (e.g. `a < b < c') will not produce the mathematically expected result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < c'). If chaining is really intended, parentheses will disable this warning (e.g. `(a < b) < c'.)"
4020 msgstr "L'encadenament d'operadors relacionals (p.e. `a < b < c') no produirà el resultat esperat matemàticament. Utilitzeu l'operador lògic AND per solucionar el problema (p.e. `a < b AND b < c'). Si l'encadenament és realment intencionat, l'ús de parèntesis desactivarà aquesta alerta (p.e. `(a < b) < c'.)"
45984021
45994022 #: src/language/expressions/parse.c:750
4600 msgid ""
4601 "The exponentiation operator (`**') is left-associative, even though right-"
4602 "associative semantics are more useful. That is, `a**b**c' equals `(a**b)"
4603 "**c', not as `a**(b**c)'. To disable this warning, insert parentheses."
4604 msgstr ""
4605 "L'operador d'exponenciació (`**') apareix a l'esquerra, tot i que si apareix "
4606 "a la dreta és més útil. Es a dir, `a**b**c' és igual a `(a**b)**c', i no "
4607 "`a**(b**c)'. Per desactivar aquesta alerta, insereix uns parèntesis."
4023 msgid "The exponentiation operator (`**') is left-associative, even though right-associative semantics are more useful. That is, `a**b**c' equals `(a**b)**c', not as `a**(b**c)'. To disable this warning, insert parentheses."
4024 msgstr "L'operador d'exponenciació (`**') apareix a l'esquerra, tot i que si apareix a la dreta és més útil. Es a dir, `a**b**c' és igual a `(a**b)**c', i no `a**(b**c)'. Per desactivar aquesta alerta, insereix uns parèntesis."
46084025
46094026 #: src/language/expressions/parse.c:830
46104027 #, c-format
46434060
46444061 #: src/language/expressions/parse.c:1137
46454062 #, c-format
4646 msgid ""
4647 "With %s, using minimum valid argument count of %d does not make sense when "
4648 "passing only %d arguments in list."
4649 msgstr ""
4650 "Amb %s, utilitzar el mínim recompte d'argument vàlid %d no té sentit quan es "
4651 "passen només %d arguments en la llista."
4063 msgid "With %s, using minimum valid argument count of %d does not make sense when passing only %d arguments in list."
4064 msgstr "Amb %s, utilitzar el mínim recompte d'argument vàlid %d no té sentit quan es passen només %d arguments en la llista."
46524065
46534066 #: src/language/expressions/parse.c:1191
46544067 #, c-format
46994112 msgstr "escrivint a un arxiu temporal"
47004113
47014114 #: src/libpspp/inflate.c:89
4702 #, fuzzy, c-format
4115 #, c-format
47034116 msgid "Cannot initialize inflator: %s"
4704 msgstr "no pot inicialitzar el controlador de sortida `%s' de la classe `%s'"
4117 msgstr "No es pot inicialitzar el descompressor: %s"
47054118
47064119 #: src/libpspp/inflate.c:144
4707 #, fuzzy, c-format
4120 #, c-format
47084121 msgid "Error inflating: %s"
4709 msgstr "error en crear \"%s\""
4122 msgstr "Error en descomprimir: %s"
47104123
47114124 #: src/libpspp/message.c:85
47124125 msgid "error"
47234136 #: src/libpspp/message.c:280
47244137 #, c-format
47254138 msgid "Notes (%d) exceed limit (%d). Suppressing further notes."
4726 msgstr ""
4727 "Les anotacions (%d) han superat el límit (%d). Es suprimeixen les "
4728 "posteriors."
4139 msgstr "Les anotacions (%d) han superat el límit (%d). Es suprimeixen les posteriors."
47294140
47304141 #: src/libpspp/message.c:288
47314142 #, c-format
47324143 msgid "Warnings (%d) exceed limit (%d). Syntax processing will be halted."
4733 msgstr ""
4734 "Les alertes (%d) han superat el límit (%d). S'atura el processament de "
4735 "sintaxi."
4144 msgstr "Les alertes (%d) han superat el límit (%d). S'atura el processament de sintaxi."
47364145
47374146 #: src/libpspp/message.c:291
47384147 #, c-format
47394148 msgid "Errors (%d) exceed limit (%d). Syntax processing will be halted."
4740 msgstr ""
4741 "Els errors (%d) han superat el límit (%d). S'atura el processament de "
4742 "sintaxi."
4743
4744 #: src/libpspp/zip-reader.c:88
4149 msgstr "Els errors (%d) han superat el límit (%d). S'atura el processament de sintaxi."
4150
4151 #: src/libpspp/zip-reader.c:87
47454152 #, c-format
47464153 msgid "Unsupported compression type (%d)"
4747 msgstr ""
4748
4749 #: src/libpspp/zip-reader.c:201
4154 msgstr "Tipus de compressió no suportada (%d)"
4155
4156 #: src/libpspp/zip-reader.c:181
47504157 #, c-format
47514158 msgid "Corrupt file at 0x%llx: Expected %<PRIx32>; got %<PRIx32>"
4752 msgstr ""
4753
4754 #: src/libpspp/zip-reader.c:325
4159 msgstr "Arxiu corrupte a 0x%llx: S'esparaba %<PRIx32>; s'obte %<PRIx32>"
4160
4161 #: src/libpspp/zip-reader.c:312
47554162 msgid "Cannot find central directory"
4756 msgstr ""
4757
4758 #: src/libpspp/zip-reader.c:334
4759 #, fuzzy, c-format
4163 msgstr "No es pot trobar el directori central"
4164
4165 #: src/libpspp/zip-reader.c:321
4166 #, c-format
47604167 msgid "Failed to seek to end of central directory record: %s"
4761 msgstr "error en crear el directori temporal"
4762
4763 #: src/libpspp/zip-reader.c:360
4764 #, fuzzy, c-format
4168 msgstr "Falla en cercar el registre al final del directori central: %s"
4169
4170 #: src/libpspp/zip-reader.c:347
4171 #, c-format
47654172 msgid "Failed to seek to central directory: %s"
4766 msgstr "error en crear el directori temporal"
4767
4768 #: src/libpspp/zip-reader.c:412
4173 msgstr "Falla en cercar el directori central: %s"
4174
4175 #: src/libpspp/zip-reader.c:399
47694176 #, c-format
47704177 msgid "Failed to seek to start of member `%s': %s"
4771 msgstr ""
4772
4773 #: src/libpspp/zip-reader.c:443
4774 #, c-format
4775 msgid ""
4776 "Name mismatch in zip archive. Central directory says `%s'; local file header "
4777 "says `%s'"
4778 msgstr ""
4178 msgstr "Falla en cercar l'inicio del membre `%s': %s"
4179
4180 #: src/libpspp/zip-reader.c:430
4181 #, c-format
4182 msgid "Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"
4183 msgstr "Nom incorrecte en arxiu zip. El directori central diu `%s'; l'encapçalament de l'arxiu local diu `%s'"
47794184
47804185 #: src/libpspp/zip-writer.c:92
47814186 #, c-format
48144219
48154220 #: src/output/ascii.c:331
48164221 #, c-format
4817 msgid ""
4818 "ascii: page excluding margins and headers must be at least %d characters "
4819 "wide by %d lines long, but as configured is only %d characters by %d lines"
4820 msgstr ""
4821 "ascii: excloent els marges i encapçalaments la pàgina ha de tenir com a "
4822 "mínim %d caràcters d'ample per %d línies de llarg, però tal com està "
4823 "configurada, només n'hi ha %d caràcters i %d línies"
4222 msgid "ascii: page excluding margins and headers must be at least %d characters wide by %d lines long, but as configured is only %d characters by %d lines"
4223 msgstr "ascii: excloent els marges i encapçalaments la pàgina ha de tenir com a mínim %d caràcters d'ample per %d línies de llarg, però tal com està configurada, només n'hi ha %d caràcters i %d línies"
48244224
48254225 #: src/output/ascii.c:377
48264226 #, c-format
48514251 #. TRANSLATORS: Don't translate the words `terminal' or `listing'.
48524252 #: src/output/driver.c:319
48534253 #, c-format
4854 msgid ""
4855 "%s is not a valid device type (the choices are `terminal' and `listing')"
4856 msgstr ""
4857 "%s no és un tipus de dispositiu vàlid (les opcions son `terminal' i "
4858 "`listing')"
4254 msgid "%s is not a valid device type (the choices are `terminal' and `listing')"
4255 msgstr "%s no és un tipus de dispositiu vàlid (les opcions son `terminal' i `listing')"
48594256
48604257 #: src/output/driver.c:332
48614258 #, c-format
49534350 #: src/output/tab.c:245
49544351 #, c-format
49554352 msgid "bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in table size (%d,%d)\n"
4956 msgstr ""
4957 "incorrecta hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d a taula de mida (%d,%d)\n"
4353 msgstr "incorrecta hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d a taula de mida (%d,%d)\n"
49584354
49594355 #: src/output/tab.c:289
49604356 #, c-format
4961 msgid ""
4962 "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
4963 msgstr ""
4964 "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) en taula amb mida (%d,%d)\n"
4357 msgid "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
4358 msgstr "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) en taula amb mida (%d,%d)\n"
49654359
49664360 #: src/output/cairo.c:225
49674361 #, c-format
49754369
49764370 #: src/output/cairo.c:417
49774371 #, c-format
4978 msgid ""
4979 "The defined page is not wide enough to hold at least %d characters in the "
4980 "default font. In fact, there's only room for %d characters."
4981 msgstr ""
4982 "La pàgina definida no és prou ampla com per contenir al més d'almenys %d "
4983 "caracters en la font per defecte. De fet, només n'hi ha espai per %d "
4984 "caracters."
4372 msgid "The defined page is not wide enough to hold at least %d characters in the default font. In fact, there's only room for %d characters."
4373 msgstr "La pàgina definida no és prou ampla com per contenir al més d'almenys %d caracters en la font per defecte. De fet, només n'hi ha espai per %d caracters."
49854374
49864375 #: src/output/cairo.c:427
49874376 #, c-format
4988 msgid ""
4989 "The defined page is not long enough to hold at least %d lines in the default "
4990 "font. In fact, there's only room for %d lines."
4991 msgstr ""
4992 "La pàgina definida no és prou llarga com per contenir almenys %d línies amb "
4993 "les fonts per defecte. De fet, només n'hi ha espai per %d línies."
4377 msgid "The defined page is not long enough to hold at least %d lines in the default font. In fact, there's only room for %d lines."
4378 msgstr "La pàgina definida no és prou llarga com per contenir almenys %d línies amb les fonts per defecte. De fet, només n'hi ha espai per %d línies."
49944379
49954380 #: src/output/cairo.c:478
49964381 #, c-format
50624447 msgstr "Detectat un error mentre està actiu ERROR=STOP."
50634448
50644449 #: src/ui/terminal/main.c:153
5065 msgid ""
5066 "Stopping syntax file processing here to avoid a cascade of dependent command "
5067 "failures."
5068 msgstr ""
5069 "Aturant el processament de l'arxiu de sintaxi aquí per evitar una cascada "
5070 "d'errors derivats."
4450 msgid "Stopping syntax file processing here to avoid a cascade of dependent command failures."
4451 msgstr "Aturant el processament de l'arxiu de sintaxi aquí per evitar una cascada d'errors derivats."
50714452
50724453 #: src/ui/terminal/terminal-opts.c:122
50734454 #, c-format
51204501 "PSPP, un programa per l'anàlisi estadistic de dades mostrals.\n"
51214502 "Ús: %s [OPTION]... FILE...\n"
51224503 "\n"
5123 "Els arguments per a opcions llargues també s'apliquen a les opcions curtes "
5124 "equivalents.\n"
4504 "Els arguments per a opcions llargues també s'apliquen a les opcions curtes equivalents.\n"
51254505 "\n"
51264506 "Opcions de Sortida:\n"
5127 " -o, --output=FILE sortida cap a FILE, amb format per defecte "
5128 "segons el nom de FILE\n"
4507 " -o, --output=FILE sortida cap a FILE, amb format per defecte segons el nom de FILE\n"
51294508 " -O format=FORMAT sobreescritura del format previ de -o\n"
5130 " -O OPTION=VALUE estableix opcions de sortida personalitzades per "
5131 "a -o\n"
4509 " -O OPTION=VALUE estableix opcions de sortida personalitzades per a -o\n"
51324510 " -O device={terminal|listing} canvia el tipus de dispositivo per a -o\n"
51334511 " -e, --error-file=FILE afegeix errors, alertes i notes a FILE\n"
51344512 " --no-output desactiva el dispositiu de sortida per defecte\n"
51394517 " -I-, --no-include netejar la ruta de cerca\n"
51404518 " -r, --no-statrc desactiva arxiu rc executant-se a l'inici\n"
51414519 " -a, --algorithm={compatible|enhanced}\n"
5142 " marcar com `compatible' si es prefereix la "
5143 "sortida\n"
4520 " marcar com `compatible' si es prefereix la sortida\n"
51444521 " calculada a partir d'algoritmes trencats\n"
51454522 " -x, --syntax={compatible|enhanced}\n"
5146 " marcar com `compatible' per desactivar les "
5147 "extensions de PSPP\n"
4523 " marcar com `compatible' per desactivar les extensions de PSPP\n"
51484524 " -b, --batch interpretar la sintaxi en mode paquet\n"
51494525 " -i, --interactive interpretar la sintaxi en mode interactiu\n"
51504526 " -s, --safer no permet algunes operacions poc segures\n"
51544530 " -h, --help mostra aquesta ajuda i surt\n"
51554531 " -V, --version mostra informació sobre la versió i surt\n"
51564532 "\n"
5157 "Els arguments sense opcions son interpretats com a arxius de sintaxis per "
5158 "executar.\n"
4533 "Els arguments sense opcions son interpretats com a arxius de sintaxis per executar.\n"
51594534
51604535 #: src/ui/terminal/terminal.c:62
51614536 #, c-format
51774552 msgstr "Arxiu destinació de l'agregació"
51784553
51794554 #: src/ui/gui/aggregate-dialog.c:174 src/ui/gui/psppire-data-window.c:504
5180 #: src/ui/gui/psppire-window.c:733
4555 #: src/ui/gui/psppire-window.c:754
51814556 msgid "System Files (*.sav)"
51824557 msgstr "Arxius de Sistema (*.sav)"
51834558
51844559 #: src/ui/gui/aggregate-dialog.c:179 src/ui/gui/psppire-data-window.c:509
5185 #: src/ui/gui/psppire-window.c:738
4560 #: src/ui/gui/psppire-window.c:759
51864561 msgid "Portable Files (*.por) "
51874562 msgstr "Arxius Portables (*.por)"
51884563
52824657 msgstr "Expressió regular incorrecta: %s"
52834658
52844659 #: src/ui/gui/factor-dialog.c:348
5285 #, fuzzy, c-format
4660 #, c-format
52864661 msgid "_Eigenvalues over %4.2f times the mean eigenvalue"
5287 msgstr "Valors-propis per sobre de %4.2f vegades el valor-propi mitjà"
4662 msgstr "_Valors-propis per sobre de %4.2f vegades el valor-propi mitjà"
52884663
52894664 #: src/ui/gui/frequencies-dialog.c:45
52904665 msgid "Standard error of the mean"
53144689
53154690 #: src/ui/gui/help-menu.c:106
53164691 #, c-format
5317 msgid ""
5318 "Cannot open reference manual: %s. The PSPP user manual is also available at "
5319 "%s"
5320 msgstr ""
5321 "No es pot obrir el manual de referència: %s. El manual d'usuari de PSPP es "
5322 "tambè disponible a %s"
4692 msgid "Cannot open reference manual: %s. The PSPP user manual is also available at %s"
4693 msgstr "No es pot obrir el manual de referència: %s. El manual d'usuari de PSPP es tambè disponible a %s"
53234694
53244695 #: src/ui/gui/help-menu.c:133
53254696 msgid "_Help"
53304701 msgstr "Manual de _Referencia"
53314702
53324703 #: src/ui/gui/main.c:83
5333 #, fuzzy, c-format
4704 #, c-format
53344705 msgid ""
53354706 "PSPPIRE, a GUI for PSPP, a program for statistical analysis of sample data.\n"
53364707 "Usage: %s [OPTION]... FILE\n"
53564727 " -h, --help display this help and exit\n"
53574728 " -V, --version output version information and exit\n"
53584729 "\n"
5359 "A non-option argument is interpreted as a .sav file, a .por file or a "
5360 "syntax\n"
5361 "file to load.\n"
4730 "A non-option argument is interpreted as a .sav or .por file to load.\n"
53624731 msgstr ""
5363 "PSPPIRE, un entorn gràfic (GUI) per PSPP, programa per l'anàlisi estatistic "
5364 "de dades mostrals.\n"
4732 "PSPPIRE, un entorn gràfic (GUI) per PSPP, programa per l'anàlisi estatistic de dades mostrals.\n"
53654733 "Ús: %s [OPTION]... FILE\n"
53664734 "\n"
5367 "Els arguments per a opcions llargues s'apliquen també a opcions curtes "
5368 "equivalents.\n"
4735 "Els arguments per a opcions llargues s'apliquen també a opcions curtes equivalents.\n"
53694736 "\n"
53704737 "Opcions de GUI:\n"
53714738 " -q, --no-splash no mostrar la pantalla inicial \n"
53744741 " -I, --include=DIR afegeix DIR a la ruta de cerca\n"
53754742 " -I-, --no-include netejar la ruta de cerca\n"
53764743 " -a, --algorithm={compatible|enhanced}\n"
5377 " marcar com `compatible' si es prefereix la "
5378 "sortida\n"
4744 " marcar com `compatible' si es prefereix la sortida\n"
53794745 " calculada a partir d'algoritmes trencats\n"
53804746 " -x, --syntax={compatible|enhanced}\n"
5381 " maracar com `compatible' per desactivar les "
5382 "extensions de PSPP\n"
4747 " maracar com `compatible' per desactivar les extensions de PSPP\n"
53834748 " -i, --interactive interpretar la sintaxis en mode interactiu\n"
53844749 " -s, --safer no permet algunes operacions poc segures\n"
53854750 "Ruta de cerca per defecte:%s\n"
53884753 " -h, --help mostra aquesta ajuda i surt\n"
53894754 " -V, --version mostra informació sobre la versió i surt\n"
53904755 "\n"
5391 "Els arguments sense opcions son interpretats com a arxius de sintaxis per "
5392 "executar.\n"
4756 "Els arguments sense opcions son interpretats com a arxius de sintaxis per executar.\n"
53934757
53944758 #: src/ui/gui/missing-val-dialog.c:114 src/ui/gui/missing-val-dialog.c:167
53954759 msgid "Incorrect value for variable type"
54044768 msgid "Contrast %d of %d"
54054769 msgstr "Contrast %d de %d"
54064770
5407 #: src/ui/gui/psppire.c:242
4771 #: src/ui/gui/psppire.c:227
54084772 msgid "_Reset"
54094773 msgstr "_Reiniciar"
54104774
5411 #: src/ui/gui/psppire.c:243
4775 #: src/ui/gui/psppire.c:228
54124776 msgid "_Select"
54134777 msgstr "_Selecionar"
54144778
54594823 msgstr "Desar"
54604824
54614825 #: src/ui/gui/psppire-data-window.c:514 src/ui/gui/psppire-syntax-window.c:608
5462 #: src/ui/gui/psppire-window.c:749
4826 #: src/ui/gui/psppire-window.c:770
54634827 msgid "All Files"
54644828 msgstr "Tots els arxius"
54654829
54724836 msgstr "Eliminar arxiu de dades existent?"
54734837
54744838 #: src/ui/gui/psppire-data-window.c:588
5475 #, fuzzy, c-format
5476 msgid ""
5477 "Renaming \"%s\" to \"%s\" will destroy the existing dataset named \"%s\". "
5478 "Are you sure that you want to do this?"
5479 msgstr ""
5480 "Re-anomenar \"%s\" com a \"%s\" eliminarà l'arxiu existent anomenat \"%s\". "
5481 "Esta segur que vol fer aixó?"
4839 #, c-format
4840 msgid "Renaming \"%s\" to \"%s\" will delete destroy the existing dataset named \"%s\". Are you sure that you want to do this?"
4841 msgstr "Re-anomenar \"%s\" com a \"%s\" eliminarà l'arxiu existent anomenat \"%s\". Esta segur que vol fer aixó?"
54824842
54834843 #: src/ui/gui/psppire-data-window.c:616
54844844 #, c-format
55444904 msgstr "VAR%05d"
55454905
55464906 #: src/ui/gui/psppire-dict.c:537
5547 #, fuzzy
55484907 msgid "Duplicate variable name."
5549 msgstr "Nom de la variable %s duplicat."
4908 msgstr "Nom de variable duplicat."
55504909
55514910 #: src/ui/gui/psppire-encoding-selector.c:153
55524911 msgid "Automatically Detect"
5553 msgstr ""
4912 msgstr "Detecció Automàtica"
55544913
55554914 #: src/ui/gui/psppire-encoding-selector.c:154
5556 #, fuzzy
55574915 msgid "Locale Encoding"
5558 msgstr "Tipus Little-Endian."
4916 msgstr "Codificació Local"
55594917
55604918 #: src/ui/gui/psppire-encoding-selector.c:158
55614919 msgid "Arabic"
5562 msgstr ""
4920 msgstr "Aràbic"
55634921
55644922 #: src/ui/gui/psppire-encoding-selector.c:160
55654923 msgid "Armenian"
5566 msgstr ""
4924 msgstr "Armeni"
55674925
55684926 #: src/ui/gui/psppire-encoding-selector.c:161
55694927 msgid "Baltic"
5570 msgstr ""
4928 msgstr "Baltic"
55714929
55724930 #: src/ui/gui/psppire-encoding-selector.c:163
55734931 msgid "Celtic"
5574 msgstr ""
4932 msgstr "Celtic"
55754933
55764934 #: src/ui/gui/psppire-encoding-selector.c:164
55774935 msgid "Central European"
5578 msgstr ""
4936 msgstr "Centre Europeu"
55794937
55804938 #: src/ui/gui/psppire-encoding-selector.c:166
55814939 msgid "Chinese Simplified"
5582 msgstr ""
4940 msgstr "Xinès Simplificat"
55834941
55844942 #: src/ui/gui/psppire-encoding-selector.c:168
55854943 msgid "Chinese Traditional"
5586 msgstr ""
4944 msgstr "Xinès Tradicional"
55874945
55884946 #: src/ui/gui/psppire-encoding-selector.c:170
55894947 msgid "Croatian"
5590 msgstr ""
4948 msgstr "Croata"
55914949
55924950 #: src/ui/gui/psppire-encoding-selector.c:171
55934951 msgid "Cyrillic"
5594 msgstr ""
4952 msgstr "Ciril·lic"
55954953
55964954 #: src/ui/gui/psppire-encoding-selector.c:173
55974955 msgid "Cyrillic/Russian"
5598 msgstr ""
4956 msgstr "Ciril·lic/Rus"
55994957
56004958 #: src/ui/gui/psppire-encoding-selector.c:174
56014959 msgid "Cyrillic/Ukrainian"
5602 msgstr ""
4960 msgstr "Ciril·lic/Ucranià"
56034961
56044962 #: src/ui/gui/psppire-encoding-selector.c:176
56054963 msgid "Georgian"
5606 msgstr ""
4964 msgstr "Georgià"
56074965
56084966 #: src/ui/gui/psppire-encoding-selector.c:177
56094967 msgid "Greek"
5610 msgstr ""
4968 msgstr "Grec"
56114969
56124970 #: src/ui/gui/psppire-encoding-selector.c:178
56134971 msgid "Gujarati"
5614 msgstr ""
4972 msgstr "Gujarati"
56154973
56164974 #: src/ui/gui/psppire-encoding-selector.c:179
56174975 msgid "Gurmukhi"
5618 msgstr ""
4976 msgstr "Gurmukhi"
56194977
56204978 #: src/ui/gui/psppire-encoding-selector.c:180
56214979 msgid "Hebrew"
5622 msgstr ""
4980 msgstr "Hebreu"
56234981
56244982 #: src/ui/gui/psppire-encoding-selector.c:182
56254983 msgid "Hebrew Visual"
5626 msgstr ""
4984 msgstr "Hebreu Visual"
56274985
56284986 #: src/ui/gui/psppire-encoding-selector.c:183
56294987 msgid "Hindi"
5630 msgstr ""
4988 msgstr "Hindi"
56314989
56324990 #: src/ui/gui/psppire-encoding-selector.c:184
56334991 msgid "Icelandic"
5634 msgstr ""
4992 msgstr "Islandès"
56354993
56364994 #: src/ui/gui/psppire-encoding-selector.c:185
56374995 msgid "Japanese"
5638 msgstr ""
4996 msgstr "Japonès"
56394997
56404998 #: src/ui/gui/psppire-encoding-selector.c:187
56414999 msgid "Korean"
5642 msgstr ""
5000 msgstr "Coreà"
56435001
56445002 #: src/ui/gui/psppire-encoding-selector.c:189
56455003 msgid "Nordic"
5646 msgstr ""
5004 msgstr "Nórdic"
56475005
56485006 #: src/ui/gui/psppire-encoding-selector.c:190
56495007 msgid "Romanian"
5650 msgstr ""
5008 msgstr "Rumanès"
56515009
56525010 #: src/ui/gui/psppire-encoding-selector.c:192
56535011 msgid "South European"
5654 msgstr ""
5012 msgstr "Sud Europeu"
56555013
56565014 #: src/ui/gui/psppire-encoding-selector.c:193
56575015 msgid "Thai"
5658 msgstr ""
5016 msgstr "Tailandès"
56595017
56605018 #: src/ui/gui/psppire-encoding-selector.c:195
56615019 msgid "Turkish"
5662 msgstr ""
5020 msgstr "Turc"
56635021
56645022 #: src/ui/gui/psppire-encoding-selector.c:197
56655023 msgid "Vietnamese"
5666 msgstr ""
5024 msgstr "Vietnamita"
56675025
56685026 #: src/ui/gui/psppire-encoding-selector.c:199
56695027 msgid "Western European"
5670 msgstr ""
5028 msgstr "Europeu Occidental"
56715029
56725030 #: src/ui/gui/psppire-encoding-selector.c:222
56735031 msgid "Character Encoding: "
5674 msgstr ""
5675
5676 #: src/ui/gui/psppire-means-layer.c:45
5677 #, fuzzy, c-format
5678 msgid "Layer %d of %d"
5679 msgstr "Contrast %d de %d"
5032 msgstr "Codificació de caràcters: "
56805033
56815034 #: src/ui/gui/psppire-output-window.c:358
56825035 msgid "Message"
5683 msgstr ""
5036 msgstr "Missatje"
56845037
56855038 #: src/ui/gui/psppire-output-window.c:519
56865039 msgid "Infer file type from extension"
57365089 msgid "Save Syntax"
57375090 msgstr "Desar sintaxi"
57385091
5739 #: src/ui/gui/psppire-syntax-window.c:602 src/ui/gui/psppire-window.c:743
5092 #: src/ui/gui/psppire-syntax-window.c:602 src/ui/gui/psppire-window.c:764
57405093 msgid "Syntax Files (*.sps) "
57415094 msgstr "Arxius de Sintàxi (*.sps) "
57425095
58195172 msgid "{%s,`%s'}_"
58205173 msgstr "{%s,`%s'}_"
58215174
5822 #: src/ui/gui/psppire-window.c:505
5175 #: src/ui/gui/psppire-window.c:526
58235176 #, c-format
58245177 msgid "Save the changes to `%s' before closing?"
58255178 msgstr "Desa el canvis a `%s' abans de sortir?"
58265179
5827 #: src/ui/gui/psppire-window.c:512
5828 #, c-format
5829 msgid ""
5830 "If you don't save, changes from the last %ld seconds will be permanently "
5831 "lost."
5832 msgstr ""
5833 "Si no es desa, els canvis dels darrers %ld segons es perdran permanentment."
5834
5835 #: src/ui/gui/psppire-window.c:516
5180 #: src/ui/gui/psppire-window.c:533
5181 #, c-format
5182 msgid "If you don't save, changes from the last %ld seconds will be permanently lost."
5183 msgstr "Si no es desa, els canvis dels darrers %ld segons es perdran permanentment."
5184
5185 #: src/ui/gui/psppire-window.c:537
58365186 msgid "Close _without saving"
58375187 msgstr "Tancar sense desar"
58385188
5839 #: src/ui/gui/psppire-window.c:716
5189 #: src/ui/gui/psppire-window.c:737
58405190 msgid "Open"
58415191 msgstr "Obert"
58425192
5843 #: src/ui/gui/psppire-window.c:725
5193 #: src/ui/gui/psppire-window.c:746
58445194 msgid "Data and Syntax Files"
58455195 msgstr "Arxius de Dades i Sintaxi"
58465196
59035253
59045254 #: src/ui/gui/text-data-import-dialog.c:472
59055255 #, c-format
5906 msgid ""
5907 "Failed to read `%s', because it contains a line over %d bytes long and "
5908 "therefore appears not to be a text file."
5909 msgstr ""
5910 "Error en llegir `%s', per què conté una linia per sobre dels %d bytes de "
5911 "llarg i, per tant, sembla que no és un arxiu de text."
5256 msgid "Failed to read `%s', because it contains a line over %d bytes long and therefore appears not to be a text file."
5257 msgstr "Error en llegir `%s', per què conté una linia per sobre dels %d bytes de llarg i, per tant, sembla que no és un arxiu de text."
59125258
59135259 #: src/ui/gui/text-data-import-dialog.c:486
59145260 #, c-format
59355281
59365282 #: src/ui/gui/text-data-import-dialog.c:767
59375283 msgid ""
5938 "This assistant will guide you through the process of importing data into "
5939 "PSPP from a text file with one line per case, in which fields are separated "
5940 "by tabs, commas, or other delimiters.\n"
5284 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case, in which fields are separated by tabs, commas, or other delimiters.\n"
59415285 "\n"
59425286 msgstr ""
5943 "Aquest asistent t'acompanyarà per tot el procés d'importar dades cap al PSPP "
5944 "a partir d'un arxiu de text amb una linia per cas, al qual els camps estan "
5945 "separats per tabuladors, comes, o altres delimitadors.\n"
5287 "Aquest asistent t'acompanyarà per tot el procés d'importar dades cap al PSPP a partir d'un arxiu de text amb una linia per cas, al qual els camps estan separats per tabuladors, comes, o altres delimitadors.\n"
59465288 "\n"
59475289
59485290 #: src/ui/gui/text-data-import-dialog.c:773
59615303
59625304 #: src/ui/gui/text-data-import-dialog.c:787
59635305 #, c-format
5964 msgid ""
5965 "Only the first %zu line of the file will be shown for preview purposes in "
5966 "the following screens. "
5967 msgid_plural ""
5968 "Only the first %zu lines of the file will be shown for preview purposes in "
5969 "the following screens. "
5970 msgstr[0] ""
5971 "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents "
5972 "pantalles. "
5973 msgstr[1] ""
5974 "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents "
5975 "pantalles. "
5306 msgid "Only the first %zu line of the file will be shown for preview purposes in the following screens. "
5307 msgid_plural "Only the first %zu lines of the file will be shown for preview purposes in the following screens. "
5308 msgstr[0] "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents pantalles. "
5309 msgstr[1] "Només les primeres %zu linies de l'arxiu es previsualitzaran a les seguents pantalles. "
59765310
59775311 #: src/ui/gui/text-data-import-dialog.c:794
59785312 msgid "You may choose below how much of the file should actually be imported."
59905324 #: src/ui/gui/text-data-import-dialog.c:1778
59915325 #, c-format
59925326 msgid "Cannot parse field content `%.*s' as format %s: %s"
5993 msgstr ""
5994 "No es possible construïr l'arxiu de contingut `%.*s' com a format %s: %s"
5327 msgstr "No es possible construïr l'arxiu de contingut `%.*s' com a format %s: %s"
59955328
59965329 #: src/ui/gui/text-data-import-dialog.c:1931
59975330 msgid "Line"
60035336 msgstr "Interval de Confiança: %2d %%"
60045337
60055338 #: src/ui/gui/t-test-paired-samples.c:93
6006 #, fuzzy
60075339 msgid "_Options"
6008 msgstr "Opcions"
5340 msgstr "_Opcions"
60095341
60105342 #: src/ui/gui/t-test-paired-samples.c:105
60115343 msgid "Paired Samples T Test"
60165348 msgstr "Tipus de Test"
60175349
60185350 #: src/ui/gui/npar-two-sample-related.c:136
6019 #, fuzzy
60205351 msgid "_Wilcoxon"
6021 msgstr "W de Wilcoxon"
5352 msgstr "_Wilcoxon"
60225353
60235354 #: src/ui/gui/npar-two-sample-related.c:137
60245355 msgid "_Sign"
6025 msgstr ""
5356 msgstr "_Signe"
60265357
60275358 #: src/ui/gui/npar-two-sample-related.c:138
60285359 msgid "_McNemar"
6029 msgstr ""
5360 msgstr "_McNemar"
60305361
60315362 #: src/ui/gui/npar-two-sample-related.c:153
6032 #, fuzzy
60335363 msgid "Two-Related-Samples Tests"
6034 msgstr "Prova de mostres aparellades"
5364 msgstr "Prova de Dues mostres aparellades"
60355365
60365366 #: src/ui/gui/val-labs-dialog.c:511
60375367 #, c-format
60485378 msgid "Weight cases by %s"
60495379 msgstr "Pondera casos per %s"
60505380
6051 #: src/language/utilities/set.q:159 src/language/utilities/set.q:166
6052 #, fuzzy, c-format
5381 #: src/language/utilities/set.q:156 src/language/utilities/set.q:163
5382 #, c-format
60535383 msgid "%s must be at least 1."
6054 msgstr "LENGTH ha de ser com a mínim 1."
6055
6056 #: src/language/utilities/set.q:173 src/language/data-io/file-handle.q:102
6057 #, fuzzy, c-format
5384 msgstr "%s ha de ser com a mínim 1."
5385
5386 #: src/language/utilities/set.q:170 src/language/data-io/file-handle.q:102
5387 #, c-format
60585388 msgid "%s must not be negative."
6059 msgstr "%s no és un nom de variable."
6060
6061 #: src/language/utilities/set.q:192
5389 msgstr "%s no pot ser negatiu."
5390
5391 #: src/language/utilities/set.q:189
60625392 msgid "WORKSPACE must be at least 1MB"
60635393 msgstr "WORKSPACE ha de ser com a mínim 1 Mb"
60645394
6065 #: src/language/utilities/set.q:194
6066 #, fuzzy
5395 #: src/language/utilities/set.q:191
60675396 msgid "WORKSPACE must be positive"
6068 msgstr "WORKSPACE ha de ser com a mínim 1 Mb"
6069
6070 #: src/language/utilities/set.q:200 src/language/utilities/set.q:202
6071 #: src/language/utilities/set.q:204 src/language/utilities/set.q:206
6072 #: src/language/utilities/set.q:208 src/language/utilities/set.q:210
6073 #: src/language/utilities/set.q:212 src/language/utilities/set.q:214
6074 #: src/language/utilities/set.q:216 src/language/utilities/set.q:218
6075 #: src/language/utilities/set.q:220
5397 msgstr "WORKSPACE ha de ser positiu"
5398
5399 #: src/language/utilities/set.q:197 src/language/utilities/set.q:199
5400 #: src/language/utilities/set.q:201 src/language/utilities/set.q:203
5401 #: src/language/utilities/set.q:205 src/language/utilities/set.q:207
5402 #: src/language/utilities/set.q:209 src/language/utilities/set.q:211
5403 #: src/language/utilities/set.q:213 src/language/utilities/set.q:215
5404 #: src/language/utilities/set.q:217
60765405 #, c-format
60775406 msgid "%s is obsolete."
60785407 msgstr "%s és obsolet."
60795408
6080 #: src/language/utilities/set.q:226
5409 #: src/language/utilities/set.q:223
60815410 msgid "Active file compression is not implemented."
60825411 msgstr "La compressió d'arxius no està implementada."
60835412
6084 #: src/language/utilities/set.q:373
5413 #: src/language/utilities/set.q:370
60855414 msgid "EPOCH must be 1500 or later."
60865415 msgstr "EPOCH ha de ser 1500 o més tard."
60875416
6088 #: src/language/utilities/set.q:380
5417 #: src/language/utilities/set.q:377
60895418 msgid "expecting AUTOMATIC or year"
60905419 msgstr "esperant AUTOMATICA o any"
60915420
6092 #: src/language/utilities/set.q:408
5421 #: src/language/utilities/set.q:405
60935422 msgid "LENGTH must be at least 1."
60945423 msgstr "LENGTH ha de ser com a mínim 1."
60955424
6096 #: src/language/utilities/set.q:444
5425 #: src/language/utilities/set.q:441
60975426 #, c-format
60985427 msgid "%s is not a recognized encoding or locale name"
60995428 msgstr "%s no és una codificació o un nom local reconegut"
61005429
6101 #: src/language/utilities/set.q:505
5430 #: src/language/utilities/set.q:502
61025431 msgid "WIDTH must be at least 40."
61035432 msgstr "WIDTH ha de ser com a mínim 40."
61045433
6105 #: src/language/utilities/set.q:532
6106 #, c-format
6107 msgid ""
6108 "FORMAT requires numeric output format as an argument. Specified format %s "
6109 "is of type string."
6110 msgstr ""
6111 "FORMAT requereix format de resultat numeric com a argument. El format %s "
6112 "especificat es de tipus cadena."
6113
6114 #: src/language/utilities/set.q:746
5434 #: src/language/utilities/set.q:529
5435 #, c-format
5436 msgid "FORMAT requires numeric output format as an argument. Specified format %s is of type string."
5437 msgstr "FORMAT requereix format de resultat numeric com a argument. El format %s especificat es de tipus cadena."
5438
5439 #: src/language/utilities/set.q:743
61155440 msgid "ISL (32-bit IEEE 754 single, little-endian)"
61165441 msgstr "ISL (32-bit IEEE 754 single, little-endian)"
61175442
6118 #: src/language/utilities/set.q:749
5443 #: src/language/utilities/set.q:746
61195444 msgid "ISB (32-bit IEEE 754 single, big-endian)"
61205445 msgstr "ISB (32-bit IEEE 754 single, big-endian)"
61215446
6122 #: src/language/utilities/set.q:752
5447 #: src/language/utilities/set.q:749
61235448 msgid "IDL (64-bit IEEE 754 double, little-endian)"
61245449 msgstr "IDL (64-bit IEEE 754 double, little-endian)"
61255450
6126 #: src/language/utilities/set.q:755
5451 #: src/language/utilities/set.q:752
61275452 msgid "IDB (64-bit IEEE 754 double, big-endian)"
61285453 msgstr "IDB (64-bit IEEE 754 double, big-endian)"
61295454
6130 #: src/language/utilities/set.q:759
5455 #: src/language/utilities/set.q:756
61315456 msgid "VF (32-bit VAX F, VAX-endian)"
61325457 msgstr "VF (32-bit VAX F, VAX-endian)"
61335458
6134 #: src/language/utilities/set.q:762
5459 #: src/language/utilities/set.q:759
61355460 msgid "VD (64-bit VAX D, VAX-endian)"
61365461 msgstr "VD (64-bit VAX D, VAX-endian)"
61375462
6138 #: src/language/utilities/set.q:765
5463 #: src/language/utilities/set.q:762
61395464 msgid "VG (64-bit VAX G, VAX-endian)"
61405465 msgstr "VG (64-bit VAX G, VAX-endian)"
61415466
6142 #: src/language/utilities/set.q:769
5467 #: src/language/utilities/set.q:766
61435468 msgid "ZS (32-bit IBM Z hexadecimal short, big-endian)"
61445469 msgstr "ZS (32-bit IBM Z hexadecimal short, big-endian)"
61455470
6146 #: src/language/utilities/set.q:772
5471 #: src/language/utilities/set.q:769
61475472 msgid "ZL (64-bit IBM Z hexadecimal long, big-endian)"
61485473 msgstr "ZL (64-bit IBM Z hexadecimal long, big-endian)"
61495474
6150 #: src/language/utilities/set.q:912
5475 #: src/language/utilities/set.q:870
61515476 #, c-format
61525477 msgid "%s is %s."
61535478 msgstr "%s és %s."
61545479
6155 #: src/language/utilities/set.q:1016
6156 #, c-format
6157 msgid ""
6158 "Too many PRESERVE commands without a RESTORE: at most %d levels of saved "
6159 "settings are allowed."
6160 msgstr ""
6161 "Massa comandos PRESERVE sense un RESTORE: es permet, com a màxim, %d nivells "
6162 "de configuracions desades."
6163
6164 #: src/language/utilities/set.q:1035
5480 #: src/language/utilities/set.q:973
5481 #, c-format
5482 msgid "Too many PRESERVE commands without a RESTORE: at most %d levels of saved settings are allowed."
5483 msgstr "Massa comandos PRESERVE sense un RESTORE: es permet, com a màxim, %d nivells de configuracions desades."
5484
5485 #: src/language/utilities/set.q:992
61655486 msgid "RESTORE without matching PRESERVE."
61665487 msgstr "RESTORE sense el corresponent PRESERVE."
61675488
61685489 #: src/language/stats/crosstabs.q:294
6169 msgid ""
6170 "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE."
6171 msgstr ""
6172 "L'INFORME de perduts no esta disponible el mode general. S'assumeix "
6173 "MISSING=TABLE."
5490 msgid "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE."
5491 msgstr "L'INFORME de perduts no esta disponible el mode general. S'assumeix MISSING=TABLE."
61745492
61755493 #: src/language/stats/crosstabs.q:404
61765494 msgid "Too many cross-tabulation variables or dimensions."
64335751
64345752 #: src/language/stats/frequencies.q:398
64355753 #, c-format
6436 msgid ""
6437 "MAX for histogram must be greater than or equal to MIN, but MIN was "
6438 "specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
6439 msgstr ""
6440 "Per l'histograma, MAX ha de ser major o igual a MIN, però MIN s'ha "
6441 "especificat com a %.15g i MAX com a %.15g. MIN i MAX seràn ignorats."
5754 msgid "MAX for histogram must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
5755 msgstr "Per l'histograma, MAX ha de ser major o igual a MIN, però MIN s'ha especificat com a %.15g i MAX com a %.15g. MIN i MAX seràn ignorats."
64425756
64435757 #: src/language/stats/frequencies.q:419
64445758 #, c-format
6445 msgid ""
6446 "MAX for pie chart must be greater than or equal to MIN, but MIN was "
6447 "specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
6448 msgstr ""
6449 "Per grafica de sectors, MAX ha de ser major o igual a MIN, però MIN s'ha "
6450 "especificat com a %.15g i MAX com a %.15g. MIN i MAX seràn ignorats."
5759 msgid "MAX for pie chart must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
5760 msgstr "Per grafica de sectors, MAX ha de ser major o igual a MIN, però MIN s'ha especificat com a %.15g i MAX com a %.15g. MIN i MAX seràn ignorats."
64515761
64525762 #: src/language/stats/frequencies.q:722
64535763 #, c-format
64745784 #: src/language/stats/frequencies.q:1015
64755785 #, c-format
64765786 msgid "No valid data for variable %s; statistics not displayed."
6477 msgstr ""
6478 "No hi ha dades vàlides per a la variable %s; not es mostren estadístiques."
5787 msgstr "No hi ha dades vàlides per a la variable %s; not es mostren estadístiques."
64795788
64805789 #: src/language/stats/frequencies.q:1061
64815790 msgid "50 (Median)"
65365845 msgstr "Correlacions de Coeficients"
65375846
65385847 #: src/language/stats/regression.q:787
6539 msgid ""
6540 "The dependent variable is equal to the independent variable.The least "
6541 "squares line is therefore Y=X.Standard errors and related statistics may be "
6542 "meaningless."
6543 msgstr ""
6544 "La variable dependiente es igual a la variable independiente. La línea de "
6545 "minimos cuadrados es por tanto Y=X. Los errores estàndard i els estadistics "
6546 "relacionats podríen ser irrellevants."
5848 msgid "The dependent variable is equal to the independent variable.The least squares line is therefore Y=X.Standard errors and related statistics may be meaningless."
5849 msgstr "La variable dependiente es igual a la variable independiente. La línea de minimos cuadrados es por tanto Y=X. Los errores estàndard i els estadistics relacionats podríen ser irrellevants."
65475850
65485851 #: src/language/stats/regression.q:938
65495852 msgid "REGRESSION requires numeric variables."
65555858
65565859 #: src/language/data-io/file-handle.q:70
65575860 #, c-format
6558 msgid ""
6559 "File handle %s is already defined. Use CLOSE FILE HANDLE before redefining "
6560 "a file handle."
6561 msgstr ""
6562 "El manipulador d'arxiu %s ja ha esta definit. Utilitzar CLOSE FILE HANDLE "
6563 "abans de redefinir un manipulador d'arxius."
5861 msgid "File handle %s is already defined. Use CLOSE FILE HANDLE before redefining a file handle."
5862 msgstr "El manipulador d'arxiu %s ja ha esta definit. Utilitzar CLOSE FILE HANDLE abans de redefinir un manipulador d'arxius."
65645863
65655864 #: src/language/data-io/file-handle.q:127
65665865 msgid "RECFORM must be specified with MODE=360."
65685867
65695868 #: src/language/data-io/file-handle.q:138
65705869 #, c-format
6571 msgid ""
6572 "The specified file mode requires LRECL. Assuming %zu-character records."
6573 msgstr ""
6574 "El mode d'arxiu especificat requereix LRECL. S'asumeix registres de %zu "
6575 "caracters."
5870 msgid "The specified file mode requires LRECL. Assuming %zu-character records."
5871 msgstr "El mode d'arxiu especificat requereix LRECL. S'asumeix registres de %zu caracters."
65765872
65775873 #: src/language/data-io/file-handle.q:142
65785874 #, c-format
6579 msgid ""
6580 "Record length (%ld) must be between 1 and %lu bytes. Assuming %zu-character "
6581 "records."
6582 msgstr ""
6583 "L'amplada de registre (%ld) ha d'estar entre 1 i %lu bytes. S'asumeix %zu-"
6584 "registres de caracter."
5875 msgid "Record length (%ld) must be between 1 and %lu bytes. Assuming %zu-character records."
5876 msgstr "L'amplada de registre (%ld) ha d'estar entre 1 i %lu bytes. S'asumeix %zu-registres de caracter."
65855877
65865878 #: src/language/data-io/file-handle.q:183
65875879 msgid "file"
66025894
66035895 #: src/language/data-io/list.q:98
66045896 #, c-format
6605 msgid ""
6606 "The first case (%ld) specified precedes the last case (%ld) specified. The "
6607 "values will be swapped."
6608 msgstr ""
6609 "El primer cas (%ld) especificat precedeix a l'ultim cas (%ld) especificat. "
6610 "Els valors s'intercanviaran."
5897 msgid "The first case (%ld) specified precedes the last case (%ld) specified. The values will be swapped."
5898 msgstr "El primer cas (%ld) especificat precedeix a l'ultim cas (%ld) especificat. Els valors s'intercanviaran."
66115899
66125900 #: src/language/data-io/list.q:106
66135901 #, c-format
6614 msgid ""
6615 "The first case (%ld) to list is less than 1. The value is being reset to 1."
6616 msgstr ""
6617 "EL primer cas (%ld) per llistar es menor que 1. El valor es retorna a 1."
5902 msgid "The first case (%ld) to list is less than 1. The value is being reset to 1."
5903 msgstr "EL primer cas (%ld) per llistar es menor que 1. El valor es retorna a 1."
66185904
66195905 #: src/language/data-io/list.q:112
66205906 #, c-format
6621 msgid ""
6622 "The last case (%ld) to list is less than 1. The value is being reset to 1."
6623 msgstr ""
6624 "L'últim cas (%ld) per llistar es menor que 1. El valor es restaura a 1.."
5907 msgid "The last case (%ld) to list is less than 1. The value is being reset to 1."
5908 msgstr "L'últim cas (%ld) per llistar es menor que 1. El valor es restaura a 1.."
66255909
66265910 #: src/language/data-io/list.q:118
66275911 #, c-format
66705954
66715955 #: src/ui/gui/aggregate.ui:393
66725956 msgid "_Write a new data file containing only the aggregated variables"
6673 msgstr ""
6674 "Escriu un nou arxiu de dades que contingui només les variables agregades"
5957 msgstr "Escriu un nou arxiu de dades que contingui només les variables agregades"
66755958
66765959 #: src/ui/gui/aggregate.ui:430
66775960 msgid "label"
66915974
66925975 #: src/ui/gui/autorecode.ui:7
66935976 msgid "Automatic Recode"
6694 msgstr ""
5977 msgstr "Recodificació Automàtica"
66955978
66965979 #: src/ui/gui/autorecode.ui:92
6697 #, fuzzy
66985980 msgid "Variable -> New Name"
6699 msgstr " Variable:"
5981 msgstr "Variable -> Nom Nou"
67005982
67015983 #: src/ui/gui/autorecode.ui:115
6702 #, fuzzy
67035984 msgid "_Lowest value"
6704 msgstr "Valor Superior"
5985 msgstr "_Valor Inferior"
67055986
67065987 #: src/ui/gui/autorecode.ui:131
6707 #, fuzzy
67085988 msgid "_Highest value"
6709 msgstr "Valor Superior"
5989 msgstr "_Valor Superior"
67105990
67115991 #: src/ui/gui/autorecode.ui:153
67125992 msgid "Recode starting from"
6713 msgstr ""
5993 msgstr "Recodificació comença des de"
67145994
67155995 #: src/ui/gui/autorecode.ui:175
6716 #, fuzzy
67175996 msgid "_New Name"
6718 msgstr "Nou Valor"
5997 msgstr "_Nou Valor"
67195998
67205999 #: src/ui/gui/autorecode.ui:193
67216000 msgid "_Add New Name"
6722 msgstr ""
6001 msgstr "_Afegir Nou Nom"
67236002
67246003 #: src/ui/gui/autorecode.ui:235
67256004 msgid "_Use the same recoding scheme for all variables"
6726 msgstr ""
6005 msgstr "_Utilitzar el mateix esquema de codificació per a totes les variables"
67276006
67286007 #: src/ui/gui/autorecode.ui:250
67296008 msgid "Treat _blank string values as missing"
6730 msgstr ""
6009 msgstr "Tractar els valors de cadena en _blanc com a perduts"
67316010
67326011 #: src/ui/gui/binomial.ui:63
67336012 msgid "_Test Variable List:"
68246103
68256104 #: src/ui/gui/count.ui:7
68266105 msgid "Count Occurrences of Values within Cases"
6827 msgstr ""
6106 msgstr "Recomptar Ocurrencies de Valors dins de Casos"
68286107
68296108 #: src/ui/gui/count.ui:97
6830 #, fuzzy
68316109 msgid "Numeric _Variables:"
6832 msgstr "Nom de Variable:"
6110 msgstr "_Variables Numèriques:"
68336111
68346112 #: src/ui/gui/count.ui:132
6835 #, fuzzy
68366113 msgid "_Target Variable:"
6837 msgstr "Variable objectiu:"
6114 msgstr "Variable Objec_tiu:"
68386115
68396116 #: src/ui/gui/count.ui:164
6840 #, fuzzy
68416117 msgid "Target _Label:"
6842 msgstr "Variable objectiu:"
6118 msgstr "_Etiqueta d'Objetiu:"
68436119
68446120 #: src/ui/gui/count.ui:179
6845 #, fuzzy
68466121 msgid "_Define Values..."
6847 msgstr "Ponderar Cassos..."
6122 msgstr "_Definir Valors..."
68486123
68496124 #: src/ui/gui/count.ui:229
68506125 msgid "Count Values within Cases: Values to Count"
6851 msgstr ""
6126 msgstr "Recomptar Valors en Casos: Valors a Comptar"
68526127
68536128 #: src/ui/gui/count.ui:271
6854 #, fuzzy
68556129 msgid "Values _to Count:"
6856 msgstr "Valor de constrast"
6130 msgstr "Valors a Comp_tar:"
68576131
68586132 #: src/ui/gui/crosstabs.ui:7
68596133 msgid "Crosstabs"
68606134 msgstr "Taules _Creuades"
68616135
68626136 #: src/ui/gui/crosstabs.ui:57
6863 #, fuzzy
68646137 msgid "_Rows"
6865 msgstr "Filas"
6138 msgstr "_Files"
68666139
68676140 #: src/ui/gui/crosstabs.ui:100
6868 #, fuzzy
68696141 msgid "_Columns"
6870 msgstr "Columnes"
6142 msgstr "_Columnes"
68716143
68726144 #: src/ui/gui/crosstabs.ui:139
6873 #, fuzzy
68746145 msgid "_Format..."
6875 msgstr "Formato..."
6146 msgstr "_Format..."
68766147
68776148 #: src/ui/gui/crosstabs.ui:153
6878 #, fuzzy
68796149 msgid "_Statistics..."
6880 msgstr "Estatística"
6150 msgstr "_Estadístics..."
68816151
68826152 #: src/ui/gui/crosstabs.ui:167
6883 #, fuzzy
68846153 msgid "Ce_lls..."
6885 msgstr "Cel.les..."
6154 msgstr "Ce_l.les..."
68866155
68876156 #: src/ui/gui/crosstabs.ui:248
68886157 msgid "Crosstabs: Format"
69496218 msgstr "Valors Esperats:"
69506219
69516220 #: src/ui/gui/chi-square.ui:317
6952 #, fuzzy
69536221 msgid "Test _Variables"
6954 msgstr "Variables de prova:"
6222 msgstr "Variables de prova"
69556223
69566224 #: src/ui/gui/descriptives.ui:115 src/ui/gui/factor.ui:183
6957 #, fuzzy
69586225 msgid "_Variables:"
6959 msgstr "Variables:"
6226 msgstr "_Variables:"
69606227
69616228 #: src/ui/gui/descriptives.ui:159
6962 #, fuzzy
69636229 msgid "S_tatistics:"
6964 msgstr "Estadístiques:"
6230 msgstr "Es_tadístiques:"
69656231
69666232 #: src/ui/gui/descriptives.ui:198
6967 #, fuzzy
69686233 msgid "_Exclude entire case if any selected variable is missing"
6969 msgstr "Excluo el cas sencer si qualsevol variable te valor perdut"
6234 msgstr "_Exclou el cas sencer si qualsevol variable seleccionada te valor perdut"
69706235
69716236 #: src/ui/gui/descriptives.ui:214
6972 #, fuzzy
69736237 msgid "_Include user-missing data in analysis"
6974 msgstr "Incloure els valors perduts d'usuari a l'anàlisi"
6238 msgstr "_Incloure els valors perduts d'usuari a l'anàlisi"
69756239
69766240 #: src/ui/gui/descriptives.ui:230
6977 #, fuzzy
69786241 msgid "Save _Z-scores of selected variables as new variables"
6979 msgstr "Desar puntuacions-Z de les variables seleccionades com noves variables"
6242 msgstr "Desar puntuacions-_Z de les variables seleccionades com a noves variables"
69806243
69816244 #: src/ui/gui/descriptives.ui:252
69826245 msgid "Options:"
70726335 msgstr "Anàlisi Factorial: Extracció"
70736336
70746337 #: src/ui/gui/factor.ui:228
7075 #, fuzzy
70766338 msgid "_Method: "
7077 msgstr "Mètode: "
6339 msgstr "_Mètode: "
70786340
70796341 #: src/ui/gui/factor.ui:280
7080 #, fuzzy
70816342 msgid "Co_rrelation matrix"
7082 msgstr "Matriu de Correlació"
6343 msgstr "Matriu de Co_rrelació"
70836344
70846345 #: src/ui/gui/factor.ui:295
7085 #, fuzzy
70866346 msgid "Co_variance matrix"
7087 msgstr "Matriu de Covariància"
6347 msgstr "Matriu de Co_variància"
70886348
70896349 #: src/ui/gui/factor.ui:316
70906350 msgid "Analyze"
70916351 msgstr "Analitzar"
70926352
70936353 #: src/ui/gui/factor.ui:340
7094 #, fuzzy
70956354 msgid "_Unrotated factor solution"
7096 msgstr "Solució factorial sense rotació"
6355 msgstr "Sol·l_ució factorial sense rotació"
70976356
70986357 #: src/ui/gui/factor.ui:355
7099 #, fuzzy
71006358 msgid "_Scree plot"
7101 msgstr "Gràfic de sedimentació"
6359 msgstr "Gràfic de _sedimentació"
71026360
71036361 #: src/ui/gui/factor.ui:375 src/ui/gui/roc.ui:288
71046362 msgid "Display"
71056363 msgstr "Contingut"
71066364
71076365 #: src/ui/gui/factor.ui:448
7108 #, fuzzy
71096366 msgid "_Number of factors:"
7110 msgstr "Nombre de factors:"
6367 msgstr "_Nombre de factors:"
71116368
71126369 #: src/ui/gui/factor.ui:480
71136370 msgid "Extract"
71146371 msgstr "Extracció"
71156372
71166373 #: src/ui/gui/factor.ui:495 src/ui/gui/factor.ui:687
7117 #, fuzzy
71186374 msgid "Ma_ximum iterations for convergence:"
7119 msgstr "Iteracions màximes per convergència:"
6375 msgstr "Iteracions mà_ximes per convergència:"
71206376
71216377 #: src/ui/gui/factor.ui:560
71226378 msgid "Factor Analysis: Rotation"
71756431 msgstr "Cerca cap enrrera"
71766432
71776433 #: src/ui/gui/frequencies.ui:107
7178 #, fuzzy
71796434 msgid "_Variable(s):"
7180 msgstr "Variable(s):"
6435 msgstr "_Variable(s):"
71816436
71826437 #: src/ui/gui/frequencies.ui:148
7183 #, fuzzy
71846438 msgid "_Statistics:"
7185 msgstr "Estadístiques:"
6439 msgstr "E_stadístics:"
71866440
71876441 #: src/ui/gui/frequencies.ui:161
7188 #, fuzzy
71896442 msgid "Include _missing values"
7190 msgstr "Inclou valors perduts"
6443 msgstr "Inclou valors _perduts"
71916444
71926445 #: src/ui/gui/frequencies.ui:179
71936446 msgid "Charts..."
72906543 msgstr "<b>Gràfiques de Sectors</b>"
72916544
72926545 #: src/ui/gui/k-means.ui:7
7293 #, fuzzy
72946546 msgid "K-Means Cluster Analysis"
7295 msgstr "Anàlisi Factorial"
6547 msgstr "Anàlisi de Conglometars K-Mitjanes"
72966548
72976549 #: src/ui/gui/k-means.ui:93
7298 #, fuzzy
72996550 msgid "N_umber of Clusters: "
7300 msgstr "Nombre de casos"
6551 msgstr "_Nombre de conglomerats: "
73016552
73026553 #: src/ui/gui/k-related.ui:7
73036554 msgid "Tests for Several Related Samples"
73206571 msgstr "Q de Cochran"
73216572
73226573 #: src/ui/gui/ks-one-sample.ui:108
7323 #, fuzzy
73246574 msgid "Test _Variable List:"
7325 msgstr "Lista de Variable _Test:"
6575 msgstr "Llista de Variables de _Prova:"
73266576
73276577 #: src/ui/gui/ks-one-sample.ui:139
7328 #, fuzzy
73296578 msgid "_Normal"
7330 msgstr "Format"
6579 msgstr "_Normal"
73316580
73326581 #: src/ui/gui/ks-one-sample.ui:150
73336582 msgid "_Poisson"
7334 msgstr ""
6583 msgstr "_Poisson"
73356584
73366585 #: src/ui/gui/ks-one-sample.ui:164
7337 #, fuzzy
73386586 msgid "_Uniform"
7339 msgstr "_Transformar"
6587 msgstr "_Uniforme"
73406588
73416589 #: src/ui/gui/ks-one-sample.ui:178
73426590 msgid "_Exponential"
7343 msgstr ""
6591 msgstr "_Exponencial"
73446592
73456593 #: src/ui/gui/ks-one-sample.ui:199
73466594 msgid "Test Distribution"
7347 msgstr ""
7348
7349 #: src/ui/gui/means.ui:8
7350 #, fuzzy
7351 msgid "Means"
7352 msgstr "Mitjana"
7353
7354 #: src/ui/gui/means.ui:110
7355 #, fuzzy
7356 msgid "_Dependent List:"
7357 msgstr "Llista de Dependents:"
7358
7359 #: src/ui/gui/means.ui:139
7360 #, fuzzy
7361 msgid "_Independent List:"
7362 msgstr "Llista de Dependents:"
6595 msgstr "Distribució de Prova"
73636596
73646597 #: src/ui/gui/oneway.ui:8
73656598 msgid "One-Way ANOVA"
74026635 msgstr "Contrast 1 de 1"
74036636
74046637 #: src/ui/gui/paired-samples.ui:113
7405 #, fuzzy
74066638 msgid "Test _Pair(s):"
7407 msgstr "Variable(s) de prova:"
6639 msgstr "_Parella(es) de Prova:"
74086640
74096641 #: src/ui/gui/psppire.ui:7
74106642 msgid "Weight Cases"
75636795 msgstr "Rang assignat a empats"
75646796
75656797 #: src/ui/gui/runs.ui:113
7566 #, fuzzy
75676798 msgid "_Median"
7568 msgstr "Mediana"
6799 msgstr "_Mediana"
75696800
75706801 #: src/ui/gui/runs.ui:123
75716802 msgid "M_ean"
7572 msgstr ""
6803 msgstr "M_itjana"
75736804
75746805 #: src/ui/gui/runs.ui:137
75756806 msgid "Mo_de"
7576 msgstr ""
6807 msgstr "M_oda"
75776808
75786809 #: src/ui/gui/runs.ui:154
7579 #, fuzzy
75806810 msgid "_Custom:"
7581 msgstr "Usuari"
6811 msgstr "_Personalitzat:"
75826812
75836813 #: src/ui/gui/runs.ui:193
7584 #, fuzzy
75856814 msgid "Cut Point"
7586 msgstr "Punt de tall:"
6815 msgstr "Punt de tall"
75876816
75886817 #: src/ui/gui/sort.ui:8
75896818 msgid "Sort Cases"
76866915 msgstr "Valors antics i nous"
76876916
76886917 #: src/ui/gui/regression.ui:32
7689 #, fuzzy
76906918 msgid "S_tatistics..."
7691 msgstr "Estatística"
6919 msgstr "E_stadístics..."
76926920
76936921 #: src/ui/gui/regression.ui:47
7694 #, fuzzy
76956922 msgid "_Save..."
7696 msgstr "Desar..."
6923 msgstr "De_sar..."
76976924
76986925 #: src/ui/gui/regression.ui:165
7699 #, fuzzy
77006926 msgid "_Dependent"
7701 msgstr "Dependent"
6927 msgstr "_Dependent"
77026928
77036929 #: src/ui/gui/regression.ui:213
7704 #, fuzzy
77056930 msgid "_Independent"
7706 msgstr "Independent"
6931 msgstr "_Independent"
77076932
77086933 #: src/ui/gui/regression.ui:252
77096934 msgid "Regression: Save"
77106935 msgstr "Regresió: Desar"
77116936
77126937 #: src/ui/gui/regression.ui:267 src/ui/gui/univariate.ui:222
7713 #, fuzzy
77146938 msgid "_Predicted values"
7715 msgstr "Valors predits"
6939 msgstr "Valors _Predits"
77166940
77176941 #: src/ui/gui/regression.ui:281 src/ui/gui/univariate.ui:236
7718 #, fuzzy
77196942 msgid "_Residuals"
7720 msgstr "Residuals"
6943 msgstr "_Residuals"
77216944
77226945 #: src/ui/gui/regression.ui:317
77236946 msgid "Regression: Statistics"
77246947 msgstr "Regresió: Estadìstics"
77256948
77266949 #: src/ui/gui/regression.ui:358 src/ui/gui/univariate.ui:313
7727 #, fuzzy
77286950 msgid "S_tatistics"
7729 msgstr "Estatísticas"
6951 msgstr "E_statístics"
77306952
77316953 #: src/ui/gui/reliability.ui:26
77326954 msgid "Reliability Analysis"
77376959 msgstr "_Items:"
77386960
77396961 #: src/ui/gui/reliability.ui:142
7740 #, fuzzy
77416962 msgid "_Model: "
7742 msgstr "Model:\t"
6963 msgstr "_Model: "
77436964
77446965 #: src/ui/gui/reliability.ui:183
7745 #, fuzzy
77466966 msgid "_Variables in first split:"
7747 msgstr "Variables a primera divissió:"
6967 msgstr "_Variables a la primera divisió:"
77486968
77496969 #: src/ui/gui/reliability.ui:222
7750 #, fuzzy
77516970 msgid "Show _descriptives for scale if item is deleted"
7752 msgstr "Mostrar descriptius per escala si l'_item és esborrat"
6971 msgstr "Mostrar _descriptius per escala si l'item és esborrat"
77536972
77546973 #: src/ui/gui/roc.ui:115
77556974 msgid "_Test Variable:"
78927111 msgstr "Prova T per una mostra"
78937112
78947113 #: src/ui/gui/t-test.ui:630
7895 #, fuzzy
78967114 msgid "Test _Value: "
7897 msgstr "Valor de prova: "
7115 msgstr "_Valor de Prova: "
78987116
78997117 #: src/ui/gui/text-data-import.ui:8
79007118 msgid "Importing Textual Data"
79027120
79037121 #: src/ui/gui/text-data-import.ui:19
79047122 msgid ""
7905 "This assistant will guide you through the process of importing data into "
7906 "PSPP from a text file with one line per case, in which fields are separated "
7907 "by tabs, commas, or other delimiters.\n"
7123 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case, in which fields are separated by tabs, commas, or other delimiters.\n"
79087124 "\n"
7909 "The selected file contains N lines of text. Only the first M of these will "
7910 "be shown for preview purposes in the following screens. You may choose "
7911 "below how much of the file should actually be imported."
7125 "The selected file contains N lines of text. Only the first M of these will be shown for preview purposes in the following screens. You may choose below how much of the file should actually be imported."
79127126 msgstr ""
7913 "Aquest assitent t'acompanyarà per tot el procés d'importar dades al PSPP des "
7914 "d'un arxiu de text amb una linia per cas, al qual els camps estan separats "
7915 "per tabuladors, comas, o altres delimitadors.\n"
7127 "Aquest assitent t'acompanyarà per tot el procés d'importar dades al PSPP des d'un arxiu de text amb una linia per cas, al qual els camps estan separats per tabuladors, comas, o altres delimitadors.\n"
79167128 "\n"
7917 "L'arxiu seleccionat conté N linies de text. Només les primeres M seran "
7918 "mostrades per previsualització a les pantalles seguents. Pots triar a "
7919 "continuació quina part de l'arxiu ha de ser importat."
7129 "L'arxiu seleccionat conté N linies de text. Només les primeres M seran mostrades per previsualització a les pantalles seguents. Pots triar a continuació quina part de l'arxiu ha de ser importat."
79207130
79217131 #: src/ui/gui/text-data-import.ui:95
79227132 msgid "All cases"
80077217 msgstr "Ajustar formats de variables"
80087218
80097219 #: src/ui/gui/text-data-import.ui:551
8010 msgid ""
8011 "Check the data formats displayed below and fix any that are incorrect. You "
8012 "may set other variable properties now or later."
8013 msgstr ""
8014 "Comprovar les formats de les dades mostrades a continuació i corregir els "
8015 "problemes. Es pot asignar altres propietats de les variables ara o més tard."
7220 msgid "Check the data formats displayed below and fix any that are incorrect. You may set other variable properties now or later."
7221 msgstr "Comprovar les formats de les dades mostrades a continuació i corregir els problemes. Es pot asignar altres propietats de les variables ara o més tard."
80167222
80177223 #: src/ui/gui/text-data-import.ui:595
80187224 msgid "<b>Variables</b>"
80237229 msgstr "<b>Previsualització de dades</b>"
80247230
80257231 #: src/ui/gui/univariate.ui:7
8026 #, fuzzy
80277232 msgid "Univariate"
8028 msgstr "Covariància"
7233 msgstr "Univariat"
80297234
80307235 #: src/ui/gui/univariate.ui:110
8031 #, fuzzy
80327236 msgid "_Dependent Variable"
8033 msgstr "_Variable(s) Depenents:"
7237 msgstr "Variable(s) _Dependent(s):"
80347238
80357239 #: src/ui/gui/univariate.ui:159
8036 #, fuzzy
80377240 msgid "_Fixed Factors"
8038 msgstr "_Factor:"
7241 msgstr "_Factors Fixes:"
80397242
80407243 #: src/ui/gui/univariate.ui:207
80417244 msgid "Univariate: Save"
8042 msgstr ""
7245 msgstr "Univariat: Desar"
80437246
80447247 #: src/ui/gui/univariate.ui:272
8045 #, fuzzy
80467248 msgid "Univariate: Statistics"
8047 msgstr "Explorar: Estadístics"
7249 msgstr "Univariat: Estadístics"
80487250
80497251 #: src/ui/gui/var-sheet-dialogs.ui:7
80507252 msgid "Variable Type"
82907492 msgstr "_Calcular..."
82917493
82927494 #: src/ui/gui/data-editor.ui:301
8293 #, fuzzy
82947495 msgid "Cou_nt..."
8295 msgstr "_Font..."
7496 msgstr "Reco_mpte..."
82967497
82977498 #: src/ui/gui/data-editor.ui:307
82987499 msgid "Ran_k Cases..."
83007501
83017502 #: src/ui/gui/data-editor.ui:313
83027503 msgid "Auto_matic Recode..."
8303 msgstr ""
7504 msgstr "Recodificació Auto_màtica..."
83047505
83057506 #: src/ui/gui/data-editor.ui:319
83067507 msgid "Recode into _Same Variables..."
83387539 msgid "Compare _Means"
83397540 msgstr "Comparar _Mitjanes"
83407541
8341 #: src/ui/gui/data-editor.ui:382
8342 #, fuzzy
8343 msgid "_Means..."
8344 msgstr "_Mitjana"
8345
8346 #: src/ui/gui/data-editor.ui:388
7542 #: src/ui/gui/data-editor.ui:381
83477543 msgid "_One Sample T Test..."
83487544 msgstr "Prova T per una mostra..."
83497545
8350 #: src/ui/gui/data-editor.ui:394
7546 #: src/ui/gui/data-editor.ui:387
83517547 msgid "_Independent Samples T Test..."
83527548 msgstr "Prova T per a Mostres _Independents..."
83537549
8354 #: src/ui/gui/data-editor.ui:400
7550 #: src/ui/gui/data-editor.ui:393
83557551 msgid "_Paired Samples T Test..."
83567552 msgstr "Prova T per a Mostres A_parellades..."
83577553
8358 #: src/ui/gui/data-editor.ui:406
7554 #: src/ui/gui/data-editor.ui:399
83597555 msgid "One Way _ANOVA..."
83607556 msgstr "_ANOVA d'un factor..."
83617557
8362 #: src/ui/gui/data-editor.ui:412
8363 #, fuzzy
7558 #: src/ui/gui/data-editor.ui:405
83647559 msgid "_Univariate Analysis..."
8365 msgstr "_Anàlisi Factorial..."
8366
8367 #: src/ui/gui/data-editor.ui:420
7560 msgstr "Anàlisi Univariada..."
7561
7562 #: src/ui/gui/data-editor.ui:413
83687563 msgid "Bivariate _Correlation..."
83697564 msgstr "_Correlació Bivariada..."
83707565
8371 #: src/ui/gui/data-editor.ui:427
7566 #: src/ui/gui/data-editor.ui:420
83727567 msgid "_K-Means Cluster..."
8373 msgstr ""
8374
8375 #: src/ui/gui/data-editor.ui:433
7568 msgstr "Conglomerat K-Mitjanes..."
7569
7570 #: src/ui/gui/data-editor.ui:426
83767571 msgid "Factor _Analysis..."
83777572 msgstr "_Anàlisi Factorial..."
83787573
8379 #: src/ui/gui/data-editor.ui:440
7574 #: src/ui/gui/data-editor.ui:433
83807575 msgid "Re_liability..."
83817576 msgstr "Fiabi_litat..."
83827577
8383 #: src/ui/gui/data-editor.ui:446
7578 #: src/ui/gui/data-editor.ui:439
83847579 msgid "Linear _Regression..."
83857580 msgstr "_Regressió Lineal..."
83867581
8387 #: src/ui/gui/data-editor.ui:452
7582 #: src/ui/gui/data-editor.ui:445
83887583 msgid "_Non-Parametric Statistics"
83897584 msgstr "Proves _No-Paramétriques"
83907585
8391 #: src/ui/gui/data-editor.ui:458
7586 #: src/ui/gui/data-editor.ui:451
83927587 msgid "_Chi-Square..."
83937588 msgstr "_Chi-quadrat..."
83947589
8395 #: src/ui/gui/data-editor.ui:464
7590 #: src/ui/gui/data-editor.ui:457
83967591 msgid "_Binomial..."
83977592 msgstr "_Binomial..."
83987593
8399 #: src/ui/gui/data-editor.ui:470
8400 #, fuzzy
7594 #: src/ui/gui/data-editor.ui:463
84017595 msgid "R_uns..."
8402 msgstr "Vincles..."
8403
8404 #: src/ui/gui/data-editor.ui:476
8405 #, fuzzy
7596 msgstr "Exec_ucions..."
7597
7598 #: src/ui/gui/data-editor.ui:469
84067599 msgid "1-Sample _K-S..."
8407 msgstr "Mostra..."
8408
8409 #: src/ui/gui/data-editor.ui:482
8410 #, fuzzy
7600 msgstr "_K-S per a Una Mostra..."
7601
7602 #: src/ui/gui/data-editor.ui:475
84117603 msgid "2 _Related Samples..."
8412 msgstr "K Mostre_s aparellades..."
8413
8414 #: src/ui/gui/data-editor.ui:488
7604 msgstr "Dues Mostres Apa_rellades..."
7605
7606 #: src/ui/gui/data-editor.ui:481
84157607 msgid "K Related _Samples..."
84167608 msgstr "K Mostre_s aparellades..."
84177609
8418 #: src/ui/gui/data-editor.ui:495
7610 #: src/ui/gui/data-editor.ui:488
84197611 msgid "ROC Cur_ve..."
84207612 msgstr "Corba ROC..."
84217613
8422 #: src/ui/gui/data-editor.ui:501
7614 #: src/ui/gui/data-editor.ui:494
84237615 msgid "_Utilities"
84247616 msgstr "_Utilitats"
84257617
8426 #: src/ui/gui/data-editor.ui:508
7618 #: src/ui/gui/data-editor.ui:501
84277619 msgid "_Variables..."
84287620 msgstr "_Variables..."
84297621
8430 #: src/ui/gui/data-editor.ui:509
7622 #: src/ui/gui/data-editor.ui:502
84317623 msgid "Jump to variable"
84327624 msgstr "Anar a la variable"
84337625
8434 #: src/ui/gui/data-editor.ui:516
7626 #: src/ui/gui/data-editor.ui:509
84357627 msgid "Data File _Comments..."
84367628 msgstr "_Comentaris arxiu de dades..."
84377629
8438 #: src/ui/gui/data-editor.ui:522 src/ui/gui/output-viewer.ui:47
7630 #: src/ui/gui/data-editor.ui:515 src/ui/gui/output-viewer.ui:47
84397631 #: src/ui/gui/syntax-editor.ui:143
84407632 msgid "_Windows"
84417633 msgstr "Finestres"
84427634
8443 #: src/ui/gui/data-editor.ui:528 src/ui/gui/output-viewer.ui:53
7635 #: src/ui/gui/data-editor.ui:521 src/ui/gui/output-viewer.ui:53
84447636 #: src/ui/gui/syntax-editor.ui:149
84457637 msgid "_Minimize All Windows"
84467638 msgstr "_Minimitza totes les finestres"
84477639
8448 #: src/ui/gui/data-editor.ui:534
7640 #: src/ui/gui/data-editor.ui:527
84497641 msgid "_Split"
84507642 msgstr "Divideix"
84517643
8452 #: src/ui/gui/data-editor.ui:719
7644 #: src/ui/gui/data-editor.ui:711
84537645 msgid "Information Area"
84547646 msgstr "Àrea d'Informació"
84557647
8456 #: src/ui/gui/data-editor.ui:741
7648 #: src/ui/gui/data-editor.ui:733
84577649 msgid "Processor Area"
84587650 msgstr "Area del processador"
84597651
8460 #: src/ui/gui/data-editor.ui:766
7652 #: src/ui/gui/data-editor.ui:758
84617653 msgid "Case Counter Area"
84627654 msgstr "Area del Recompte"
84637655
8464 #: src/ui/gui/data-editor.ui:791
7656 #: src/ui/gui/data-editor.ui:783
84657657 msgid "Filter Use Status Area"
84667658 msgstr "Area del Filtre"
84677659
8468 #: src/ui/gui/data-editor.ui:817
7660 #: src/ui/gui/data-editor.ui:809
84697661 msgid "Weight Status Area"
84707662 msgstr "Area de Ponderació"
84717663
8472 #: src/ui/gui/data-editor.ui:843
7664 #: src/ui/gui/data-editor.ui:835
84737665 msgid "Split File Status Area"
84747666 msgstr "Area de Divisió"
84757667
85017693 msgid "To End"
85027694 msgstr "Fins al final"
85037695
8504 #: src/ui/gui/gen-dot-desktop.sh:14
8505 #, fuzzy
8506 msgid "Statistical Software"
8507 msgstr "Estatístic"
8508
8509 #: src/ui/gui/gen-dot-desktop.sh:15
8510 msgid "Analyze statistical data with a free alternative to SPSS"
8511 msgstr ""
8512
8513 #~ msgid "OK"
8514 #~ msgstr "OK"
8515
8516 #~ msgid "Go To"
8517 #~ msgstr "Anar a"
8518
8519 #~ msgid "Cancel"
8520 #~ msgstr "Cancel·lar"
8521
8522 #~ msgid "Help"
8523 #~ msgstr "Ajuda"
8524
8525 #~ msgid "Reset"
8526 #~ msgstr "Reiniciar"
8527
8528 #~ msgid "Paste"
8529 #~ msgstr "Enganxa"
8530
85317696 #~ msgid "Unknown variable format %<PRIu8>."
85327697 #~ msgstr "Format de variable %<PRIu8> desconegut."
85337698
85407705 #~ msgid "write"
85417706 #~ msgstr "escriure"
85427707
8543 #~ msgid ""
8544 #~ "%s is allowed only before the active dataset has been defined or inside "
8545 #~ "INPUT PROGRAM."
8546 #~ msgstr ""
8547 #~ "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins "
8548 #~ "de INPUT PROGRAM."
8549
8550 #~ msgid ""
8551 #~ "%s is allowed only after the active dataset has been defined or inside "
8552 #~ "INPUT PROGRAM."
8553 #~ msgstr ""
8554 #~ "%s només es permet després que l'arxiu de dades actiu s'ha definit, o "
8555 #~ "dins de INPUT PROGRAM."
7708 #~ msgid "%s is allowed only before the active dataset has been defined or inside INPUT PROGRAM."
7709 #~ msgstr "%s només es permet abans que l'arxiu de dades actiu s'ha definit o dins de INPUT PROGRAM."
7710
7711 #~ msgid "%s is allowed only after the active dataset has been defined or inside INPUT PROGRAM."
7712 #~ msgstr "%s només es permet després que l'arxiu de dades actiu s'ha definit, o dins de INPUT PROGRAM."
85567713
85577714 #~ msgid "missing required subcommand %s"
85587715 #~ msgstr "subordre requerida %s absent"
85767733 #~ msgstr "S'espera `(' al subcomando %s."
85777734
85787735 #~ msgid "`)' expected following variable names on REORDER subcommand."
8579 #~ msgstr ""
8580 #~ "`)' s'esperava seguit dels noms de la variable en el subcomando REORDER."
8581
8582 #~ msgid ""
8583 #~ "`=' expected between lists of new and old variable names on RENAME "
8584 #~ "subcommand."
8585 #~ msgstr ""
8586 #~ "`=' esperat entre les llistes de noms de variables noves i velles en el "
8587 #~ "subcomando RENAME."
7736 #~ msgstr "`)' s'esperava seguit dels noms de la variable en el subcomando REORDER."
7737
7738 #~ msgid "`=' expected between lists of new and old variable names on RENAME subcommand."
7739 #~ msgstr "`=' esperat entre les llistes de noms de variables noves i velles en el subcomando RENAME."
85887740
85897741 #~ msgid "`)' expected after variable lists on RENAME subcommand."
8590 #~ msgstr ""
8591 #~ "`)' esperat després de les llistes de variables en el subcomando RENAME."
7742 #~ msgstr "`)' esperat després de les llistes de variables en el subcomando RENAME."
85927743
85937744 #~ msgid "`/' or `.' expected."
85947745 #~ msgstr "'/' o '.' esperat."
86157766 #~ msgstr "El subcomando %s només pot ser utilitzat una vegada."
86167767
86177768 #~ msgid "Number of contrast coefficients must equal the number of groups"
8618 #~ msgstr ""
8619 #~ "El nombre de coeficients de contrast ha de ser igual al nombre de grups."
7769 #~ msgstr "El nombre de coeficients de contrast ha de ser igual al nombre de grups."
86207770
86217771 #~ msgid "Variables cannot be parsed"
86227772 #~ msgstr "No es poden generar les variables"
86437793 #~ msgstr "Tipus de registre 7 no reconegut, subtipe %d."
86447794
86457795 #~ msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
8646 #~ msgstr ""
8647 #~ "Camp de longitud (%zu) o quantitat (%zu) invàlids en el registre tipus 7, "
8648 #~ "subtipus 3."
7796 #~ msgstr "Camp de longitud (%zu) o quantitat (%zu) invàlids en el registre tipus 7, subtipus 3."
86497797
86507798 #~ msgid "Bad size (%zu) or count (%zu) on extension 4."
86517799 #~ msgstr "Longitud (%zu) o quantitat (%zu) de l'extensió 4 no vàlid."
86537801 #~ msgid "Missing space following `%c' at offset %zu in MRSETS record"
86547802 #~ msgstr "Espai perdut darrera `%c' a la posició %zu al registre MRSETS"
86557803
8656 #~ msgid ""
8657 #~ "Unexpected label source value `%s' following `E' at offset %zu in MRSETS "
8658 #~ "record"
8659 #~ msgstr ""
8660 #~ "Valor d'etiqueta no esperat `%s' darrera `E' a la posició %zu del "
8661 #~ "registre MRSETS"
7804 #~ msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record"
7805 #~ msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició %zu del registre MRSETS"
86627806
86637807 #~ msgid "Bad size %zu on extension 11."
86647808 #~ msgstr "Amplada no vàlida %zu en l'extensió 11."
86757819 #~ msgid "Bad count %zu for extended number of cases."
86767820 #~ msgstr "Recompte incorrecte %zu per nombre extens de casos."
86777821
8678 #~ msgid ""
8679 #~ "Variable name length in long string value label record (%d) exceeds %d-"
8680 #~ "byte limit."
8681 #~ msgstr ""
8682 #~ "La longitud del nom de la variable al registre de l'etiqueta del valor de "
8683 #~ "cadena llarga (%d) supera el límit %d-byte."
7822 #~ msgid "Variable name length in long string value label record (%d) exceeds %d-byte limit."
7823 #~ msgstr "La longitud del nom de la variable al registre de l'etiqueta del valor de cadena llarga (%d) supera el límit %d-byte."
86847824
86857825 #~ msgid "`)' expected after GROUPED interval list."
86867826 #~ msgstr "`)' esperat després de la llista de variables GRUPED."
86877827
8688 #~ msgid ""
8689 #~ "FRACTION has been specified, but NORMAL and PROPORTION rank functions "
8690 #~ "have not been requested. The FRACTION subcommand will be ignored."
8691 #~ msgstr ""
8692 #~ "S'ha especificat FRACTION, però no s'ahn demanat funcions de rang NORMAL "
8693 #~ "o PROPORTION. La subordre FRACTION será ignorada."
7828 #~ msgid "FRACTION has been specified, but NORMAL and PROPORTION rank functions have not been requested. The FRACTION subcommand will be ignored."
7829 #~ msgstr "S'ha especificat FRACTION, però no s'ahn demanat funcions de rang NORMAL o PROPORTION. La subordre FRACTION será ignorada."
86947830
86957831 #~ msgid "One or more VARIABLES must be specified."
86967832 #~ msgstr "Una o més VARIABLES han de ser especificades."
87077843 #~ msgid "Labeling"
87087844 #~ msgstr "Etiquetant"
87097845
8710 #~ msgid ""
8711 #~ "Scratch file handle %s has not yet been written, using SAVE or another "
8712 #~ "procedure, so it cannot yet be used for reading."
8713 #~ msgstr ""
8714 #~ "El manipulador de l'arxius de treball %s encara no s'ha escrit, "
8715 #~ "utilitzant SAVE o altre procediment, de manera que encara no es pot "
8716 #~ "llegir."
7846 #~ msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
7847 #~ msgstr "El manipulador de l'arxius de treball %s encara no s'ha escrit, utilitzant SAVE o altre procediment, de manera que encara no es pot llegir."
87177848
87187849 #~ msgid "scratch file"
87197850 #~ msgstr "arxiu de treball"
87227853 #~ msgstr "Sufix de la variable massa gran."
87237854
87247855 #~ msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
8725 #~ msgstr ""
8726 #~ "Espai perdut darrera `%c' a la posició UTF-8 %zu d'un registre MRSETS."
8727
8728 #~ msgid ""
8729 #~ "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in "
8730 #~ "MRSETS record."
8731 #~ msgstr ""
8732 #~ "Valor d'etiqueta no esperat `%s' darrera `E' a la posició UTF-8 %zu d'un "
8733 #~ "registre MRSETS."
7856 #~ msgstr "Espai perdut darrera `%c' a la posició UTF-8 %zu d'un registre MRSETS."
7857
7858 #~ msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
7859 #~ msgstr "Valor d'etiqueta no esperat `%s' darrera `E' a la posició UTF-8 %zu d'un registre MRSETS."
87347860
87357861 #~ msgid "PSPP-data"
87367862 #~ msgstr "datos-PSPP"
87507876 #~ msgid "Duplicate variable name %s in position %d."
87517877 #~ msgstr "Nom de la variable %s duplicat en la posició %d."
87527878
8753 #~ msgid ""
8754 #~ "Recoded variable name duplicates an existing `%s' within system file."
8755 #~ msgstr ""
8756 #~ "El nom de la variable recodificada duplica `%s' existent dins de l'arxiu "
8757 #~ "de sistema."
7879 #~ msgid "Recoded variable name duplicates an existing `%s' within system file."
7880 #~ msgstr "El nom de la variable recodificada duplica `%s' existent dins de l'arxiu de sistema."
87587881
87597882 #~ msgid "Variable name begins with invalid character `%c'."
87607883 #~ msgstr "El nom de la variable comença amb el caràctar invàlid `%c'."
88057928 #~ msgstr "%s és massa llarg per un nom de variable."
88067929
88077930 #~ msgid "%zu-byte string needed but %zu-byte string supplied."
8808 #~ msgstr ""
8809 #~ "Es necessita cadena de %zu-byte però s'han subministrat de %zu-byte."
7931 #~ msgstr "Es necessita cadena de %zu-byte però s'han subministrat de %zu-byte."
88107932
88117933 #~ msgid "Hexadecimal floating constant too long."
88127934 #~ msgstr "Constant hexadecimal flotant massa llarga."
88137935
8814 #~ msgid ""
8815 #~ "%s conversion of %s from %s to %s should have produced %s but actually "
8816 #~ "produced %s."
8817 #~ msgstr ""
8818 #~ "conversió %s de %s desde %s a %s s'hauria d'haver produït %s però "
8819 #~ "actualment ha produït %s."
7936 #~ msgid "%s conversion of %s from %s to %s should have produced %s but actually produced %s."
7937 #~ msgstr "conversió %s de %s desde %s a %s s'hauria d'haver produït %s però actualment ha produït %s."
88207938
88217939 #~ msgid "Too many values in single command."
88227940 #~ msgstr "Massa valors en el comandament únic."
90648182 #~ msgid "unexpected end of line expecting string"
90658183 #~ msgstr "final de línia inesperat quan s'esperava una cadena"
90668184
9067 #~ msgid ""
9068 #~ "ascii: bad index value for `box' key: syntax is box[INDEX], 0 <= INDEX < "
9069 #~ "%d decimal, with INDEX expressed in base 4"
9070 #~ msgstr ""
9071 #~ "ascii: índex de valor defectuós per a la clau `box' : la sintaxi és la box"
9072 #~ "[INDEX], 0 <= INDEX < %d decimal, amb INDEX expressat en base 4"
8185 #~ msgid "ascii: bad index value for `box' key: syntax is box[INDEX], 0 <= INDEX < %d decimal, with INDEX expressed in base 4"
8186 #~ msgstr "ascii: índex de valor defectuós per a la clau `box' : la sintaxi és la box[INDEX], 0 <= INDEX < %d decimal, amb INDEX expressat en base 4"
90738187
90748188 #~ msgid "ascii: multiple values for %s"
90758189 #~ msgstr "ascii: valors múltiples per a %s"
90768190
90778191 #~ msgid "ascii: only screen devices may have `auto' length or width"
9078 #~ msgstr ""
9079 #~ "ascii: només els dispositius de pantalla poden tenir longitud o amplada "
9080 #~ "`auto'"
8192 #~ msgstr "ascii: només els dispositius de pantalla poden tenir longitud o amplada `auto'"
90818193
90828194 #~ msgid "ascii: positive integer required as `%s' value"
90838195 #~ msgstr "ascii: enter positiu requerit com a valor `%s'"
90848196
90858197 #~ msgid "ascii: `emphasis' value must be `bold', `underline', or `none'"
9086 #~ msgstr ""
9087 #~ "ascii: el valor d' `emphasis' ha de ser `bold', `underline', o `none'"
8198 #~ msgstr "ascii: el valor d' `emphasis' ha de ser `bold', `underline', o `none'"
90888199
90898200 #~ msgid "ascii: zero or positive integer required as `%s' value"
90908201 #~ msgstr "ascii: zero o enter positiu requerit com a valor `%s'"
91028213 #~ msgstr "obrint arxiu de resultat HTML: %s"
91038214
91048215 #~ msgid "unknown configuration parameter `%s' for HTML device driver"
9105 #~ msgstr ""
9106 #~ "paràmetre de configuració `%s' desconegut per al dispositiu controlador "
9107 #~ "HTML"
8216 #~ msgstr "paràmetre de configuració `%s' desconegut per al dispositiu controlador HTML"
91088217
91098218 #~ msgid "unknown output driver `%s'"
91108219 #~ msgstr " controlador de sortida desconegut `%s'"
91158224 #~ msgid "using default output driver configuration"
91168225 #~ msgstr "utilitzant controlador de configuració de resultats per defecte"
91178226
9118 #~ msgid ""
9119 #~ "cannot find output initialization file (use `-vv' to view search path)"
9120 #~ msgstr ""
9121 #~ "no es pot trobar l'arxiu d'inicialització de resultats (utilitzar `-vv' "
9122 #~ "per a veure la ruta de cerca)"
8227 #~ msgid "cannot find output initialization file (use `-vv' to view search path)"
8228 #~ msgstr "no es pot trobar l'arxiu d'inicialització de resultats (utilitzar `-vv' per a veure la ruta de cerca)"
91238229
91248230 #~ msgid "cannot open \"%s\""
91258231 #~ msgstr "no es pot obrir \"%s\""
91438249 #~ "Clases de controlador:\n"
91448250 #~ "\t"
91458251
9146 #~ msgid ""
9147 #~ "reached end of options inside quoted string parsing options for \"%s\" "
9148 #~ "driver"
9149 #~ msgstr ""
9150 #~ "Arribat al final d'opcions dins de la cadena entre cometes tot analitzant "
9151 #~ "opcions pel controlador \"%s\""
8252 #~ msgid "reached end of options inside quoted string parsing options for \"%s\" driver"
8253 #~ msgstr "Arribat al final d'opcions dins de la cadena entre cometes tot analitzant opcions pel controlador \"%s\""
91528254
91538255 #~ msgid "syntax error in string constant parsing options for \"%s\" driver"
9154 #~ msgstr ""
9155 #~ "error de sintaxi en una constant de cadena analitzant opcions pel "
9156 #~ "controlador \"%s\""
8256 #~ msgstr "error de sintaxi en una constant de cadena analitzant opcions pel controlador \"%s\""
91578257
91588258 #~ msgid "syntax error expecting `=' parsing options for driver \"%s\""
9159 #~ msgstr ""
9160 #~ "error de sintaxi quan s'esperava `=' analitzant les opcions pel "
9161 #~ "controlador \"%s\""
8259 #~ msgstr "error de sintaxi quan s'esperava `=' analitzant les opcions pel controlador \"%s\""
91628260
91638261 #~ msgid "unknown output driver class `%.*s'"
91648262 #~ msgstr "controlador de sortida de classe desconeguda `%.*s'"
91678265 #~ msgstr "tipus de dispositiu desconegut `%.*s'"
91688266
91698267 #~ msgid "driver definition line missing driver name or class name"
9170 #~ msgstr ""
9171 #~ "línia de definició del controlador sense nom del controlador o nom de la "
9172 #~ "classe"
8268 #~ msgstr "línia de definició del controlador sense nom del controlador o nom de la classe"
91738269
91748270 #~ msgid "opening PostScript output file \"%s\""
91758271 #~ msgstr "obrir l'arxiu de sortida PostScript \"%s\""
91788274 #~ msgstr "tanqui l'arxiu de sortida PostScript \"%s\""
91798275
91808276 #~ msgid "unknown configuration parameter `%s' for PostScript device driver"
9181 #~ msgstr ""
9182 #~ "paràmetre de configuració desconegut`%s' pel controlador del dispositiu "
9183 #~ "PostScript"
9184
9185 #~ msgid ""
9186 #~ "unknown orientation `%s' (valid orientations are `portrait' and "
9187 #~ "`landscape')"
9188 #~ msgstr ""
9189 #~ "orientació desconeguda `%s' (les orientacions vàlides són `retrat' i "
9190 #~ "`paisatge')"
8277 #~ msgstr "paràmetre de configuració desconegut`%s' pel controlador del dispositiu PostScript"
8278
8279 #~ msgid "unknown orientation `%s' (valid orientations are `portrait' and `landscape')"
8280 #~ msgstr "orientació desconeguda `%s' (les orientacions vàlides són `retrat' i `paisatge')"
91918281
91928282 #~ msgid "boolean value expected for %s"
91938283 #~ msgstr "valor booleà esperat per a %s"
91958285 #~ msgid "positive integer value required for `%s'"
91968286 #~ msgstr "valor enter positiu necessari per a `%s'"
91978287
9198 #~ msgid ""
9199 #~ "default font size must be at least 1 point (value of 1000 for key `%s')"
9200 #~ msgstr ""
9201 #~ "la mida de caràcter per defecte ha de ser com a mínim 1 punt (valor de "
9202 #~ "1000 per la clau `%s')"
8288 #~ msgid "default font size must be at least 1 point (value of 1000 for key `%s')"
8289 #~ msgstr "la mida de caràcter per defecte ha de ser com a mínim 1 punt (valor de 1000 per la clau `%s')"
92038290
92048291 #~ msgid "could not find AFM file \"%s\""
92058292 #~ msgstr "no es pot trobar l'arxiu AFM \"%s\""
92288315 #~ msgid "creating \"%s\""
92298316 #~ msgstr "creant \"%s\""
92308317
9231 #~ msgid ""
9232 #~ "set to `compatible' if you want output calculated from broken algorithms"
9233 #~ msgstr ""
9234 #~ "activeu `compatible' si voleu obtenir resultats calculat a partir "
9235 #~ "d'algorismes trencats"
8318 #~ msgid "set to `compatible' if you want output calculated from broken algorithms"
8319 #~ msgstr "activeu `compatible' si voleu obtenir resultats calculat a partir d'algorismes trencats"
92368320
92378321 #~ msgid "Append DIR to include path"
92388322 #~ msgstr "Adjuntar DIR a la ruta d'inclusió"
92498333 #~ msgid "Don't allow some unsafe operations"
92508334 #~ msgstr "No permet algunes operacions insegures"
92518335
9252 #~ msgid ""
9253 #~ "Set to `compatible' if you want only to accept SPSS compatible syntax"
9254 #~ msgstr ""
9255 #~ "Activeu `compatible' si només voleu acceptar la sintaxi compatible de "
9256 #~ "l'SPSS"
8336 #~ msgid "Set to `compatible' if you want only to accept SPSS compatible syntax"
8337 #~ msgstr "Activeu `compatible' si només voleu acceptar la sintaxi compatible de l'SPSS"
92578338
92588339 #~ msgid "PSPP --- A program for statistical analysis"
92598340 #~ msgstr "PSPP ---Un programa d'anàlisi estadística"
92718352 #~ msgstr "Opcions que afecten a la sintaxi i al comportament:"
92728353
92738354 #~ msgid "Cannot open %s (%s). Writing errors to stdout instead.\n"
9274 #~ msgstr ""
9275 #~ "No es pot obrir %s (%s). Alternativament, escrivint errors a stdout.\n"
8355 #~ msgstr "No es pot obrir %s (%s). Alternativament, escrivint errors a stdout.\n"
92768356
92778357 #~ msgid "Terminating execution of syntax file due to error."
92788358 #~ msgstr "Finalitzant l'execució de l'arxiu de sintaxi degut a un error."
92848364 #~ msgstr "Enviar missatges d'error a FILE (annexa)"
92858365
92868366 #~ msgid "Select output driver DEVICE and disable defaults"
9287 #~ msgstr ""
9288 #~ "Seleccionar el controlador de sortida DEVICE i desactivar els valors per "
9289 #~ "defecte"
8367 #~ msgstr "Seleccionar el controlador de sortida DEVICE i desactivar els valors per defecte"
92908368
92918369 #~ msgid "Print a list of known driver classes, then exit"
9292 #~ msgstr ""
9293 #~ "Imprimir una llista de classes de controladors coneguts, després sortir"
8370 #~ msgstr "Imprimir una llista de classes de controladors coneguts, després sortir"
92948371
92958372 #~ msgid "Start an interactive session"
92968373 #~ msgstr "Inici d'una sessió interactiva"
94518528 #~ msgid "Messages Reported"
94528529 #~ msgstr "S'han generat missatges"
94538530
9454 #~ msgid ""
9455 #~ "The PSPP processor reported # errors. The first # and last # are shown "
9456 #~ "below:"
9457 #~ msgstr ""
9458 #~ "El processador d'PSPP ha genrat # errors. Els primers # y els darrers # "
9459 #~ "es mostren a continuació:"
8531 #~ msgid "The PSPP processor reported # errors. The first # and last # are shown below:"
8532 #~ msgstr "El processador d'PSPP ha genrat # errors. Els primers # y els darrers # es mostren a continuació:"
94608533
94618534 #~ msgid "gtk-close"
94628535 #~ msgstr "tanca-gtk"
94868559 #~ "Alpha\n"
94878560 #~ "Dividit"
94888561
9489 #~ msgid ""
9490 #~ "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will "
9491 #~ "be assumed. Argument values will be given precedence increasing along "
9492 #~ "the order given."
9493 #~ msgstr ""
9494 #~ "Al menys s'ha de donar algun BARCHART, HISTOGRAM o HBAR. S'assumeix "
9495 #~ "HBAR. Els valors d'arguments Argument tindrán preferencia creixent en "
9496 #~ "aquest mateix ordre)."
8562 #~ msgid "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will be assumed. Argument values will be given precedence increasing along the order given."
8563 #~ msgstr "Al menys s'ha de donar algun BARCHART, HISTOGRAM o HBAR. S'assumeix HBAR. Els valors d'arguments Argument tindrán preferencia creixent en aquest mateix ordre)."
94978564
94988565 #~ msgid "Variable %s specified multiple times on VARIABLES subcommand."
9499 #~ msgstr ""
9500 #~ "La variable %s s'ha especificat més d'una vegada a l'ordre VARIABLES."
8566 #~ msgstr "La variable %s s'ha especificat més d'una vegada a l'ordre VARIABLES."
95018567
95028568 #~ msgid "Cum"
95038569 #~ msgstr "Acumulat"
+1020
-2002
po/es.po less more
55 # Javier Gómez Serrano, 2009.
66 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2010.
77 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
8 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2011.
8 # Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>, 2012.
99 msgid ""
1010 msgstr ""
11 "Project-Id-Version: pspp-0.7.8\n"
11 "Project-Id-Version: pspp-0.7.9\n"
1212 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
13 "POT-Creation-Date: 2012-02-26 16:39+0100\n"
14 "PO-Revision-Date: 2011-08-17 13:28+0200\n"
13 "POT-Creation-Date: 2012-02-03 19:12-0800\n"
14 "PO-Revision-Date: 2012-04-25 20:14+0200\n"
1515 "Last-Translator: Francesc Josep Miguel Quesada <Miguel.Quesada@uab.cat>\n"
1616 "Language-Team: Spanish <es@li.org>\n"
1717 "Language: es\n"
2424 msgid "Sorry. The help system hasn't yet been implemented."
2525 msgstr "Disculpas. El sistema de ayuda todavía no ha sido implementado."
2626
27 #: src/ui/gui/psppire-buttonbox.c:329
27 #: src/ui/gui/psppire-buttonbox.c:329 src/ui/gui/psppire-buttonbox.c:487
2828 msgid "Continue"
2929 msgstr "Continuar"
3030
31 #: src/ui/gui/psppire-dictview.c:469 src/language/dictionary/split-file.c:82
31 #: src/ui/gui/psppire-buttonbox.c:485
32 msgid "OK"
33 msgstr "Ok"
34
35 #: src/ui/gui/psppire-buttonbox.c:486
36 msgid "Go To"
37 msgstr "Ir a"
38
39 #: src/ui/gui/psppire-buttonbox.c:488
40 msgid "Cancel"
41 msgstr "Cancelar"
42
43 #: src/ui/gui/psppire-buttonbox.c:489
44 msgid "Help"
45 msgstr "Ayuda"
46
47 #: src/ui/gui/psppire-buttonbox.c:490
48 msgid "Reset"
49 msgstr "Reiniciar"
50
51 #: src/ui/gui/psppire-buttonbox.c:491
52 msgid "Paste"
53 msgstr "Pegar"
54
55 #: src/ui/gui/psppire-dictview.c:466 src/language/dictionary/split-file.c:82
3256 #: src/language/dictionary/sys-file-info.c:148
33 #: src/language/dictionary/sys-file-info.c:332
34 #: src/language/dictionary/sys-file-info.c:646
57 #: src/language/dictionary/sys-file-info.c:331
58 #: src/language/dictionary/sys-file-info.c:645
3559 #: src/language/stats/descriptives.c:895
3660 #: src/language/data-io/data-parser.c:683
3761 #: src/language/data-io/data-parser.c:722 src/language/data-io/print.c:403
3862 msgid "Variable"
3963 msgstr "Variable"
4064
41 #: src/ui/gui/psppire-dictview.c:506
65 #: src/ui/gui/psppire-dictview.c:503
4266 msgid "Prefer variable labels"
4367 msgstr "Prefiero las etiquetas de variable"
4468
45 #: src/ui/gui/psppire-var-view.c:201
69 #: src/ui/gui/psppire-var-view.c:192
4670 #, c-format
4771 msgid "Var%d"
4872 msgstr "Var%d"
5276 msgid "An error occurred while opening `%s': %s."
5377 msgstr "Se ha producido un error al abrir `%s': %s."
5478
55 #: src/data/any-reader.c:111
79 #: src/data/any-reader.c:105
5680 #, c-format
5781 msgid "`%s' is not a system or portable file."
5882 msgstr "`%s' no es un archivo del sistema o portátil."
5983
60 #: src/data/any-reader.c:117 src/data/any-writer.c:67
84 #: src/data/any-reader.c:111 src/data/any-writer.c:67
6185 msgid "The inline file is not allowed here."
6286 msgstr "El archivo en línea no está permitido aquí."
6387
7498 #: src/data/calendar.c:119
7599 #, c-format
76100 msgid "Date %04d-%d-%d is before the earliest acceptable date of 1582-10-15."
77 msgstr ""
78 "La fecha %04d-%d-%d es anterior a la fecha aceptada más antigua, 1582-10-15."
101 msgstr "La fecha %04d-%d-%d es anterior a la fecha aceptada más antigua, 1582-10-15."
79102
80103 #: src/data/casereader-filter.c:221
81 msgid ""
82 "At least one case in the data read had a weight value that was user-missing, "
83 "system-missing, zero, or negative. These case(s) were ignored."
84 msgstr ""
85 "Al menos un caso en la lectura de datos tenia un valor de ponderación que es "
86 "perdido del usuari, del sistema, cero o negativo. Este(os) caso(s) fueron "
87 "ignorado(s)."
104 msgid "At least one case in the data read had a weight value that was user-missing, system-missing, zero, or negative. These case(s) were ignored."
105 msgstr "Al menos un caso en la lectura de datos tenia un valor de ponderación que es perdido del usuari, del sistema, cero o negativo. Este(os) caso(s) fueron ignorado(s)."
88106
89107 #. TRANSLATORS: this fragment will be interpolated into messages in fh_lock()
90108 #. that identify types of files.
92110 msgid "CSV file"
93111 msgstr "archivo CSV"
94112
95 #: src/data/csv-file-writer.c:161 src/data/sys-file-writer.c:227
113 #: src/data/csv-file-writer.c:161 src/data/sys-file-writer.c:225
96114 #, c-format
97115 msgid "Error opening `%s' for writing as a system file: %s."
98116 msgstr "Error al abrir `%s' para grabar como archivo de sistema: %s."
165183 msgstr "En la fecha se espera un delimitador entre los campos."
166184
167185 #: src/data/data-in.c:901
168 msgid ""
169 "Unrecognized month format. Months may be specified as Arabic or Roman "
170 "numerals or as at least 3 letters of their English names."
171 msgstr ""
172 "Formato de mes no reconocido. Los meses pueden ser especificados como "
173 "números Arábicos o Romanos, o como mínimo 3 letras de sus nombres en Inglés."
186 msgid "Unrecognized month format. Months may be specified as Arabic or Roman numerals or as at least 3 letters of their English names."
187 msgstr "Formato de mes no reconocido. Los meses pueden ser especificados como números Arábicos o Romanos, o como mínimo 3 letras de sus nombres en Inglés."
174188
175189 #: src/data/data-in.c:928
176190 #, c-format
211225 msgstr "Minuto (%ld) debe estar entre 0 y 59."
212226
213227 #: src/data/data-in.c:1070
214 msgid ""
215 "Unrecognized weekday name. At least the first two letters of an English "
216 "weekday name must be specified."
217 msgstr ""
218 "Día de la semana no reconocido. Al menos se deben especificar las dos "
219 "primeras letras del nombre en inglés."
228 msgid "Unrecognized weekday name. At least the first two letters of an English weekday name must be specified."
229 msgstr "Día de la semana no reconocido. Al menos se deben especificar las dos primeras letras del nombre en inglés."
220230
221231 #: src/data/data-in.c:1196
222232 #, c-format
235245
236246 #: src/data/dataset-reader.c:54
237247 #, c-format
238 msgid ""
239 "Cannot read from dataset %s because no dictionary or data has been written "
240 "to it yet."
241 msgstr ""
242 "No es pot llegir de l'arxiu de dades actiu %s perquè no s'ha omplert encara "
243 "amb cap diccionari o dades."
248 msgid "Cannot read from dataset %s because no dictionary or data has been written to it yet."
249 msgstr "No es pot llegir de l'arxiu de dades actiu %s perquè no s'ha omplert encara amb cap diccionari o dades."
244250
245251 #. TRANSLATORS: this fragment will be interpolated into
246252 #. messages in fh_lock() that identify types of files.
261267 msgstr "borrador"
262268
263269 #: src/data/dictionary.c:1004
264 msgid ""
265 "At least one case in the data file had a weight value that was user-missing, "
266 "system-missing, zero, or negative. These case(s) were ignored."
267 msgstr ""
268 "Al menos un caso del archivo de datos tenía un valor de ponderación perdido "
269 "de usuario, de sistema, cero o negativo. Estos caso(s) fueron ignorado(s)."
270
271 #: src/data/dictionary.c:1333
270 msgid "At least one case in the data file had a weight value that was user-missing, system-missing, zero, or negative. These case(s) were ignored."
271 msgstr "Al menos un caso del archivo de datos tenía un valor de ponderación perdido de usuario, de sistema, cero o negativo. Estos caso(s) fueron ignorado(s)."
272
273 #: src/data/dictionary.c:1330
272274 #, c-format
273275 msgid "Truncating document line to %d bytes."
274276 msgstr "Linea de documento truncada a %d bytes."
280282 #: src/data/file-handle-def.c:465
281283 #, c-format
282284 msgid "Can't read from %s as a %s because it is already being read as a %s."
283 msgstr ""
284 "No se puede leer de %s como una %s porque ya esta siendo leída como una %s."
285 msgstr "No se puede leer de %s como una %s porque ya esta siendo leída como una %s."
285286
286287 #: src/data/file-handle-def.c:469
287288 #, c-format
288289 msgid "Can't write to %s as a %s because it is already being written as a %s."
289 msgstr ""
290 "No se puede escribir en %s como una %s porque ya esta siendo escrita como "
291 "una %s."
290 msgstr "No se puede escribir en %s como una %s porque ya esta siendo escrita como una %s."
292291
293292 #: src/data/file-handle-def.c:476
294293 #, c-format
298297 #: src/data/file-name.c:173
299298 #, c-format
300299 msgid "Not opening pipe file `%s' because SAFER option set."
301 msgstr ""
302 "No abrir el archivo de transferencia '%s' porque la opción SAFER esta "
303 "activada."
300 msgstr "No abrir el archivo de transferencia '%s' porque la opción SAFER esta activada."
304301
305302 #: src/data/format.c:320
306303 msgid "Input format"
323320 #: src/data/format.c:345
324321 #, c-format
325322 msgid "%s %s specifies width %d, but %s requires a width between %d and %d."
326 msgstr ""
327 "%s %s especifica anchura %d, pero %s requiere una anchura entre %d y %d."
323 msgstr "%s %s especifica anchura %d, pero %s requiere una anchura entre %d y %d."
328324
329325 #: src/data/format.c:354
330326 #, c-format
331327 msgid "%s %s specifies %d decimal place, but %s does not allow any decimals."
332 msgid_plural ""
333 "%s %s specifies %d decimal places, but %s does not allow any decimals."
328 msgid_plural "%s %s specifies %d decimal places, but %s does not allow any decimals."
334329 msgstr[0] "%s %s especifica %d lugar decimal, pero %s no permite ninguno."
335330 msgstr[1] "%s %s especifica %d lugares decimales, pero %s no permite ninguno."
336331
337332 #: src/data/format.c:365
338333 #, c-format
339 msgid ""
340 "%s %s specifies %d decimal place, but the given width allows at most %d "
341 "decimals."
342 msgid_plural ""
343 "%s %s specifies %d decimal places, but the given width allows at most %d "
344 "decimals."
345 msgstr[0] ""
346 "%s %s especifica %d lugar decimal, pero la anchura dada permite como mucho "
347 "%d decimales."
348 msgstr[1] ""
349 "%s %s especifica %d lugares decimales, pero la anchura dada permite como "
350 "mucho %d decimales."
334 msgid "%s %s specifies %d decimal place, but the given width allows at most %d decimals."
335 msgid_plural "%s %s specifies %d decimal places, but the given width allows at most %d decimals."
336 msgstr[0] "%s %s especifica %d lugar decimal, pero la anchura dada permite como mucho %d decimales."
337 msgstr[1] "%s %s especifica %d lugares decimales, pero la anchura dada permite como mucho %d decimales."
351338
352339 #: src/data/format.c:372
353340 #, c-format
354 msgid ""
355 "%s %s specifies %d decimal place, but the given width does not allow for any "
356 "decimals."
357 msgid_plural ""
358 "%s %s specifies %d decimal places, but the given width does not allow for "
359 "any decimals."
360 msgstr[0] ""
361 "%s %s especifica %d lugar decimal, pero la anchura dada no permite ninguno."
362 msgstr[1] ""
363 "%s %s especifica %d lugares decimales, pero la anchura dada no permite "
364 "ninguno."
341 msgid "%s %s specifies %d decimal place, but the given width does not allow for any decimals."
342 msgid_plural "%s %s specifies %d decimal places, but the given width does not allow for any decimals."
343 msgstr[0] "%s %s especifica %d lugar decimal, pero la anchura dada no permite ninguno."
344 msgstr[1] "%s %s especifica %d lugares decimales, pero la anchura dada no permite ninguno."
365345
366346 #: src/data/format.c:411
367347 #, c-format
378358 msgid "Numeric"
379359 msgstr "Numérico"
380360
381 #: src/data/format.c:413 src/data/sys-file-reader.c:1713
382 #: src/data/sys-file-reader.c:1715 src/language/xforms/recode.c:506
361 #: src/data/format.c:413 src/data/sys-file-reader.c:1674
362 #: src/data/sys-file-reader.c:1676 src/language/xforms/recode.c:506
383363 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
384364 #: src/language/xforms/recode.c:520
385365 #: src/language/dictionary/apply-dictionary.c:77
387367 msgid "numeric"
388368 msgstr "numérico"
389369
390 #: src/data/format.c:413 src/data/sys-file-reader.c:1713
391 #: src/data/sys-file-reader.c:1715 src/language/xforms/recode.c:506
370 #: src/data/format.c:413 src/data/sys-file-reader.c:1674
371 #: src/data/sys-file-reader.c:1676 src/language/xforms/recode.c:506
392372 #: src/language/xforms/recode.c:507 src/language/xforms/recode.c:519
393373 #: src/language/xforms/recode.c:520
394374 #: src/language/dictionary/apply-dictionary.c:77
426406 msgstr "De usuario"
427407
428408 #: src/data/gnumeric-reader.c:35 src/data/ods-reader.c:38
429 #, fuzzy, c-format
409 #, c-format
430410 msgid "Support for %s files was not compiled into this installation of PSPP"
431 msgstr ""
432 "Soporte para archivos Gnumeric no fue compilado en esta instalación de PSPP"
411 msgstr "Soporte para archivos %s no fue compilado en esta instalación de PSPP"
433412
434413 #: src/data/gnumeric-reader.c:289
435414 #, c-format
441420 msgid "Invalid cell range `%s'"
442421 msgstr "Intervalo de celda `%s' inválido"
443422
444 #: src/data/gnumeric-reader.c:447 src/data/ods-reader.c:432
445 #: src/data/ods-reader.c:547
423 #: src/data/gnumeric-reader.c:447 src/data/ods-reader.c:430
424 #: src/data/ods-reader.c:545
446425 #, c-format
447426 msgid "Selected sheet or range of spreadsheet `%s' is empty."
448 msgstr ""
449 "La hoja o el intervalo de hojas de cálculo seleccionadas `%s' está vacía."
427 msgstr "La hoja o el intervalo de hojas de cálculo seleccionadas `%s' está vacía."
450428
451429 #: src/data/identifier2.c:60
452430 #, c-format
460438 #: src/data/identifier2.c:92
461439 #, c-format
462440 msgid "`%s' may not be used as an identifier because it is a reserved word."
463 msgstr ""
464 "`%s' no puede ser utilizado como identificador porque es una palabra "
465 "reservada."
441 msgstr "`%s' no puede ser utilizado como identificador porque es una palabra reservada."
466442
467443 #: src/data/identifier2.c:103
468444 #, c-format
469 msgid ""
470 "`%s' may not be used as an identifier because it contains ill-formed UTF-8 "
471 "at byte offset %tu."
472 msgstr ""
473 "`%s' no puede ser utilizado como identificador porque contiene UTF-8 "
474 "malformado en la posición %tu."
445 msgid "`%s' may not be used as an identifier because it contains ill-formed UTF-8 at byte offset %tu."
446 msgstr "`%s' no puede ser utilizado como identificador porque contiene UTF-8 malformado en la posición %tu."
475447
476448 #: src/data/identifier2.c:114
477449 #, c-format
478 msgid ""
479 "Character %s (in `%s') may not appear as the first character in a identifier."
480 msgstr ""
481 "Carácter %s (en `%s') no puede aparecer como el primer carácter en un "
482 "identificador."
450 msgid "Character %s (in `%s') may not appear as the first character in a identifier."
451 msgstr "Carácter %s (en `%s') no puede aparecer como el primer carácter en un identificador."
483452
484453 #: src/data/identifier2.c:126
485454 #, c-format
523492
524493 #: src/data/mrset.c:83
525494 #, c-format
526 msgid ""
527 "%s is not a valid name for a multiple response set. Multiple response set "
528 "names must begin with `$'."
529 msgstr ""
530 "%s no es un nombre válido de variable para un conjunto de respuesta "
531 "múltiple. Los conjuntos de respuesta múltiple han de comenzar con `$'."
495 msgid "%s is not a valid name for a multiple response set. Multiple response set names must begin with `$'."
496 msgstr "%s no es un nombre válido de variable para un conjunto de respuesta múltiple. Los conjuntos de respuesta múltiple han de comenzar con `$'."
532497
533498 #: src/data/ods-reader.c:359
534 #, fuzzy, c-format
499 #, c-format
535500 msgid "Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."
536 msgstr "Error al abrir `%s' para la lectura como archivo Gnumeric: %s."
501 msgstr "Error al abrir `%s' para la lectura como archivo de hoja de cálculo OpenDocument: %s."
537502
538503 #: src/data/ods-reader.c:368
539504 #, c-format
540505 msgid "Could not extract OpenDocument spreadsheet from file `%s': %s."
541 msgstr ""
506 msgstr "NO se pudo extraer la hoja de cálculo OpenDocument del archivo `%s': %s."
542507
543508 #: src/data/por-file-reader.c:101
544509 #, c-format
567532
568533 #: src/data/por-file-reader.c:283
569534 #, c-format
570 msgid ""
571 "An error occurred while opening `%s' for reading as a portable file: %s."
535 msgid "An error occurred while opening `%s' for reading as a portable file: %s."
572536 msgstr "Error abriendo `%s' para la lectura como archivo portátil: %s."
573537
574538 #: src/data/por-file-reader.c:304
614578
615579 #: src/data/por-file-reader.c:601
616580 #, c-format
617 msgid ""
618 "%s: Bad format specifier byte (%d). Variable will be assigned a default "
619 "format."
620 msgstr ""
621 "%s: Byte especificador de formato inválido (%d). Se asignará formato "
622 "predeterminado a la variable."
581 msgid "%s: Bad format specifier byte (%d). Variable will be assigned a default format."
582 msgstr "%s: Byte especificador de formato inválido (%d). Se asignará formato predeterminado a la variable."
623583
624584 #: src/data/por-file-reader.c:622
625585 #, c-format
626586 msgid "Numeric variable %s has invalid format specifier %s."
627 msgstr ""
628 "La variable numérica %s tiene una especificación de formato inválida %s."
587 msgstr "La variable numérica %s tiene una especificación de formato inválida %s."
629588
630589 #: src/data/por-file-reader.c:626
631590 #, c-format
632591 msgid "String variable %s with width %d has invalid format specifier %s."
633 msgstr ""
634 "La variable en cadena %s con longitud %d tiene una especificación de formato "
635 "inválida %s."
592 msgstr "La variable en cadena %s con longitud %d tiene una especificación de formato inválida %s."
636593
637594 #: src/data/por-file-reader.c:650
638595 msgid "Expected variable count record."
662619 msgid "Invalid variable name `%s' in position %d."
663620 msgstr "Nombre de la variable inválido `%s' en la posición %d."
664621
665 #: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:997
622 #: src/data/por-file-reader.c:694 src/data/sys-file-reader.c:963
666623 #, c-format
667624 msgid "Bad width %d for variable %s."
668625 msgstr "Ancho %d incorrecto para la variable %s."
670627 #: src/data/por-file-reader.c:708
671628 #, c-format
672629 msgid "Duplicate variable name %s in position %d renamed to %s."
673 msgstr ""
674 "Nombre de la variable %s duplicado en la posición %d se ha renombrado a %s."
630 msgstr "Nombre de la variable %s duplicado en la posición %d se ha renombrado a %s."
675631
676632 #: src/data/por-file-reader.c:757
677633 #, c-format
685641
686642 #: src/data/por-file-reader.c:804
687643 #, c-format
688 msgid ""
689 "Cannot assign value labels to %s and %s, which have different variable types."
690 msgstr ""
691 "No se puede asignar etiquetas de valor a %s y %s, que tienen diferentes "
692 "tipos de variables."
644 msgid "Cannot assign value labels to %s and %s, which have different variable types."
645 msgstr "No se puede asignar etiquetas de valor a %s y %s, que tienen diferentes tipos de variables."
693646
694647 #: src/data/por-file-writer.c:140
695648 #, c-format
701654 msgid "Error opening `%s' for writing as a portable file: %s."
702655 msgstr "Error abriendo `%s' para escribir como archivo portátil: %s."
703656
704 #: src/data/por-file-writer.c:503
657 #: src/data/por-file-writer.c:502
705658 #, c-format
706659 msgid "An I/O error occurred writing portable file `%s'."
707660 msgstr "Error I/O al escribir el archivo portátil `%s'."
708661
709662 #: src/data/psql-reader.c:47
710 msgid ""
711 "Support for reading postgres databases was not compiled into this "
712 "installation of PSPP"
713 msgstr ""
714 "El soporte para la lectura de las bases de datos postgres no fue compilado "
715 "en esta instalación de PSPP"
663 msgid "Support for reading postgres databases was not compiled into this installation of PSPP"
664 msgstr "El soporte para la lectura de las bases de datos postgres no fue compilado en esta instalación de PSPP"
716665
717666 #: src/data/psql-reader.c:241
718667 msgid "Memory error whilst opening psql source"
725674
726675 #: src/data/psql-reader.c:262
727676 #, c-format
728 msgid ""
729 "Postgres server is version %s. Reading from versions earlier than 8.0 is not "
730 "supported."
731 msgstr ""
732 "La versión del servidor Postgres es la %s. No es posible la lectura desde "
733 "versiones anteriores a la 8.0."
677 msgid "Postgres server is version %s. Reading from versions earlier than 8.0 is not supported."
678 msgstr "La versión del servidor Postgres es la %s. No es posible la lectura desde versiones anteriores a la 8.0."
734679
735680 #: src/data/psql-reader.c:282
736 msgid ""
737 "Connection is unencrypted, but unencrypted connections have not been "
738 "permitted."
739 msgstr ""
740 "La conexión no está cifrada, pero las conexiones sin cifrar no están "
741 "permitidas."
681 msgid "Connection is unencrypted, but unencrypted connections have not been permitted."
682 msgstr "La conexión no está cifrada, pero las conexiones sin cifrar no están permitidas."
742683
743684 #: src/data/psql-reader.c:318 src/data/psql-reader.c:343
744685 #: src/data/psql-reader.c:353
752693 msgstr "OID %d no admitido. Valores SYSMIS serán insertados."
753694
754695 #: src/data/settings.c:390
755 msgid ""
756 "MXWARNS set to zero. No further warnings will be given even when "
757 "potentially problematic situations are encountered."
758 msgstr ""
759 "MXWARNS colocado a cero. NIngún aviso se mostrará en lo sucesivo aunque se "
760 "den situaciones problemáticas."
696 msgid "MXWARNS set to zero. No further warnings will be given even when potentially problematic situations are encountered."
697 msgstr "MXWARNS colocado a cero. NIngún aviso se mostrará en lo sucesivo aunque se den situaciones problemáticas."
761698
762699 #: src/data/settings.c:397
763700 #, c-format
764 msgid ""
765 "Warnings re-enabled. %d warnings will be issued before aborting syntax "
766 "processing."
767 msgstr ""
768 "Avisos re-activados. %d avisos se mostraran antes de abortar el "
769 "procesamiento de sintaxis."
701 msgid "Warnings re-enabled. %d warnings will be issued before aborting syntax processing."
702 msgstr "Avisos re-activados. %d avisos se mostraran antes de abortar el procesamiento de sintaxis."
770703
771704 #: src/data/settings.c:605
772705 #, c-format
773 msgid ""
774 "%s: Custom currency string `%s' does not contain exactly three periods or "
775 "commas (or it contains both)."
776 msgstr ""
777 "%s: La cadena de moneda personalizada '%s' no contiene exactamente tres "
778 "puntos o comas (o contiene ambos)."
706 msgid "%s: Custom currency string `%s' does not contain exactly three periods or commas (or it contains both)."
707 msgstr "%s: La cadena de moneda personalizada '%s' no contiene exactamente tres puntos o comas (o contiene ambos)."
779708
780709 #. TRANSLATORS: this fragment will be interpolated into
781710 #. messages in fh_lock() that identify types of files.
782 #: src/data/sys-file-reader.c:359 src/data/sys-file-writer.c:215
711 #: src/data/sys-file-reader.c:324 src/data/sys-file-writer.c:213
783712 msgid "system file"
784713 msgstr "archivo de sistema"
785714
786 #: src/data/sys-file-reader.c:366
715 #: src/data/sys-file-reader.c:331
787716 #, c-format
788717 msgid "Error opening `%s' for reading as a system file: %s."
789718 msgstr "Error abriendo `%s' para la lectura como archivo de sistema: %s."
790719
791 #: src/data/sys-file-reader.c:418
720 #: src/data/sys-file-reader.c:388
792721 msgid "Misplaced type 4 record."
793722 msgstr "Registro de tipo 4 fuera de lugar."
794723
795 #: src/data/sys-file-reader.c:422
724 #: src/data/sys-file-reader.c:392
796725 msgid "Duplicate type 6 (document) record."
797726 msgstr "Registros de tipo 6 (document) duplicados."
798727
799 #: src/data/sys-file-reader.c:431 src/data/sys-file-reader.c:921
800 #, c-format
801 msgid ""
802 "Unrecognized record type 7, subtype %d. Please send a copy of this file, "
803 "and the syntax which created it to %s."
804 msgstr ""
805 "Registro de tipo 7, subtipo %d , no reconocido. Por favor envíe una copia de "
806 "este archivo, así como de la sintaxis que lo creó a %s."
807
808 #: src/data/sys-file-reader.c:440
809 #, c-format
810 msgid ""
811 "Record type 7, subtype %d found here has the same type as the record found "
812 "near offset 0x%llx. Please send a copy of this file, and the syntax which "
813 "created it to %s."
814 msgstr ""
815 "Registro de tipo 7, subtipo %d encontrado aquí del mismo tipo que el "
816 "registro encontrado cerca de la posición 0x%llx. Por favor envíe una copia "
817 "de este archivo y de la sintaxis que lo creó a %s."
818
819 #: src/data/sys-file-reader.c:453
728 #: src/data/sys-file-reader.c:401 src/data/sys-file-reader.c:900
729 #, c-format
730 msgid "Unrecognized record type 7, subtype %d. Please send a copy of this file, and the syntax which created it to %s."
731 msgstr "Registro de tipo 7, subtipo %d , no reconocido. Por favor envíe una copia de este archivo, así como de la sintaxis que lo creó a %s."
732
733 #: src/data/sys-file-reader.c:410
734 #, c-format
735 msgid "Record type 7, subtype %d found here has the same type as the record found near offset 0x%llx. Please send a copy of this file, and the syntax which created it to %s."
736 msgstr "Registro de tipo 7, subtipo %d encontrado aquí del mismo tipo que el registro encontrado cerca de la posición 0x%llx. Por favor envíe una copia de este archivo y de la sintaxis que lo creó a %s."
737
738 #: src/data/sys-file-reader.c:423
820739 #, c-format
821740 msgid "Unrecognized record type %d."
822741 msgstr "Tipo de registro %d no reconocido."
823742
824 #: src/data/sys-file-reader.c:500
743 #: src/data/sys-file-reader.c:467
825744 #, c-format
826745 msgid "Weighting variable must be numeric (not string variable `%s')."
827 msgstr ""
828 "Variable de ponderación tiene que ser numérica (no cadena textual `%s')."
829
830 #: src/data/sys-file-reader.c:535
746 msgstr "Variable de ponderación tiene que ser numérica (no cadena textual `%s')."
747
748 #: src/data/sys-file-reader.c:502
831749 #, c-format
832750 msgid "File header claims %d variable positions but %zu were read from file."
833 msgstr ""
834 "La cabecera del archivo requiere %d posiciones de variable, pero se han "
835 "leído %zu desde el archivo."
836
837 #: src/data/sys-file-reader.c:581
751 msgstr "La cabecera del archivo requiere %d posiciones de variable, pero se han leído %zu desde el archivo."
752
753 #: src/data/sys-file-reader.c:542
838754 #, c-format
839755 msgid "Error closing system file `%s': %s."
840756 msgstr "Error cerrando el archivo de sistema `%s': %s."
841757
842 #: src/data/sys-file-reader.c:634 src/data/sys-file-reader.c:644
758 #: src/data/sys-file-reader.c:604 src/data/sys-file-reader.c:614
843759 msgid "This is not an SPSS system file."
844760 msgstr "Esto no es un archivo de sistema de SPSS."
845761
846 #: src/data/sys-file-reader.c:667
847 msgid ""
848 "Compression bias is not the usual value of 100, or system file uses "
849 "unrecognized floating-point format."
850 msgstr ""
851 "El sesgo de compresión no es el valor habitual de 100, o el archivo de "
852 "sistema utiliza un formato de punto flotante no reconocido."
853
854 #: src/data/sys-file-reader.c:733
762 #: src/data/sys-file-reader.c:636
763 msgid "Compression bias is not the usual value of 100, or system file uses unrecognized floating-point format."
764 msgstr "El sesgo de compresión no es el valor habitual de 100, o el archivo de sistema utiliza un formato de punto flotante no reconocido."
765
766 #: src/data/sys-file-reader.c:712
855767 msgid "Variable label indicator field is not 0 or 1."
856768 msgstr "Campo indicador de etiqueta de variable no es 0 o 1."
857769
858 #: src/data/sys-file-reader.c:743
770 #: src/data/sys-file-reader.c:722
859771 msgid "Numeric missing value indicator field is not -3, -2, 0, 1, 2, or 3."
860 msgstr ""
861 "Campo de indicador de valores perdidos numéricos no es -3, -2, 0, 1, 2 o 3."
862
863 #: src/data/sys-file-reader.c:750
772 msgstr "Campo de indicador de valores perdidos numéricos no es -3, -2, 0, 1, 2 o 3."
773
774 #: src/data/sys-file-reader.c:729
864775 msgid "String missing value indicator field is not 0, 1, 2, or 3."
865776 msgstr "Campo de indicador de valores perdidos de cadena no es 0, 1, 2 o 3."
866777
867 #: src/data/sys-file-reader.c:770
778 #: src/data/sys-file-reader.c:749
868779 #, c-format
869780 msgid "Invalid number of labels %zu."
870781 msgstr "Número inválido de etiquetas %zu."
871782
872 #: src/data/sys-file-reader.c:795
873 msgid ""
874 "Variable index record (type 4) does not immediately follow value label "
875 "record (type 3) as it should."
876 msgstr ""
877 "Registro de índice de variable (tipo 4) no está seguido inmediatament, como "
878 "debería, por el registro de etiquetas de valores (tipo 3) ."
783 #: src/data/sys-file-reader.c:774
784 msgid "Variable index record (type 4) does not immediately follow value label record (type 3) as it should."
785 msgstr "Registro de índice de variable (tipo 4) no está seguido inmediatament, como debería, por el registro de etiquetas de valores (tipo 3) ."
786
787 #: src/data/sys-file-reader.c:782
788 #, c-format
789 msgid "Number of variables associated with a value label (%zu) is not between 1 and the number of variables (%zu)."
790 msgstr "El número de variables asociadas con una etiqueta de valor (%zu) no está entre 1 y el número de variables (%zu)."
879791
880792 #: src/data/sys-file-reader.c:803
881793 #, c-format
882 msgid ""
883 "Number of variables associated with a value label (%zu) is not between 1 and "
884 "the number of variables (%zu)."
885 msgstr ""
886 "El número de variables asociadas con una etiqueta de valor (%zu) no está "
887 "entre 1 y el número de variables (%zu)."
888
889 #: src/data/sys-file-reader.c:824
890 #, c-format
891794 msgid "Number of document lines (%d) must be greater than 0 and less than %d."
892 msgstr ""
893 "Número de líneas de documento (%d) tiene que ser mayor que 0 y menor que %d."
894
895 #: src/data/sys-file-reader.c:897
795 msgstr "Número de líneas de documento (%d) tiene que ser mayor que 0 y menor que %d."
796
797 #: src/data/sys-file-reader.c:876
896798 #, c-format
897799 msgid "Record type 7, subtype %d has bad size %zu (expected %d)."
898 msgstr ""
899 "Registro de tipo 7, subtipo %d tiene medida incorrecta %zu (se espera %d)."
900
901 #: src/data/sys-file-reader.c:901
800 msgstr "Registro de tipo 7, subtipo %d tiene medida incorrecta %zu (se espera %d)."
801
802 #: src/data/sys-file-reader.c:880
902803 #, c-format
903804 msgid "Record type 7, subtype %d has bad count %zu (expected %d)."
904 msgstr ""
905 "Registro de tipo 7, subtipo %d tiene recuento incorrecto %zu (se espera %d)."
906
907 #: src/data/sys-file-reader.c:993
805 msgstr "Registro de tipo 7, subtipo %d tiene recuento incorrecto %zu (se espera %d)."
806
807 #: src/data/sys-file-reader.c:959
908808 #, c-format
909809 msgid "Invalid variable name `%s'."
910810 msgstr "Nombre de variable '%s' no válido."
911811
912 #: src/data/sys-file-reader.c:1001
812 #: src/data/sys-file-reader.c:967
913813 #, c-format
914814 msgid "Duplicate variable name `%s'."
915815 msgstr "Nombre de variable `%s' duplicado."
916816
917 #: src/data/sys-file-reader.c:1072
817 #: src/data/sys-file-reader.c:1038
918818 msgid "Missing string continuation record."
919819 msgstr "Falta de registro de continuación de cadena."
920820
921 #: src/data/sys-file-reader.c:1114
922 #, fuzzy, c-format
821 #: src/data/sys-file-reader.c:1080
822 #, c-format
923823 msgid "Variable %s with width %d has invalid print format 0x%x."
924 msgstr ""
925 "La variable en cadena %s con longitud %d tiene una especificación de formato "
926 "inválida %s."
927
928 #: src/data/sys-file-reader.c:1118
929 #, fuzzy, c-format
824 msgstr "La variable %s con longitud %d tiene formato inválido 0x%x."
825
826 #: src/data/sys-file-reader.c:1084
827 #, c-format
930828 msgid "Variable %s with width %d has invalid write format 0x%x."
931 msgstr ""
932 "La variable en cadena %s con longitud %d tiene una especificación de formato "
933 "inválida %s."
934
935 #: src/data/sys-file-reader.c:1123
829 msgstr "La variable %s con longitud %d tiene formato de escritura inválido 0x%x."
830
831 #: src/data/sys-file-reader.c:1089
936832 msgid "Suppressing further invalid format warnings."
937833 msgstr "Se desactivan las alertas posteriores de formato no válido."
938834
939 #: src/data/sys-file-reader.c:1175
940 #, c-format
941 msgid ""
942 "Floating-point representation indicated by system file (%d) differs from "
943 "expected (%d)."
944 msgstr ""
945 "Representación del punto flotante indicado por el archivo de sistema (%d) "
946 "difiere de lo esperado (%d)."
947
948 #: src/data/sys-file-reader.c:1189
949 #, c-format
950 msgid ""
951 "Integer format indicated by system file (%d) differs from expected (%d)."
952 msgstr ""
953 "El formato entero indicado por el archivo de sistema (%d) difiere de lo "
954 "esperado (%d)."
955
956 #: src/data/sys-file-reader.c:1253 src/data/sys-file-reader.c:1257
957 #: src/data/sys-file-reader.c:1261
835 #: src/data/sys-file-reader.c:1141
836 #, c-format
837 msgid "Floating-point representation indicated by system file (%d) differs from expected (%d)."
838 msgstr "Representación del punto flotante indicado por el archivo de sistema (%d) difiere de lo esperado (%d)."
839
840 #: src/data/sys-file-reader.c:1155
841 #, c-format
842 msgid "Integer format indicated by system file (%d) differs from expected (%d)."
843 msgstr "El formato entero indicado por el archivo de sistema (%d) difiere de lo esperado (%d)."
844
845 #: src/data/sys-file-reader.c:1214 src/data/sys-file-reader.c:1218
846 #: src/data/sys-file-reader.c:1222
958847 #, c-format
959848 msgid "File specifies unexpected value %g as %s."
960849 msgstr "El archivo especifica un valor inesperado %g como %s."
961850
962 #: src/data/sys-file-reader.c:1294
851 #: src/data/sys-file-reader.c:1255
963852 #, c-format
964853 msgid "`%s' does not begin with `$' at offset %zu in MRSETS record."
965854 msgstr "`%s' no comienza con `$' en la posición %zu de un registro MRSETS."
966855
967 #: src/data/sys-file-reader.c:1305 src/data/sys-file-reader.c:1324
856 #: src/data/sys-file-reader.c:1266 src/data/sys-file-reader.c:1285
968857 #, c-format
969858 msgid "Missing space following `%c' at offset %zu in MRSETS record."
970859 msgstr "Espacio perdido tras `%c' en la posición %zu de un registro MRSETS."
971860
972 #: src/data/sys-file-reader.c:1334
973 #, c-format
974 msgid ""
975 "Unexpected label source value `%s' following `E' at offset %zu in MRSETS "
976 "record."
977 msgstr ""
978 "Valor de etiqueta inesperado `%s' tras `E' en la posición %zu de un registro "
979 "MRSETS."
980
981 #: src/data/sys-file-reader.c:1341
861 #: src/data/sys-file-reader.c:1295
862 #, c-format
863 msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record."
864 msgstr "Valor de etiqueta inesperado `%s' tras `E' en la posición %zu de un registro MRSETS."
865
866 #: src/data/sys-file-reader.c:1302
982867 #, c-format
983868 msgid "Missing `C', `D', or `E' at offset %zu in MRSETS record."
984869 msgstr "Falta `C', `D' o `E' en la posición %zu de un registro MRSETS."
985870
986 #: src/data/sys-file-reader.c:1373
871 #: src/data/sys-file-reader.c:1334
987872 #, c-format
988873 msgid "Missing new-line parsing variable names at offset %zu in MRSETS record."
989 msgstr ""
990 "Faltan nombres de variables para nueva línea en la posición %zu de un "
991 "registro MRSETS."
992
993 #: src/data/sys-file-reader.c:1389
874 msgstr "Faltan nombres de variables para nueva línea en la posición %zu de un registro MRSETS."
875
876 #: src/data/sys-file-reader.c:1350
994877 #, c-format
995878 msgid "Duplicate variable name %s at offset %zu in MRSETS record."
996 msgstr ""
997 "Nombre de variable %s duplicado en la posición %zu de un registro MRSETS."
998
999 #: src/data/sys-file-reader.c:1405
879 msgstr "Nombre de variable %s duplicado en la posición %zu de un registro MRSETS."
880
881 #: src/data/sys-file-reader.c:1366
1000882 #, c-format
1001883 msgid "MRSET %s contains both string and numeric variables."
1002884 msgstr "MRSET %s contiene tanto variables textuales como numéricas."
1003885
1004 #: src/data/sys-file-reader.c:1421
886 #: src/data/sys-file-reader.c:1382
1005887 #, c-format
1006888 msgid "MRSET %s has only %zu variables."
1007889 msgstr "MRSET %s tiene sólo %zu variables."
1008890
1009 #: src/data/sys-file-reader.c:1467
891 #: src/data/sys-file-reader.c:1428
1010892 #, c-format
1011893 msgid "Extension 11 has bad count %zu (for %zu variables)."
1012894 msgstr "Extensión 11 tiene un recuento inválido %zu (para %zu variables)."
1013895
1014 #: src/data/sys-file-reader.c:1501
1015 #, c-format
1016 msgid ""
1017 "Invalid variable display parameters for variable %zu (%s). Default "
1018 "parameters substituted."
1019 msgstr ""
1020 "Parámetros de visualización de variable no válidos para la variable %zu "
1021 "(%s). Sustitución de parámetros por defecto."
1022
1023 #: src/data/sys-file-reader.c:1598
896 #: src/data/sys-file-reader.c:1462
897 #, c-format
898 msgid "Invalid variable display parameters for variable %zu (%s). Default parameters substituted."
899 msgstr "Parámetros de visualización de variable no válidos para la variable %zu (%s). Sustitución de parámetros por defecto."
900
901 #: src/data/sys-file-reader.c:1559
1024902 #, c-format
1025903 msgid "Long variable mapping from %s to invalid variable name `%s'."
1026 msgstr ""
1027 "Identificación de variable larga desde %s hacia un nombre de variable "
1028 "inválido '%s'."
1029
1030 #: src/data/sys-file-reader.c:1609
904 msgstr "Identificación de variable larga desde %s hacia un nombre de variable inválido '%s'."
905
906 #: src/data/sys-file-reader.c:1570
1031907 #, c-format
1032908 msgid "Duplicate long variable name `%s'."
1033909 msgstr "Nombre largo de la variable `%s' duplicado."
1034910
1035 #: src/data/sys-file-reader.c:1642
911 #: src/data/sys-file-reader.c:1603
1036912 #, c-format
1037913 msgid "%s listed as string of invalid length %s in very long string record."
1038 msgstr ""
1039 "%s figura como cadena de longitud no válida %s en un registro de cadena muy "
1040 "largo."
1041
1042 #: src/data/sys-file-reader.c:1653
1043 #, c-format
1044 msgid ""
1045 "%s listed in very long string record with width %s, which requires only one "
1046 "segment."
1047 msgstr ""
1048 "%s figura en el registro de cadena muy larga con longitud %s, que requiere "
1049 "solo un segmento."
1050
1051 #: src/data/sys-file-reader.c:1660
914 msgstr "%s figura como cadena de longitud no válida %s en un registro de cadena muy largo."
915
916 #: src/data/sys-file-reader.c:1614
917 #, c-format
918 msgid "%s listed in very long string record with width %s, which requires only one segment."
919 msgstr "%s figura en el registro de cadena muy larga con longitud %s, que requiere solo un segmento."
920
921 #: src/data/sys-file-reader.c:1621
1052922 #, c-format
1053923 msgid "Very long string %s overflows dictionary."
1054924 msgstr "Cadena muy larga %s desborda el diccionario."
1055925
1056 #: src/data/sys-file-reader.c:1675
1057 #, c-format
1058 msgid ""
1059 "Very long string with width %ld has segment %d of width %d (expected %d)."
1060 msgstr ""
1061 "Cadena muy larga con una longitud %ld tiene un segmento %d de longitud %d "
1062 "(se espera %d)"
1063
1064 #: src/data/sys-file-reader.c:1709
1065 #, c-format
1066 msgid ""
1067 "Variables associated with value label are not all of identical type. "
1068 "Variable %s is %s, but variable %s is %s."
1069 msgstr ""
1070 "Las variables asociadas con etiqueta de valores no son todas del mismo "
1071 "tipo. La variable %s es %s, pero la variable %s es %s."
1072
1073 #: src/data/sys-file-reader.c:1726
1074 #, c-format
1075 msgid ""
1076 "Value labels may not be added to long string variables (e.g. %s) using "
1077 "records types 3 and 4."
1078 msgstr ""
1079 "No se pueden añadir etiquetas de valor a las variables de cadena larga (e.g. "
1080 "%s) utilizando los tipos de registro 3 y 4."
1081
1082 #: src/data/sys-file-reader.c:1745
926 #: src/data/sys-file-reader.c:1636
927 #, c-format
928 msgid "Very long string with width %ld has segment %d of width %d (expected %d)."
929 msgstr "Cadena muy larga con una longitud %ld tiene un segmento %d de longitud %d (se espera %d)"
930
931 #: src/data/sys-file-reader.c:1670
932 #, c-format
933 msgid "Variables associated with value label are not all of identical type. Variable %s is %s, but variable %s is %s."
934 msgstr "Las variables asociadas con etiqueta de valores no son todas del mismo tipo. La variable %s es %s, pero la variable %s es %s."
935
936 #: src/data/sys-file-reader.c:1687
937 #, c-format
938 msgid "Value labels may not be added to long string variables (e.g. %s) using records types 3 and 4."
939 msgstr "No se pueden añadir etiquetas de valor a las variables de cadena larga (e.g. %s) utilizando los tipos de registro 3 y 4."
940
941 #: src/data/sys-file-reader.c:1706
1083942 #, c-format
1084943 msgid "Duplicate value label for %g on %s."
1085944 msgstr "Etiqueta de valor duplicad para %g en %s."
1086945
1087 #: src/data/sys-file-reader.c:1749 src/data/sys-file-reader.c:1991
946 #: src/data/sys-file-reader.c:1710 src/data/sys-file-reader.c:1952
1088947 #, c-format
1089948 msgid "Duplicate value label for `%.*s' on %s."
1090949 msgstr "Etiqueta de valor duplicada para `%.*s' en %s."
1091950
1092 #: src/data/sys-file-reader.c:1774
951 #: src/data/sys-file-reader.c:1735
1093952 #, c-format
1094953 msgid "Variable index %d not in valid range 1...%zu."
1095954 msgstr "El índice de la variable %d no pertenece al intervalo válido 1...%zu."
1096955
1097 #: src/data/sys-file-reader.c:1783
956 #: src/data/sys-file-reader.c:1744
1098957 #, c-format
1099958 msgid "Variable index %d refers to long string continuation."
1100 msgstr ""
1101 "Índice de la variable %d se refiere a una continuación de cadena larga."
1102
1103 #: src/data/sys-file-reader.c:1819
959 msgstr "Índice de la variable %d se refiere a una continuación de cadena larga."
960
961 #: src/data/sys-file-reader.c:1780
1104962 #, c-format
1105963 msgid "Error parsing attribute value %s[%d]."
1106964 msgstr "Error al analizar el valor del atributo %s[%d]"
1107965
1108 #: src/data/sys-file-reader.c:1833
966 #: src/data/sys-file-reader.c:1794
1109967 #, c-format
1110968 msgid "Attribute value %s[%d] is not quoted: %s."
1111969 msgstr "El valor del atributo %s[%d] no está entre comillas: %s."
1112970
971 #: src/data/sys-file-reader.c:1847
972 msgid "Long string value label record ends unexpectedly."
973 msgstr "Etiqueta de valor de un registro de texto muy largo finaliza inesperadamente."
974
1113975 #: src/data/sys-file-reader.c:1886
1114 msgid "Long string value label record ends unexpectedly."
1115 msgstr ""
1116 "Etiqueta de valor de un registro de texto muy largo finaliza inesperadamente."
1117
1118 #: src/data/sys-file-reader.c:1925
1119976 #, c-format
1120977 msgid "Ignoring long string value record for unknown variable %s."
1121 msgstr ""
1122 "Ignorando el registro del valor de cadena larga para la variable desconocida "
1123 "%s."
1124
1125 #: src/data/sys-file-reader.c:1930
978 msgstr "Ignorando el registro del valor de cadena larga para la variable desconocida %s."
979
980 #: src/data/sys-file-reader.c:1891
1126981 #, c-format
1127982 msgid "Ignoring long string value record for numeric variable %s."
1128 msgstr ""
1129 "Ignorando el registro del valor de cadena larga para la variable numérica %s."
1130
1131 #: src/data/sys-file-reader.c:1937
1132 #, c-format
1133 msgid ""
1134 "Ignoring long string value record for variable %s because the record's width "
1135 "(%d) does not match the variable's width (%d)."
1136 msgstr ""
1137 "Ignorando el registro del valor de cadena larga %s ya que el ancho del "
1138 "registro (%d) no coincide con el ancho de la variable (%d)."
1139
1140 #: src/data/sys-file-reader.c:1966
1141 #, c-format
1142 msgid ""
1143 "Ignoring long string value %zu for variable %s, with width %d, that has bad "
1144 "value width %zu."
1145 msgstr ""
1146 "Ignorando el valor de cadena larga %zu para la variable %s, de ancho %d, que "
1147 "tiene un ancho de valor incorrecto %zu."
1148
1149 #: src/data/sys-file-reader.c:2070
983 msgstr "Ignorando el registro del valor de cadena larga para la variable numérica %s."
984
985 #: src/data/sys-file-reader.c:1898
986 #, c-format
987 msgid "Ignoring long string value record for variable %s because the record's width (%d) does not match the variable's width (%d)."
988 msgstr "Ignorando el registro del valor de cadena larga %s ya que el ancho del registro (%d) no coincide con el ancho de la variable (%d)."
989
990 #: src/data/sys-file-reader.c:1927
991 #, c-format
992 msgid "Ignoring long string value %zu for variable %s, with width %d, that has bad value width %zu."
993 msgstr "Ignorando el valor de cadena larga %zu para la variable %s, de ancho %d, que tiene un ancho de valor incorrecto %zu."
994
995 #: src/data/sys-file-reader.c:2031
1150996 msgid "File ends in partial case."
1151997 msgstr "El archivo acaba en un caso parcial."
1152998
1153 #: src/data/sys-file-reader.c:2078
999 #: src/data/sys-file-reader.c:2039
11541000 #, c-format
11551001 msgid "Error reading case from file %s."
11561002 msgstr "Error leyendo un caso del archivo %s."
11571003
1158 #: src/data/sys-file-reader.c:2180
1159 msgid ""
1160 "Possible compressed data corruption: compressed spaces appear in numeric "
1161 "field."
1162 msgstr ""
1163 "Posible corrupción de datos comprimidos: aparecen espacios comprimidos en un "
1164 "campo numérico."
1165
1166 #: src/data/sys-file-reader.c:2234
1167 #, c-format
1168 msgid ""
1169 "Possible compressed data corruption: string contains compressed integer "
1170 "(opcode %d)."
1171 msgstr ""
1172 "Posible corrupción de datos comprimidos: una cadena textual contiene un "
1173 "entero comprimido (opcode %d)."
1174
1175 #: src/data/sys-file-reader.c:2328
1004 #: src/data/sys-file-reader.c:2141
1005 msgid "Possible compressed data corruption: compressed spaces appear in numeric field."
1006 msgstr "Posible corrupción de datos comprimidos: aparecen espacios comprimidos en un campo numérico."
1007
1008 #: src/data/sys-file-reader.c:2195
1009 #, c-format
1010 msgid "Possible compressed data corruption: string contains compressed integer (opcode %d)."
1011 msgstr "Posible corrupción de datos comprimidos: una cadena textual contiene un entero comprimido (opcode %d)."
1012
1013 #: src/data/sys-file-reader.c:2289
11761014 #, c-format
11771015 msgid "Suppressed %d additional related warnings."
11781016 msgstr "Suprimidas %d advertencias adicionales."
11791017
1180 #: src/data/sys-file-reader.c:2374 src/data/sys-file-reader.c:2391
1018 #: src/data/sys-file-reader.c:2335 src/data/sys-file-reader.c:2352
11811019 #, c-format
11821020 msgid "Dictionary record refers to unknown variable %s."
11831021 msgstr "El registro diccionario se refiere a una variable desconocida %s."
11841022
1185 #: src/data/sys-file-reader.c:2453
1023 #: src/data/sys-file-reader.c:2414
11861024 #, c-format
11871025 msgid "Expecting digit at offset %zu in MRSETS record."
11881026 msgstr "Se espera un dígito en la posición %zu de un registro MRSETS."
11891027
1190 #: src/data/sys-file-reader.c:2461
1028 #: src/data/sys-file-reader.c:2422
11911029 #, c-format
11921030 msgid "Expecting space at offset %zu in MRSETS record."
11931031 msgstr "Se espera un espacio en la posición %zu de un registro MRSETS."
11941032
1195 #: src/data/sys-file-reader.c:2469
1033 #: src/data/sys-file-reader.c:2430
11961034 #, c-format
11971035 msgid "%zu-byte string starting at offset %zu exceeds record length %zu."
1198 msgstr ""
1199 "Texto de %zu-bytes que comienza en la posición %zu excede la longitud del "
1200 "registro %zu. "
1201
1202 #: src/data/sys-file-reader.c:2479
1036 msgstr "Texto de %zu-bytes que comienza en la posición %zu excede la longitud del registro %zu. "
1037
1038 #: src/data/sys-file-reader.c:2440
12031039 #, c-format
12041040 msgid "Expecting space at offset %zu following %zu-byte string."
12051041 msgstr "Se espera un espacio en la posición %zu tras un texto de %zu-bytes."
12061042
1207 #: src/data/sys-file-reader.c:2520
1043 #: src/data/sys-file-reader.c:2481
12081044 #, c-format
12091045 msgid "`%s' near offset 0x%llx: "
12101046 msgstr "`%s' cerca de la posición 0x%llx: "
12111047
1212 #: src/data/sys-file-reader.c:2523
1048 #: src/data/sys-file-reader.c:2484
12131049 #, c-format
12141050 msgid "`%s': "
12151051 msgstr "`%s': "
12161052
1217 #: src/data/sys-file-reader.c:2580
1053 #: src/data/sys-file-reader.c:2541
12181054 #, c-format
12191055 msgid "System error: %s."
12201056 msgstr "Error de sistema: %s."
12211057
1222 #: src/data/sys-file-reader.c:2582
1058 #: src/data/sys-file-reader.c:2543
12231059 msgid "Unexpected end of file."
12241060 msgstr "Final de archivo inesperado."
12251061
1226 #: src/data/sys-file-writer.c:188
1062 #: src/data/sys-file-writer.c:186
12271063 #, c-format
12281064 msgid "Unknown system file version %d. Treating as version %d."
1229 msgstr ""
1230 "Versión de archivo de sistema %d desconocida.Se tratará como versión %d."
1231
1232 #: src/data/sys-file-writer.c:1110
1065 msgstr "Versión de archivo de sistema %d desconocida.Se tratará como versión %d."
1066
1067 #: src/data/sys-file-writer.c:1086
12331068 #, c-format
12341069 msgid "An I/O error occurred writing system file `%s'."
12351070 msgstr "Error de E/S al guardar el archivo de sistema `%s'."
12391074 msgid "Truncating variable label for variable `%s' to %d bytes."
12401075 msgstr "Truncando la etiqueta de la variable `%s' a %d bytes."
12411076
1242 #: src/data/variable.c:679 src/language/dictionary/sys-file-info.c:501
1077 #: src/data/variable.c:679 src/language/dictionary/sys-file-info.c:500
12431078 #: src/ui/gui/psppire-var-sheet.c:112
12441079 msgid "Nominal"
12451080 msgstr "Nominal"
12461081
1247 #: src/data/variable.c:682 src/language/dictionary/sys-file-info.c:502
1082 #: src/data/variable.c:682 src/language/dictionary/sys-file-info.c:501
12481083 #: src/ui/gui/psppire-var-sheet.c:113
12491084 msgid "Ordinal"
12501085 msgstr "Ordinal"
12511086
1252 #: src/data/variable.c:685 src/language/dictionary/sys-file-info.c:503
1087 #: src/data/variable.c:685 src/language/dictionary/sys-file-info.c:502
12531088 #: src/language/stats/ks-one-sample.c:327 src/ui/gui/psppire-var-sheet.c:114
12541089 msgid "Scale"
12551090 msgstr "Escala"
12561091
1257 #: src/data/variable.c:761 src/language/dictionary/sys-file-info.c:507
1092 #: src/data/variable.c:761 src/language/dictionary/sys-file-info.c:506
12581093 #: src/ui/gui/psppire-var-sheet.c:105
12591094 msgid "Left"
12601095 msgstr "Izquierda"
12611096
1262 #: src/data/variable.c:764 src/language/dictionary/sys-file-info.c:509
1097 #: src/data/variable.c:764 src/language/dictionary/sys-file-info.c:508
12631098 #: src/ui/gui/psppire-var-sheet.c:106
12641099 msgid "Right"
12651100 msgstr "Derecha"
12661101
1267 #: src/data/variable.c:767 src/language/dictionary/sys-file-info.c:508
1102 #: src/data/variable.c:767 src/language/dictionary/sys-file-info.c:507
12681103 #: src/ui/gui/psppire-var-sheet.c:107
12691104 msgid "Center"
12701105 msgstr "Centro"
12711106
12721107 #: src/language/command.c:196 src/language/expressions/parse.c:1293
1273 #: src/language/utilities/set.q:223
1108 #: src/language/utilities/set.q:220
12741109 #, c-format
12751110 msgid "%s is not yet implemented."
12761111 msgstr "%s aún no está implementado."
12971132 #: src/language/command.c:369
12981133 #, c-format
12991134 msgid "%s is allowed only before the active dataset has been defined."
1300 msgstr ""
1301 "%s sólo se permite antes de que el archivo de datos activo se haya definido."
1135 msgstr "%s sólo se permite antes de que el archivo de datos activo se haya definido."
13021136
13031137 #: src/language/command.c:373
13041138 #, c-format
13051139 msgid "%s is allowed only after the active dataset has been defined."
1306 msgstr ""
1307 "%s sólo se permite después que el archivo de datos activo se haya definido."
1140 msgstr "%s sólo se permite después que el archivo de datos activo se haya definido."
13081141
13091142 #: src/language/command.c:377
13101143 #, c-format
13171150 msgstr "%s sólo se permite dentro de FILE TYPE."
13181151
13191152 #: src/language/command.c:388 src/language/command.c:392
1320 #, fuzzy, c-format
1321 msgid ""
1322 "%s is allowed only before the active dataset has been defined or inside %s."
1323 msgstr ""
1324 "%s sólo se permite antes que el archivo de datos activo se haya definido o "
1325 "dentro de FILE TYPE."
1153 #, c-format
1154 msgid "%s is allowed only before the active dataset has been defined or inside %s."
1155 msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido o dentro de %s."
13261156
13271157 #: src/language/command.c:396 src/language/command.c:400
1328 #, fuzzy, c-format
1329 msgid ""
1330 "%s is allowed only after the active dataset has been defined or inside %s."
1331 msgstr ""
1332 "%s sólo se permite después que el archivo de datos activo se ha definido o "
1333 "dentro de FILE TYPE."
1158 #, c-format
1159 msgid "%s is allowed only after the active dataset has been defined or inside %s."
1160 msgstr "%s sólo se permite después que el archivo de datos activo se ha definido o dentro de %s."
13341161
13351162 #: src/language/command.c:404
13361163 #, c-format
13391166
13401167 #: src/language/command.c:409
13411168 #, c-format
1342 msgid ""
1343 "%s is allowed only after the active dataset has been defined, inside INPUT "
1344 "PROGRAM, or inside FILE TYPE."
1345 msgstr ""
1346 "%s sólo se permite después que el archivo de datos activo se ha definido, "
1347 "dentro de INPUT PROGRAM, o de FILE TYPE."
1169 msgid "%s is allowed only after the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
1170 msgstr "%s sólo se permite después que el archivo de datos activo se ha definido, dentro de INPUT PROGRAM, o de FILE TYPE."
13481171
13491172 #: src/language/command.c:414
13501173 #, c-format
1351 msgid ""
1352 "%s is allowed only before the active dataset has been defined, inside INPUT "
1353 "PROGRAM, or inside FILE TYPE."
1354 msgstr ""
1355 "%s sólo se permite antes que el archivo de datos activo se haya definido, "
1356 "dentro de INPUT PROGRAM, o de FILE TYPE."
1174 msgid "%s is allowed only before the active dataset has been defined, inside INPUT PROGRAM, or inside FILE TYPE."
1175 msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido, dentro de INPUT PROGRAM, o de FILE TYPE."
13571176
13581177 #: src/language/command.c:432 src/language/command.c:435
13591178 #, c-format
13811200 msgstr "esperando %s o %s"
13821201
13831202 #: src/language/lexer/lexer.c:303
1384 #, fuzzy, c-format
1203 #, c-format
13851204 msgid "expecting %s, %s, or %s"
1386 msgstr "esperando %s o %s"
1205 msgstr "se espera %s, %s o %s"
13871206
13881207 #: src/language/lexer/lexer.c:308
1389 #, fuzzy, c-format
1208 #, c-format
13901209 msgid "expecting %s, %s, %s, or %s"
1391 msgstr "esperando %s, %s, o %s tras %s"
1210 msgstr "se espera %s, %s, ,%s, o %s"
13921211
13931212 #: src/language/lexer/lexer.c:313
1394 #, fuzzy, c-format
1213 #, c-format
13951214 msgid "expecting %s, %s, %s, %s, or %s"
1396 msgstr "esperando %s, %s, o %s tras %s"
1215 msgstr "se espera %s, %s, %s, %s, o %s"
13971216
13981217 #: src/language/lexer/lexer.c:318
1399 #, fuzzy, c-format
1218 #, c-format
14001219 msgid "expecting %s, %s, %s, %s, %s, or %s"
1401 msgstr "esperando %s, %s, o %s tras %s"
1220 msgstr "se espera %s, %s, %s, %s, %s, o %s"
14021221
14031222 #: src/language/lexer/lexer.c:324
1404 #, fuzzy, c-format
1223 #, c-format
14051224 msgid "expecting %s, %s, %s, %s, %s, %s, or %s"
1406 msgstr "esperando %s, %s, o %s tras %s"
1225 msgstr "se espera %s, %s, %s, %s, %s, %s, o %s"
14071226
14081227 #: src/language/lexer/lexer.c:330
1409 #, fuzzy, c-format
1228 #, c-format
14101229 msgid "expecting %s, %s, %s, %s, %s, %s, %s, or %s"
1411 msgstr "esperando %s, %s, o %s tras %s"
1230 msgstr "se espera %s, %s, %s, %s, %s, %s, %s, o %s"
14121231
14131232 #: src/language/lexer/lexer.c:350
14141233 #, c-format
14161235 msgstr "Subcomando %s sólo se puede especificar una vez."
14171236
14181237 #: src/language/lexer/lexer.c:362
1419 #, fuzzy, c-format
1238 #, c-format
14201239 msgid "Required subcommand %s was not specified."
1421 msgstr "Subcomando %s sólo se puede especificar una vez."
1240 msgstr "El Subcomando %s requerido no fué especificao."
14221241
14231242 #: src/language/lexer/lexer.c:370
1424 #, fuzzy, c-format
1243 #, c-format
14251244 msgid "%s may only be specified once within subcommand %s"
1426 msgstr "Subcomando %s sólo se puede especificar una vez."
1245 msgstr "%s sólo se puede especificar una vez dentro del subcomando %s"
14271246
14281247 #: src/language/lexer/lexer.c:379
1429 #, fuzzy, c-format
1248 #, c-format
14301249 msgid "Required %s specification missing from %s subcommand"
1431 msgstr "Falta la especificación %s requerida para el subcomando %s."
1250 msgstr "Falta la especificación %s requerida para el subcomando %s"
14321251
14331252 #: src/language/lexer/lexer.c:398
14341253 msgid "Syntax error at end of input"
14351254 msgstr "Error de sintaxis al final de la entrada"
14361255
14371256 #: src/language/lexer/lexer.c:419 src/language/xforms/select-if.c:60
1438 #: src/language/stats/autorecode.c:206 src/language/stats/npar.c:504
1257 #: src/language/stats/autorecode.c:206 src/language/stats/npar.c:478
14391258 #: src/language/data-io/print-space.c:72
14401259 msgid "expecting end of command"
14411260 msgstr "se espera el final de la orden"
14811300
14821301 #: src/language/lexer/lexer.c:1488
14831302 #, c-format
1484 msgid ""
1485 "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 "
1486 "bytes"
1487 msgstr ""
1488 "Cadena Unicode contiene %d bytes, lo que está fuera del rango válido entre 1 "
1489 "y 8 bytes"
1303 msgid "Unicode string contains %d bytes, which is not in the valid range of 1 to 8 bytes"
1304 msgstr "Cadena Unicode contiene %d bytes, lo que está fuera del rango válido entre 1 y 8 bytes"
14901305
14911306 #: src/language/lexer/lexer.c:1494
14921307 #, c-format
15291344 #: src/language/lexer/subcommand-list.c:118
15301345 #, c-format
15311346 msgid "No more than %d %s subcommands allowed."
1532 msgstr ""
1347 msgstr "No se permite más de %d %s subcomandos."
15331348
15341349 #: src/language/lexer/format-parser.c:77
15351350 msgid "expecting valid format specifier"
15481363
15491364 #: src/language/lexer/value-parser.c:65
15501365 #, c-format
1551 msgid ""
1552 "Low end of range (%g) is below high end (%g). The range will be treated as "
1553 "reversed."
1554 msgstr ""
1555 "El límite inferior del intervalo (%g) está por debajo del límite superior "
1556 "(%g). El intervalo será invertido."
1366 msgid "Low end of range (%g) is below high end (%g). The range will be treated as reversed."
1367 msgstr "El límite inferior del intervalo (%g) está por debajo del límite superior (%g). El intervalo será invertido."
15571368
15581369 #: src/language/lexer/value-parser.c:73
15591370 #, c-format
15831394
15841395 #: src/language/lexer/variable-parser.c:180
15851396 #, c-format
1586 msgid ""
1587 "%s is not a numeric variable. It will not be included in the variable list."
1588 msgstr ""
1589 "%s no es una variable numérica. No será incluida en la lista de variables."
1397 msgid "%s is not a numeric variable. It will not be included in the variable list."
1398 msgstr "%s no es una variable numérica. No será incluida en la lista de variables."
15901399
15911400 #: src/language/lexer/variable-parser.c:183
15921401 #, c-format
1593 msgid ""
1594 "%s is not a string variable. It will not be included in the variable list."
1595 msgstr ""
1596 "%s no es una variable de cadena. No será incluida en la lista de variables."
1402 msgid "%s is not a string variable. It will not be included in the variable list."
1403 msgstr "%s no es una variable de cadena. No será incluida en la lista de variables."
15971404
15981405 #: src/language/lexer/variable-parser.c:187
15991406 #, c-format
16021409
16031410 #: src/language/lexer/variable-parser.c:191
16041411 #, c-format
1605 msgid ""
1606 "%s and %s are not the same type. All variables in this variable list must "
1607 "be of the same type. %s will be omitted from the list."
1608 msgstr ""
1609 "%s y %s no son del mismo tipo. Todas las variables de esta lista tienen que "
1610 "ser del mismo tipo. %s será omitida de la lista."
1412 msgid "%s and %s are not the same type. All variables in this variable list must be of the same type. %s will be omitted from the list."
1413 msgstr "%s y %s no son del mismo tipo. Todas las variables de esta lista tienen que ser del mismo tipo. %s será omitida de la lista."
16111414
16121415 #: src/language/lexer/variable-parser.c:197
16131416 #, c-format
1614 msgid ""
1615 "%s and %s are string variables with different widths. All variables in this "
1616 "variable list must have the same width. %s will be omitted from the list."
1617 msgstr ""
1618 "%s y %s son variables de cadena con tamaños diferentes. Todas las variables "
1619 "de esta lista deben tener el mismo tamaño. %s será omitida de la lista."
1417 msgid "%s and %s are string variables with different widths. All variables in this variable list must have the same width. %s will be omitted from the list."
1418 msgstr "%s y %s son variables de cadena con tamaños diferentes. Todas las variables de esta lista deben tener el mismo tamaño. %s será omitida de la lista."
16201419
16211420 #: src/language/lexer/variable-parser.c:202
16221421 #: src/language/lexer/variable-parser.c:404
16271426 #: src/language/lexer/variable-parser.c:315
16281427 #, c-format
16291428 msgid "%s TO %s is not valid syntax since %s precedes %s in the dictionary."
1630 msgstr ""
1631 "%s TO %s no es una sintaxis válida debido a que %s precede %s en el "
1632 "diccionario."
1429 msgstr "%s TO %s no es una sintaxis válida debido a que %s precede %s en el diccionario."
16331430
16341431 #: src/language/lexer/variable-parser.c:323
16351432 #, c-format
1636 msgid ""
1637 "When using the TO keyword to specify several variables, both variables must "
1638 "be from the same variable dictionaries, of either ordinary, scratch, or "
1639 "system variables. %s is a %s variable, whereas %s is %s."
1640 msgstr ""
1641 "Cuando se utiliza la palabra clave TO para especificar diversas variables, "
1642 "ambas tienen que ser del mismo diccionario de variables, ya sean ordinales, "
1643 "scratch, o variables de sistema. %s es una variable %s, debido a que %s es "
1644 "%s."
1433 msgid "When using the TO keyword to specify several variables, both variables must be from the same variable dictionaries, of either ordinary, scratch, or system variables. %s is a %s variable, whereas %s is %s."
1434 msgstr "Cuando se utiliza la palabra clave TO para especificar diversas variables, ambas tienen que ser del mismo diccionario de variables, ya sean ordinales, scratch, o variables de sistema. %s es una variable %s, debido a que %s es %s."
16451435
16461436 #: src/language/lexer/variable-parser.c:381
16471437 #, c-format
16671457
16681458 #: src/language/xforms/compute.c:149 src/language/xforms/compute.c:204
16691459 #, c-format
1670 msgid ""
1671 "When executing COMPUTE: SYSMIS is not a valid value as an index into vector "
1672 "%s."
1673 msgstr ""
1674 "Cuando se ejecuta COMPUTE: SYSMIS no es un valor válido como índice en el "
1675 "vector %s."
1460 msgid "When executing COMPUTE: SYSMIS is not a valid value as an index into vector %s."
1461 msgstr "Cuando se ejecuta COMPUTE: SYSMIS no es un valor válido como índice en el vector %s."
16761462
16771463 #: src/language/xforms/compute.c:153 src/language/xforms/compute.c:211
16781464 #, c-format
1679 msgid ""
1680 "When executing COMPUTE: %g is not a valid value as an index into vector %s."
1681 msgstr ""
1682 "Cuando se ejecuta COMPUTE: %g no es un valor válid como índice en el vector "
1683 "%s."
1465 msgid "When executing COMPUTE: %g is not a valid value as an index into vector %s."
1466 msgstr "Cuando se ejecuta COMPUTE: %g no es un valor válid como índice en el vector %s."
16841467
16851468 #: src/language/xforms/compute.c:355
16861469 #, c-format
16981481 #: src/language/xforms/sample.c:96
16991482 #, c-format
17001483 msgid "Cannot sample %d observations from a population of %d."
1701 msgstr ""
1702 "No se puede hacer una muestra de %d observaciones de una población de %d."
1484 msgstr "No se puede hacer una muestra de %d observaciones de una población de %d."
17031485
17041486 #: src/language/xforms/recode.c:255
1705 msgid ""
1706 "Inconsistent target variable types. Target variables must be all numeric or "
1707 "all string."
1708 msgstr ""
1709 "Tipo inconsistente de variables objetivo. Las variables objetivo tienen que "
1710 "ser todas, o bien de cadena o bien numéricas."
1487 msgid "Inconsistent target variable types. Target variables must be all numeric or all string."
1488 msgstr "Tipo inconsistente de variables objetivo. Las variables objetivo tienen que ser todas, o bien de cadena o bien numéricas."
17111489
17121490 #: src/language/xforms/recode.c:276
17131491 msgid "CONVERT requires string input values and numeric output values."
1714 msgstr ""
1715 "CONVERT requiere valores de entrada de cadena y valores de salida numéricos."
1492 msgstr "CONVERT requiere valores de entrada de cadena y valores de salida numéricos."
17161493
17171494 #: src/language/xforms/recode.c:333
17181495 msgid "THRU is not allowed with string variables."
17241501
17251502 #: src/language/xforms/recode.c:473
17261503 #, c-format
1727 msgid ""
1728 "%zu variable(s) cannot be recoded into %zu variable(s). Specify the same "
1729 "number of variables as source and target variables."
1730 msgstr ""
1731 "%zu variable(s) no pueden ser recodificadas en %zu variable(s). Especifique "
1732 "el mismo número de variables como origen y destino."
1504 msgid "%zu variable(s) cannot be recoded into %zu variable(s). Specify the same number of variables as source and target variables."
1505 msgstr "%zu variable(s) no pueden ser recodificadas en %zu variable(s). Especifique el mismo número de variables como origen y destino."
17331506
17341507 #: src/language/xforms/recode.c:488
17351508 #, c-format
1736 msgid ""
1737 "There is no variable named %s. (All string variables specified on INTO must "
1738 "already exist. Use the STRING command to create a string variable.)"
1739 msgstr ""
1740 "No existe ninguna variable llamada %s. (Todas las variables de cadena "
1741 "especificadas en INTO tienen que existir. Utilice el comando STRING para "
1742 "crear una variable de cadena.)"
1509 msgid "There is no variable named %s. (All string variables specified on INTO must already exist. Use the STRING command to create a string variable.)"
1510 msgstr "No existe ninguna variable llamada %s. (Todas las variables de cadena especificadas en INTO tienen que existir. Utilice el comando STRING para crear una variable de cadena.)"
17431511
17441512 #: src/language/xforms/recode.c:504
17451513 #, c-format
17531521
17541522 #: src/language/xforms/select-if.c:100
17551523 msgid "Syntax error expecting OFF or BY. Turning off case filtering."
1756 msgstr ""
1757 "Error de sintaxis esperando OFF o BY. Desactivando el filtraje de casos."
1524 msgstr "Error de sintaxis esperando OFF o BY. Desactivando el filtraje de casos."
17581525
17591526 #: src/language/xforms/select-if.c:115
17601527 msgid "The filter variable must be numeric."
17721539 #: src/language/control/control-stack.c:59
17731540 #, c-format
17741541 msgid "This command must appear inside %s...%s, without intermediate %s...%s."
1775 msgstr ""
1776 "Esta orden tiene que aparecer dentro de %s...%s, sin intermediarios %s...%s."
1542 msgstr "Esta orden tiene que aparecer dentro de %s...%s, sin intermediarios %s...%s."
17771543
17781544 #: src/language/control/control-stack.c:76
17791545 #, c-format
17911557 #: src/language/control/repeat.c:116
17921558 #, c-format
17931559 msgid "Dummy variable name `%s' hides dictionary variable `%s'."
1794 msgstr ""
1795 "El nombre de la variable ficticia `%s' oculta la variable de diccionario `"
1796 "%s'."
1560 msgstr "El nombre de la variable ficticia `%s' oculta la variable de diccionario `%s'."
17971561
17981562 #: src/language/control/repeat.c:120
17991563 #, c-format
18021566
18031567 #: src/language/control/repeat.c:163
18041568 #, c-format
1805 msgid ""
1806 "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were "
1807 "specified."
1808 msgstr ""
1809 "La variable ficticia `%s' tiene %zu substituciones, así que `%s' también "
1810 "tendría que tenerlas, pero se especificaron %zu."
1569 msgid "Dummy variable `%s' had %zu substitutions, so `%s' must also, but %zu were specified."
1570 msgstr "La variable ficticia `%s' tiene %zu substituciones, así que `%s' también tendría que tenerlas, pero se especificaron %zu."
18111571
18121572 #: src/language/control/repeat.c:377
18131573 msgid "Ranges may only have integer bounds."
18231583 msgstr "DO REPEAT no coincide."
18241584
18251585 #: src/language/control/temporary.c:45
1826 msgid ""
1827 "This command may only appear once between procedures and procedure-like "
1828 "commands."
1829 msgstr ""
1830 "Esta orden únicamente puede aparecer una vez entre las órdenes de "
1831 "procedimientos y casi-procedimientos."
1586 msgid "This command may only appear once between procedures and procedure-like commands."
1587 msgstr "Esta orden únicamente puede aparecer una vez entre las órdenes de procedimientos y casi-procedimientos."
18321588
18331589 #: src/language/dictionary/attributes.c:104
18341590 msgid "Attribute array index must be between 1 and 65535."
18371593 #: src/language/dictionary/apply-dictionary.c:74
18381594 #, c-format
18391595 msgid "Variable %s is %s in target file, but %s in source file."
1840 msgstr ""
1841 "La variable %s es %s en el archivo de destino, pero %s en el archivo de "
1842 "origen."
1596 msgstr "La variable %s es %s en el archivo de destino, pero %s en el archivo de origen."
18431597
18441598 #: src/language/dictionary/apply-dictionary.c:110
18451599 msgid "No matching variables found between the source and target files."
1846 msgstr ""
1847 "No se han encontrado coincidencias de variables entre los archivos de origen "
1848 "y de destino."
1600 msgstr "No se han encontrado coincidencias de variables entre los archivos de origen y de destino."
18491601
18501602 #: src/language/dictionary/delete-variables.c:40
1851 msgid ""
1852 "DELETE VARIABLES may not be used after TEMPORARY. Temporary transformations "
1853 "will be made permanent."
1854 msgstr ""
1855 "DELETE VARIABLES no puede ser utilizado después de TEMPORARY. Las "
1856 "transformaciones temporales serán permanentes."
1603 msgid "DELETE VARIABLES may not be used after TEMPORARY. Temporary transformations will be made permanent."
1604 msgstr "DELETE VARIABLES no puede ser utilizado después de TEMPORARY. Las transformaciones temporales serán permanentes."
18571605
18581606 #: src/language/dictionary/delete-variables.c:47
1859 msgid ""
1860 "DELETE VARIABLES may not be used to delete all variables from the active "
1861 "dataset dictionary. Use NEW FILE instead."
1862 msgstr ""
1863 "DELETE VARIABLES no puede ser utilizado para borrar todas las variables del "
1864 "archivo de datos de diccionario activo. Utilizar NEW FILE en su lugar."
1607 msgid "DELETE VARIABLES may not be used to delete all variables from the active dataset dictionary. Use NEW FILE instead."
1608 msgstr "DELETE VARIABLES no puede ser utilizado para borrar todas las variables del archivo de datos de diccionario activo. Utilizar NEW FILE en su lugar."
18651609
18661610 #: src/language/dictionary/missing-values.c:70
18671611 #, c-format
1868 msgid ""
1869 "Cannot mix numeric variables (e.g. %s) and string variables (e.g. %s) within "
1870 "a single list."
1871 msgstr ""
1872 "No se pueden mezclar las variables numéricas (e.g. %s) y las variables de "
1873 "cadena (e.g. %s) dentro de una lista única."
1612 msgid "Cannot mix numeric variables (e.g. %s) and string variables (e.g. %s) within a single list."
1613 msgstr "No se pueden mezclar las variables numéricas (e.g. %s) y las variables de cadena (e.g. %s) dentro de una lista única."
18741614
18751615 #: src/language/dictionary/missing-values.c:119
18761616 #, c-format
18801620 #: src/language/dictionary/missing-values.c:142
18811621 #, c-format
18821622 msgid "Missing values provided are too long to assign to variable of width %d."
1883 msgstr ""
1884 "Los valores perdidos proporcionados son demasiado largos para asignar a una "
1885 "variable de ancho %d."
1623 msgstr "Los valores perdidos proporcionados son demasiado largos para asignar a una variable de ancho %d."
18861624
18871625 #: src/language/dictionary/modify-variables.c:91
1888 msgid ""
1889 "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will "
1890 "be made permanent."
1891 msgstr ""
1892 "MODIFY VARS no puede ser utilizado después de TEMPORARY. Las "
1893 "transformaciones temporales serán permanentes."
1626 msgid "MODIFY VARS may not be used after TEMPORARY. Temporary transformations will be made permanent."
1627 msgstr "MODIFY VARS no puede ser utilizado después de TEMPORARY. Las transformaciones temporales serán permanentes."
18941628
18951629 #: src/language/dictionary/modify-variables.c:136
18961630 msgid "Cannot specify ALL after specifying a set of variables."
1897 msgstr ""
1898 "No se puede especificar ALL después de la especificación de un conjunto de "
1899 "variables."
1631 msgstr "No se puede especificar ALL después de la especificación de un conjunto de variables."
19001632
19011633 #: src/language/dictionary/modify-variables.c:206
19021634 #: src/language/dictionary/rename-variables.c:71
19031635 #, c-format
1904 msgid ""
1905 "Differing number of variables in old name list (%zu) and in new name list "
1906 "(%zu)."
1907 msgstr ""
1908 "Diferente número de variables en la lista de nombres antigua (%zu) y en la "
1909 "lista de nombres nueva (%zu)."
1636 msgid "Differing number of variables in old name list (%zu) and in new name list (%zu)."
1637 msgstr "Diferente número de variables en la lista de nombres antigua (%zu) y en la lista de nombres nueva (%zu)."
19101638
19111639 #: src/language/dictionary/modify-variables.c:231
1912 msgid ""
1913 "KEEP subcommand may be given at most once. It may not be given in "
1914 "conjunction with the DROP subcommand."
1915 msgstr ""
1916 "El subcomando KEEP puede ser emitido más de una vez. Puede ser que no sea "
1917 "facilitado en relación con el subcomando DROP."
1640 msgid "KEEP subcommand may be given at most once. It may not be given in conjunction with the DROP subcommand."
1641 msgstr "El subcomando KEEP puede ser emitido más de una vez. Puede ser que no sea facilitado en relación con el subcomando DROP."
19181642
19191643 #: src/language/dictionary/modify-variables.c:274
1920 msgid ""
1921 "DROP subcommand may be given at most once. It may not be given in "
1922 "conjunction with the KEEP subcommand."
1923 msgstr ""
1924 "El subcomando DROP puede ser utilizado únicamente una vez. No puede ser "
1925 "utilizado juntamente con el subcomando KEEP."
1644 msgid "DROP subcommand may be given at most once. It may not be given in conjunction with the KEEP subcommand."
1645 msgstr "El subcomando DROP puede ser utilizado únicamente una vez. No puede ser utilizado juntamente con el subcomando KEEP."
19261646
19271647 #: src/language/dictionary/modify-variables.c:300
19281648 #, c-format
19351655
19361656 #: src/language/dictionary/mrsets.c:116
19371657 #, c-format
1938 msgid ""
1939 "VARIABLES specified only variable %s on %s, but at least two variables are "
1940 "required."
1941 msgstr ""
1942 "VARIABLES especifica sólo la variable %s en %s, pero se requieren al menos "
1943 "dos variables."
1658 msgid "VARIABLES specified only variable %s on %s, but at least two variables are required."
1659 msgstr "VARIABLES especifica sólo la variable %s en %s, pero se requieren al menos dos variables."
19441660
19451661 #: src/language/dictionary/mrsets.c:149
19461662 msgid "Numeric VALUE must be an integer."
19481664
19491665 #: src/language/dictionary/mrsets.c:229 src/language/dictionary/mrsets.c:267
19501666 #, c-format
1951 msgid ""
1952 "MDGROUP subcommand for group %s specifies a string VALUE, but the variables "
1953 "specified for this group are numeric."
1954 msgstr ""
1955 "El subcomando MDGROUPS para el grupo %s especifica un VALUE textual, pero "
1956 "las variables especificadas por este grupo son numéricas."
1667 msgid "MDGROUP subcommand for group %s specifies a string VALUE, but the variables specified for this group are numeric."
1668 msgstr "El subcomando MDGROUPS para el grupo %s especifica un VALUE textual, pero las variables especificadas por este grupo son numéricas."
19571669
19581670 #: src/language/dictionary/mrsets.c:253
19591671 #, c-format
1960 msgid ""
1961 "VALUE string on MDGROUP subcommand for group %s is %d bytes long, but it "
1962 "must be no longer than the narrowest variable in the group, which is %s with "
1963 "a width of %d bytes."
1964 msgstr ""
1965 "El VALUE textual del subcomando MDGROUP para el grupo %s tiene %d bytes, "
1966 "pero no puede ser más largo que la variable más corta del grupo, que es %s "
1967 "con longitud %d bytes."
1672 msgid "VALUE string on MDGROUP subcommand for group %s is %d bytes long, but it must be no longer than the narrowest variable in the group, which is %s with a width of %d bytes."
1673 msgstr "El VALUE textual del subcomando MDGROUP para el grupo %s tiene %d bytes, pero no puede ser más largo que la variable más corta del grupo, que es %s con longitud %d bytes."
19681674
19691675 #: src/language/dictionary/mrsets.c:279
19701676 #, c-format
1971 msgid ""
1972 "MDGROUP subcommand for group %s specifies LABELSOURCE=VARLABEL but not "
1973 "CATEGORYLABELS=COUNTEDVALUES. Ignoring LABELSOURCE."
1974 msgstr ""
1975 "El subcomando MDGROUP para el grupo %s espeficifica LABELSOURCE=VARLABEL "
1976 "pero no CATEGORYLABELS=COUNTEDVALUES. Se ignorará LABELSOURCE."
1677 msgid "MDGROUP subcommand for group %s specifies LABELSOURCE=VARLABEL but not CATEGORYLABELS=COUNTEDVALUES. Ignoring LABELSOURCE."
1678 msgstr "El subcomando MDGROUP para el grupo %s espeficifica LABELSOURCE=VARLABEL pero no CATEGORYLABELS=COUNTEDVALUES. Se ignorará LABELSOURCE."
19771679
19781680 #: src/language/dictionary/mrsets.c:285
19791681 #, c-format
1980 msgid ""
1981 "MDGROUP subcommand for group %s specifies both LABEL and LABELSOURCE, but "
1982 "only one of these subcommands may be used at a time. Ignoring LABELSOURCE."
1983 msgstr ""
1984 "El subcomando MDGROUP para el grupo %s espeficifica LABEL i LABELSOURCE, "
1985 "pero sólo uno de estos subcomandos puede ser utilitzado a la vez. Se "
1986 "ignorará LABELSOURCE."
1682 msgid "MDGROUP subcommand for group %s specifies both LABEL and LABELSOURCE, but only one of these subcommands may be used at a time. Ignoring LABELSOURCE."
1683 msgstr "El subcomando MDGROUP para el grupo %s espeficifica LABEL i LABELSOURCE, pero sólo uno de estos subcomandos puede ser utilitzado a la vez. Se ignorará LABELSOURCE."
19871684
19881685 #: src/language/dictionary/mrsets.c:325
19891686 #, c-format
1990 msgid ""
1991 "Variables %s and %s specified as part of multiple dichotomy group %s have "
1992 "the same variable label. Categories represented by these variables will not "
1993 "be distinguishable in output."
1994 msgstr ""
1995 "Las variables %s y %s especificadas como parte del grupo dicotomico múltiple "
1996 "%s tienen la misma etiqueta de variable. Las categorias representadas por "
1997 "estas variables no seran distingibles en los resultados."
1687 msgid "Variables %s and %s specified as part of multiple dichotomy group %s have the same variable label. Categories represented by these variables will not be distinguishable in output."
1688 msgstr "Las variables %s y %s especificadas como parte del grupo dicotomico múltiple %s tienen la misma etiqueta de variable. Las categorias representadas por estas variables no seran distingibles en los resultados."
19981689
19991690 #: src/language/dictionary/mrsets.c:355
20001691 #, c-format
2001 msgid ""
2002 "Variable %s specified as part of multiple dichotomy group %s (which has "
2003 "CATEGORYLABELS=COUNTEDVALUES) has no value label for its counted value. "
2004 "This category will not be distinguishable in output."
2005 msgstr ""
2006 "La variable %s especificada como parte del grupe dicotomico múltiple %s (que "
2007 "tiene CATEGORYLABELS=COUNTEDVALUES) no tiene etiqueta de valor para su valor "
2008 "de recuento. Esta categoria no será distingible en los resultados."
1692 msgid "Variable %s specified as part of multiple dichotomy group %s (which has CATEGORYLABELS=COUNTEDVALUES) has no value label for its counted value. This category will not be distinguishable in output."
1693 msgstr "La variable %s especificada como parte del grupe dicotomico múltiple %s (que tiene CATEGORYLABELS=COUNTEDVALUES) no tiene etiqueta de valor para su valor de recuento. Esta categoria no será distingible en los resultados."
20091694
20101695 #: src/language/dictionary/mrsets.c:368
20111696 #, c-format
2012 msgid ""
2013 "Variables %s and %s specified as part of multiple dichotomy group %s (which "
2014 "has CATEGORYLABELS=COUNTEDVALUES) have the same value label for the the "
2015 "group's counted value. These categories will not be distinguishable in "
2016 "output."
2017 msgstr ""
2018 "Las variables %s y %s especificadas como parte del grupo dicotomico múltiple "
2019 "%s (que tiene CATEGORYLABELS=COUNTEDVALUES) no tiene etiqueta de valor para "
2020 "su valor de recuento. Esta categoria no será distingible en los resultados."
1697 msgid "Variables %s and %s specified as part of multiple dichotomy group %s (which has CATEGORYLABELS=COUNTEDVALUES) have the same value label for the the group's counted value. These categories will not be distinguishable in output."
1698 msgstr "Las variables %s y %s especificadas como parte del grupo dicotomico múltiple %s (que tiene CATEGORYLABELS=COUNTEDVALUES) no tiene etiqueta de valor para su valor de recuento. Esta categoria no será distingible en los resultados."
20211699
20221700 #: src/language/dictionary/mrsets.c:425
20231701 #, c-format
2024 msgid ""
2025 "Variables specified on MCGROUP should have the same categories, but %s and "
2026 "%s (and possibly others) in multiple category group %s have different value "
2027 "labels for value %s."
2028 msgstr ""
2029 "La variables especificadas en MDGROUP deben tener las mismas categorias, "
2030 "pero %s y %s (y posiblemente otras) del grupo de caterorias múltiples %s "
2031 "tiene diferentes etiquetas de valores para el valor %s."
1702 msgid "Variables specified on MCGROUP should have the same categories, but %s and %s (and possibly others) in multiple category group %s have different value labels for value %s."
1703 msgstr "La variables especificadas en MDGROUP deben tener las mismas categorias, pero %s y %s (y posiblemente otras) del grupo de caterorias múltiples %s tiene diferentes etiquetas de valores para el valor %s."
20321704
20331705 #: src/language/dictionary/mrsets.c:483
20341706 #, c-format
20361708 msgstr "Ningún conjunto multirespuesta llamado %s."
20371709
20381710 #: src/language/dictionary/mrsets.c:537
2039 msgid ""
2040 "The active dataset dictionary does not contain any multiple response sets."
2041 msgstr ""
2042 "El diccionario del fichero de datos activo no contiene ningún conjunto de "
2043 "multi-respuesta. "
1711 msgid "The active dataset dictionary does not contain any multiple response sets."
1712 msgstr "El diccionario del fichero de datos activo no contiene ningún conjunto de multi-respuesta. "
20441713
20451714 #: src/language/dictionary/mrsets.c:547
20461715 msgid "Multiple Response Sets"
20691738
20701739 #: src/language/dictionary/mrsets.c:567
20711740 #: src/language/dictionary/split-file.c:84
2072 #: src/language/dictionary/sys-file-info.c:336
2073 #: src/language/dictionary/sys-file-info.c:575
1741 #: src/language/dictionary/sys-file-info.c:335
1742 #: src/language/dictionary/sys-file-info.c:574
20741743 #: src/ui/gui/psppire-var-sheet.c:535 src/ui/gui/psppire-var-store.c:772
20751744 #: src/ui/gui/compute.ui:467
20761745 msgid "Label"
21201789 msgstr "El tipo de formato %s no puede utilizarse con variable de cadena."
21211790
21221791 #: src/language/dictionary/rename-variables.c:48
2123 msgid ""
2124 "RENAME VARS may not be used after TEMPORARY. Temporary transformations will "
2125 "be made permanent."
2126 msgstr ""
2127 "RENAME VARS no puede ser utilizado después de TEMPORARY. Las "
2128 "transformaciones temporales serán permanentes."
1792 msgid "RENAME VARS may not be used after TEMPORARY. Temporary transformations will be made permanent."
1793 msgstr "RENAME VARS no puede ser utilizado después de TEMPORARY. Las transformaciones temporales serán permanentes."
21291794
21301795 #: src/language/dictionary/rename-variables.c:89
21311796 #, c-format
21331798 msgstr "Cambiar el nombre duplicaría el nombre de la variable %s."
21341799
21351800 #: src/language/dictionary/split-file.c:83
2136 #: src/language/dictionary/sys-file-info.c:421
2137 #: src/language/dictionary/sys-file-info.c:574
2138 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:759
2139 #: src/language/stats/reliability.c:770 src/language/stats/crosstabs.q:1233
1801 #: src/language/dictionary/sys-file-info.c:420
1802 #: src/language/dictionary/sys-file-info.c:573
1803 #: src/language/stats/cochran.c:170 src/language/stats/reliability.c:753
1804 #: src/language/stats/reliability.c:764 src/language/stats/crosstabs.q:1233
21401805 #: src/language/stats/crosstabs.q:1260 src/language/stats/crosstabs.q:1283
21411806 #: src/language/stats/crosstabs.q:1308 src/language/stats/examine.q:1840
21421807 #: src/language/stats/frequencies.q:821 src/ui/gui/count.ui:244
22491914 msgstr "Conjunto de carácteres:"
22501915
22511916 #: src/language/dictionary/sys-file-info.c:149
2252 #: src/language/dictionary/sys-file-info.c:336
1917 #: src/language/dictionary/sys-file-info.c:335
22531918 msgid "Description"
22541919 msgstr "Descripción"
22551920
22561921 #: src/language/dictionary/sys-file-info.c:150
2257 #: src/language/dictionary/sys-file-info.c:338
2258 #: src/language/dictionary/sys-file-info.c:645
1922 #: src/language/dictionary/sys-file-info.c:337
1923 #: src/language/dictionary/sys-file-info.c:644
22591924 msgid "Position"
22601925 msgstr "Posición"
22611926
2262 #: src/language/dictionary/sys-file-info.c:198
1927 #: src/language/dictionary/sys-file-info.c:197
22631928 msgid "The active dataset does not have a file label."
22641929 msgstr "El archivo de datos activo no tiene etiqueta de archivo."
22651930
2266 #: src/language/dictionary/sys-file-info.c:200
1931 #: src/language/dictionary/sys-file-info.c:199
22671932 #, c-format
22681933 msgid "File label: %s"
22691934 msgstr "Etiqueta de archivo: %s"
22701935
2271 #: src/language/dictionary/sys-file-info.c:274
1936 #: src/language/dictionary/sys-file-info.c:273
22721937 msgid "No variables to display."
22731938 msgstr "Ninguna variable para mostrar."
22741939
2275 #: src/language/dictionary/sys-file-info.c:288
1940 #: src/language/dictionary/sys-file-info.c:287
22761941 msgid "Macros not supported."
22771942 msgstr "Macros no disponibles."
22781943
2279 #: src/language/dictionary/sys-file-info.c:297
1944 #: src/language/dictionary/sys-file-info.c:296
22801945 msgid "The active dataset dictionary does not contain any documents."
2281 msgstr ""
2282 "El diccionario del archivo de datos activo no contiene ningún documento."
2283
2284 #: src/language/dictionary/sys-file-info.c:304
1946 msgstr "El diccionario del archivo de datos activo no contiene ningún documento."
1947
1948 #: src/language/dictionary/sys-file-info.c:303
22851949 msgid "Documents in the active dataset:"
22861950 msgstr "Documentos en el archivo de datos activo:"
22871951
2288 #: src/language/dictionary/sys-file-info.c:420
1952 #: src/language/dictionary/sys-file-info.c:419
22891953 msgid "Attribute"
22901954 msgstr "Atributo"
22911955
2292 #: src/language/dictionary/sys-file-info.c:476
1956 #: src/language/dictionary/sys-file-info.c:475
22931957 #, c-format
22941958 msgid "Format: %s"
22951959 msgstr "Formato: %s"
22961960
2297 #: src/language/dictionary/sys-file-info.c:483
1961 #: src/language/dictionary/sys-file-info.c:482
22981962 #, c-format
22991963 msgid "Print Format: %s"
23001964 msgstr "Formato de Impresión: %s"
23011965
2302 #: src/language/dictionary/sys-file-info.c:487
1966 #: src/language/dictionary/sys-file-info.c:486
23031967 #, c-format
23041968 msgid "Write Format: %s"
23051969 msgstr "Formato de Escritura: %s"
23061970
2307 #: src/language/dictionary/sys-file-info.c:500
1971 #: src/language/dictionary/sys-file-info.c:499
23081972 #, c-format
23091973 msgid "Measure: %s"
23101974 msgstr "Medida: %s"
23111975
2312 #: src/language/dictionary/sys-file-info.c:506
1976 #: src/language/dictionary/sys-file-info.c:505
23131977 #, c-format
23141978 msgid "Display Alignment: %s"
23151979 msgstr "Alineación de la muestra: %s"
23161980
2317 #: src/language/dictionary/sys-file-info.c:512
1981 #: src/language/dictionary/sys-file-info.c:511
23181982 #, c-format
23191983 msgid "Display Width: %d"
23201984 msgstr "Ancho de la muestra: %d"
23211985
2322 #: src/language/dictionary/sys-file-info.c:526
1986 #: src/language/dictionary/sys-file-info.c:525
23231987 msgid "Missing Values: "
23241988 msgstr "Valores perdidos: "
23251989
2326 #: src/language/dictionary/sys-file-info.c:625
1990 #: src/language/dictionary/sys-file-info.c:624
23271991 msgid "No vectors defined."
23281992 msgstr "Vectores no definidos."
23291993
2330 #: src/language/dictionary/sys-file-info.c:644
1994 #: src/language/dictionary/sys-file-info.c:643
23311995 msgid "Vector"
23321996 msgstr "Vector"
23331997
2334 #: src/language/dictionary/sys-file-info.c:647
1998 #: src/language/dictionary/sys-file-info.c:646
23351999 msgid "Print Format"
23362000 msgstr "Formato de Impresión"
23372001
23522016
23532017 #: src/language/dictionary/vector.c:97
23542018 msgid "A slash must separate each vector specification in VECTOR's long form."
2355 msgstr ""
2356 "Una barra debe separar cada especificación de vector en la forma larga de "
2357 "VECTOR."
2019 msgstr "Una barra debe separar cada especificación de vector en la forma larga de VECTOR."
23582020
23592021 #: src/language/dictionary/vector.c:130
23602022 msgid "Vectors must have at least one element."
24202082 #: src/language/utilities/include.c:71
24212083 #, c-format
24222084 msgid "Can't find `%s' in include file search path."
2423 msgstr ""
2424 "No se puede encontrar `%s' en la ruta de búsqueda del archivo de inclusión."
2085 msgstr "No se puede encontrar `%s' en la ruta de búsqueda del archivo de inclusión."
24252086
24262087 #: src/language/utilities/permissions.c:114
24272088 #, c-format
25152176 msgstr "Último valor no-perdido"
25162177
25172178 #: src/language/stats/aggregate.c:257
2518 msgid ""
2519 "When PRESORTED is specified, specifying sorting directions with (A) or (D) "
2520 "has no effect. Output data will be sorted the same way as the input data."
2521 msgstr ""
2522 "Cuando se especifica PRESORTED, dar directivas de ordenación con (A) o (D) "
2523 "no tiene efecto. Los datos de salida serán ordenados de la misma manera que "
2524 "los de entrada."
2179 msgid "When PRESORTED is specified, specifying sorting directions with (A) or (D) has no effect. Output data will be sorted the same way as the input data."
2180 msgstr "Cuando se especifica PRESORTED, dar directivas de ordenación con (A) o (D) no tiene efecto. Los datos de salida serán ordenados de la misma manera que los de entrada."
25252181
25262182 #: src/language/stats/aggregate.c:447
25272183 msgid "expecting aggregation function"
25402196 #: src/language/stats/aggregate.c:522
25412197 #, c-format
25422198 msgid "Arguments to %s must be of same type as source variables."
2543 msgstr ""
2544 "Los argumentos para %s deben ser del mismo tipo que las variables de origen."
2199 msgstr "Los argumentos para %s deben ser del mismo tipo que las variables de origen."
25452200
25462201 #: src/language/stats/aggregate.c:541
25472202 #, c-format
2548 msgid ""
2549 "Number of source variables (%zu) does not match number of target variables "
2550 "(%zu)."
2551 msgstr ""
2552 "Número de variables de origen (%zu) no coincide con el número de variables "
2553 "de destino (%zu)."
2203 msgid "Number of source variables (%zu) does not match number of target variables (%zu)."
2204 msgstr "Número de variables de origen (%zu) no coincide con el número de variables de destino (%zu)."
25542205
25552206 #: src/language/stats/aggregate.c:557
25562207 #, c-format
2557 msgid ""
2558 "The value arguments passed to the %s function are out-of-order. They will "
2559 "be treated as if they had been specified in the correct order."
2560 msgstr ""
2561 "El valor de los argumentos pasados en la función %s están fuera de orden. "
2562 "Serán tratatos como si hubieran sido especificados en el orden correcto."
2208 msgid "The value arguments passed to the %s function are out-of-order. They will be treated as if they had been specified in the correct order."
2209 msgstr "El valor de los argumentos pasados en la función %s están fuera de orden. Serán tratatos como si hubieran sido especificados en el orden correcto."
25632210
25642211 #: src/language/stats/aggregate.c:631
25652212 #, c-format
2566 msgid ""
2567 "Variable name %s is not unique within the aggregate file dictionary, which "
2568 "contains the aggregate variables and the break variables."
2569 msgstr ""
2570 "El nombre de variable %s no es único dentro del archivo de diccionario "
2571 "agregado, que contiene las variables agregadas y las variables de corte."
2213 msgid "Variable name %s is not unique within the aggregate file dictionary, which contains the aggregate variables and the break variables."
2214 msgstr "El nombre de variable %s no es único dentro del archivo de diccionario agregado, que contiene las variables agregadas y las variables de corte."
25722215
25732216 #: src/language/stats/autorecode.c:156
25742217 #, c-format
25752218 msgid "Source variable count (%zu) does not match target variable count (%zu)."
2576 msgstr ""
2577 "El recuento de la variable de origen (%zu) no coincide con el recuento de la "
2578 "variable de destino (%zu)."
2219 msgstr "El recuento de la variable de origen (%zu) no coincide con el recuento de la variable de destino (%zu)."
25792220
25802221 #: src/language/stats/autorecode.c:168
25812222 #, c-format
26022243 #: src/language/stats/binomial.c:219 src/language/stats/chisquare.c:177
26032244 #: src/language/stats/chisquare.c:236 src/language/stats/factor.c:1511
26042245 #: src/language/stats/glm.c:851 src/language/stats/kruskal-wallis.c:292
2605 #: src/language/stats/mann-whitney.c:188 src/language/stats/means.c:1040
2246 #: src/language/stats/mann-whitney.c:188 src/language/stats/means.c:1055
26062247 #: src/language/stats/oneway.c:946 src/language/stats/oneway.c:1117
2607 #: src/language/stats/reliability.c:539 src/language/stats/sign.c:95
2248 #: src/language/stats/reliability.c:533 src/language/stats/sign.c:95
26082249 #: src/language/stats/wilcoxon.c:255 src/ui/gui/crosstabs-dialog.c:60
26092250 #: src/language/stats/crosstabs.q:831 src/language/stats/crosstabs.q:1175
26102251 #: src/language/stats/crosstabs.q:1559 src/language/stats/examine.q:1104
26212262 #: src/language/stats/correlations.c:120 src/language/stats/correlations.c:228
26222263 #: src/language/stats/friedman.c:275 src/language/stats/kruskal-wallis.c:257
26232264 #: src/language/stats/ks-one-sample.c:293
2624 #: src/language/stats/jonckheere-terpstra.c:380
26252265 #: src/language/stats/mann-whitney.c:190 src/language/stats/means.c:408
2626 #: src/language/stats/means.c:1049 src/language/stats/mcnemar.c:259
2627 #: src/language/stats/median.c:417 src/language/stats/npar-summary.c:123
2628 #: src/language/stats/oneway.c:1016 src/language/stats/reliability.c:542
2266 #: src/language/stats/means.c:1064 src/language/stats/mcnemar.c:259
2267 #: src/language/stats/median.c:419 src/language/stats/npar-summary.c:123
2268 #: src/language/stats/oneway.c:1016 src/language/stats/reliability.c:536
26292269 #: src/language/stats/sign.c:74 src/language/stats/t-test-indep.c:211
26302270 #: src/language/stats/t-test-one-sample.c:158
26312271 #: src/language/stats/t-test-paired.c:179
26512291
26522292 #: src/language/stats/chisquare.c:150
26532293 #, c-format
2654 msgid ""
2655 "CHISQUARE test specified %d expected values, but %d distinct values were "
2656 "encountered in variable %s."
2657 msgstr ""
2658 "Prueba CHISQUARE especifica %d valores esperados, pero %d diferentes valores "
2659 "se encontraron la variable %s."
2294 msgid "CHISQUARE test specified %d expected values, but %d distinct values were encountered in variable %s."
2295 msgstr "Prueba CHISQUARE especifica %d valores esperados, pero %d diferentes valores se encontraron la variable %s."
26602296
26612297 #: src/language/stats/chisquare.c:161 src/language/stats/chisquare.c:200
26622298 msgid "Observed N"
26722308 msgstr "Residual"
26732309
26742310 #: src/language/stats/chisquare.c:195 src/language/stats/cochran.c:159
2675 #: src/language/stats/median.c:319 src/language/stats/sign.c:62
2311 #: src/language/stats/median.c:321 src/language/stats/sign.c:62
26762312 #: src/ui/gui/frequencies.ui:9 src/ui/gui/frequencies.ui:669
26772313 msgid "Frequencies"
26782314 msgstr "Frecuencias"
26802316 #: src/language/stats/chisquare.c:249 src/language/stats/cochran.c:208
26812317 #: src/language/stats/friedman.c:272 src/language/stats/kruskal-wallis.c:310
26822318 #: src/language/stats/mann-whitney.c:251 src/language/stats/mcnemar.c:240
2683 #: src/language/stats/median.c:407 src/language/stats/sign.c:114
2319 #: src/language/stats/median.c:409 src/language/stats/sign.c:114
26842320 #: src/language/stats/wilcoxon.c:304
26852321 msgid "Test Statistics"
26862322 msgstr "Pruebas Estadísticas"
26872323
26882324 #: src/language/stats/chisquare.c:263 src/language/stats/friedman.c:282
2689 #: src/language/stats/kruskal-wallis.c:313 src/language/stats/median.c:423
2325 #: src/language/stats/kruskal-wallis.c:313 src/language/stats/median.c:425
26902326 msgid "Chi-Square"
26912327 msgstr "Chi-cuadrado"
26922328
26932329 #: src/language/stats/chisquare.c:264 src/language/stats/cochran.c:217
26942330 #: src/language/stats/factor.c:1873 src/language/stats/friedman.c:285
26952331 #: src/language/stats/glm.c:752 src/language/stats/kruskal-wallis.c:316
2696 #: src/language/stats/median.c:426 src/language/stats/oneway.c:923
2332 #: src/language/stats/median.c:428 src/language/stats/oneway.c:923
26972333 #: src/language/stats/oneway.c:1328 src/language/stats/t-test-indep.c:291
26982334 #: src/language/stats/t-test-one-sample.c:95
26992335 #: src/language/stats/t-test-paired.c:306 src/language/stats/crosstabs.q:1234
27032339
27042340 #: src/language/stats/chisquare.c:265 src/language/stats/cochran.c:220
27052341 #: src/language/stats/friedman.c:288 src/language/stats/kruskal-wallis.c:319
2706 #: src/language/stats/median.c:429
2342 #: src/language/stats/median.c:431
27072343 msgid "Asymp. Sig."
27082344 msgstr "Sign. Asint."
27092345
27102346 #: src/language/stats/cochran.c:109
27112347 msgid "More than two values encountered. Cochran Q test will not be run."
2712 msgstr ""
2713 "Más de dos valores encontrados. El test Q de Cochran Q no se ejecutará."
2348 msgstr "Más de dos valores encontrados. El test Q de Cochran Q no se ejecutará."
27142349
27152350 #: src/language/stats/cochran.c:172
27162351 #, c-format
28692504 msgstr "esperando nombre del estadístico: vuelve a aplicar el defecto"
28702505
28712506 #: src/language/stats/descriptives.c:539
2872 msgid ""
2873 "Ran out of generic names for Z-score variables. There are only 126 generic "
2874 "names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
2875 msgstr ""
2876 "Se han agotado los nombres genéricos para las variables Z. Sólo hay 126 "
2877 "nombres genéricos: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-"
2878 "ZQZQ09."
2507 msgid "Ran out of generic names for Z-score variables. There are only 126 generic names: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
2508 msgstr "Se han agotado los nombres genéricos para las variables Z. Sólo hay 126 nombres genéricos: ZSC001-ZSC0999, STDZ01-STDZ09, ZZZZ01-ZZZZ09, ZQZQ01-ZQZQ09."
28792509
28802510 #: src/language/stats/descriptives.c:568
28812511 msgid "Mapping of variables to corresponding Z-scores."
29852615 msgstr "Determinante"
29862616
29872617 #: src/language/stats/factor.c:1733
2988 msgid ""
2989 "The dataset contains no complete observations. No analysis will be performed."
2990 msgstr ""
2991 "El conjunto de datos no contiene observaciones completas. No se realizará "
2992 "ningún análisis."
2618 msgid "The dataset contains no complete observations. No analysis will be performed."
2619 msgstr "El conjunto de datos no contiene observaciones completas. No se realizará ningún análisis."
29932620
29942621 #: src/language/stats/factor.c:1801
29952622 msgid "Analysis N"
29972624
29982625 #: src/language/stats/factor.c:1838
29992626 msgid "KMO and Bartlett's Test"
3000 msgstr ""
2627 msgstr "KMO y Prueba de Bartlett"
30012628
30022629 #: src/language/stats/factor.c:1866
30032630 msgid "Kaiser-Meyer-Olkin Measure of Sampling Adequacy"
3004 msgstr ""
2631 msgstr "Medida Kaiser-Meyer-Olkin de Adecuación muestral"
30052632
30062633 #: src/language/stats/factor.c:1870
30072634 msgid "Bartlett's Test of Sphericity"
3008 msgstr ""
2635 msgstr "Prueba de esfericidad de Bartlet"
30092636
30102637 #: src/language/stats/factor.c:1872
3011 #, fuzzy
30122638 msgid "Approx. Chi-Square"
3013 msgstr "Chi-cuadrado de Pearson"
2639 msgstr "Chi-cuadrado Aprox."
30142640
30152641 #: src/language/stats/factor.c:1874 src/language/stats/glm.c:755
30162642 #: src/language/stats/oneway.c:1532 src/language/stats/t-test-indep.c:289
30192645 msgstr "Sign."
30202646
30212647 #: src/language/stats/factor.c:1912
3022 msgid ""
3023 "The FACTOR criteria result in zero factors extracted. Therefore no analysis "
3024 "will be performed."
3025 msgstr ""
3026 "El criterio FACTOR resulta en la extracción de cero factores. No se puede "
3027 "realizar ningún análisis."
2648 msgid "The FACTOR criteria result in zero factors extracted. Therefore no analysis will be performed."
2649 msgstr "El criterio FACTOR resulta en la extracción de cero factores. No se puede realizar ningún análisis."
30282650
30292651 #: src/language/stats/factor.c:1918
3030 msgid ""
3031 "The FACTOR criteria result in more factors than variables, which is not "
3032 "meaningful. No analysis will be performed."
3033 msgstr ""
3034 "El criterio FACTOR resulta en más factores que variables, y esto no tiene "
3035 "ningún sentido."
2652 msgid "The FACTOR criteria result in more factors than variables, which is not meaningful. No analysis will be performed."
2653 msgstr "El criterio FACTOR resulta en más factores que variables, y esto no tiene ningún sentido."
30362654
30372655 #: src/language/stats/factor.c:2001
30382656 msgid "Component Matrix"
30512669 msgstr "Matriz Rotada de Factores"
30522670
30532671 #: src/language/stats/flip.c:99
3054 msgid ""
3055 "FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
3056 msgstr ""
3057 "FLIP ignora TEMPORARY. Las transformaciones temporales serán permanentes."
2672 msgid "FLIP ignores TEMPORARY. Temporary transformations will be made permanent."
2673 msgstr "FLIP ignora TEMPORARY. Las transformaciones temporales serán permanentes."
30582674
30592675 #: src/language/stats/flip.c:151
30602676 msgid "Could not create temporary file for FLIP."
31172733 msgstr "W de Kendall"
31182734
31192735 #: src/language/stats/glm.c:167
3120 #, fuzzy
31212736 msgid "Multivariate analysis is not yet implemented"
3122 msgstr "%s aún no está implementado."
2737 msgstr "Análisis multivariado todavía no está implementado."
31232738
31242739 #: src/language/stats/glm.c:272
3125 #, fuzzy
31262740 msgid "Only types 1, 2 & 3 sums of squares are currently implemented"
3127 msgstr "Sólo USE ALL se está aplicando actualmente."
2741 msgstr "Sólo los tipos 1, 2 & 3 de sumas cadráticas están actualmente implementadas."
31282742
31292743 #: src/language/stats/glm.c:737
31302744 msgid "Tests of Between-Subjects Effects"
3131 msgstr ""
2745 msgstr "Puebas de Efectos Entre-Sujetos"
31322746
31332747 #: src/language/stats/glm.c:750
3134 #, fuzzy, c-format
2748 #, c-format
31352749 msgid "Type %s Sum of Squares"
3136 msgstr "Suma de Cuadrados"
2750 msgstr "Suma de Cuadrados Tipo %s"
31372751
31382752 #: src/language/stats/glm.c:753 src/language/stats/oneway.c:924
31392753 #: src/language/stats/regression.q:287
31472761
31482762 #: src/language/stats/glm.c:763
31492763 msgid "Corrected Model"
3150 msgstr ""
2764 msgstr "Modelo Corregido"
31512765
31522766 #: src/language/stats/glm.c:765 src/language/stats/regression.q:372
31532767 msgid "Model"
31542768 msgstr "Modelo"
31552769
31562770 #: src/language/stats/glm.c:778
3157 #, fuzzy
31582771 msgid "Intercept"
3159 msgstr "Porcentaje"
2772 msgstr "Constante"
31602773
31612774 #: src/language/stats/glm.c:844
3162 #, fuzzy
31632775 msgid "Error"
3164 msgstr "error"
2776 msgstr "Error"
31652777
31662778 #: src/language/stats/glm.c:860
3167 #, fuzzy
31682779 msgid "Corrected Total"
3169 msgstr "Coeficiente Total: "
2780 msgstr "Total Corregido "
31702781
31712782 #: src/language/stats/ks-one-sample.c:282 src/ui/gui/ks-one-sample.ui:7
3172 #, fuzzy
31732783 msgid "One-Sample Kolmogorov-Smirnov Test"
3174 msgstr "Prueba de una muestra"
2784 msgstr "Prueba Kolmogorov_Smirnov para una muestra"
31752785
31762786 #: src/language/stats/ks-one-sample.c:299
3177 #, fuzzy
31782787 msgid "Normal Parameters"
3179 msgstr "Puntuación Normal"
2788 msgstr "Parámetros Normal"
31802789
31812790 #: src/language/stats/ks-one-sample.c:308
31822791 msgid "Uniform Parameters"
3183 msgstr ""
2792 msgstr "Parámetros Uniforme"
31842793
31852794 #: src/language/stats/ks-one-sample.c:317
31862795 msgid "Poisson Parameters"
3187 msgstr ""
2796 msgstr "Parámetros Poisson"
31882797
31892798 #: src/language/stats/ks-one-sample.c:320 src/ui/gui/crosstabs-dialog.c:44
31902799 #: src/language/stats/crosstabs.q:1943
31932802
31942803 #: src/language/stats/ks-one-sample.c:324
31952804 msgid "Exponential Parameters"
3196 msgstr ""
2805 msgstr "Parámetros Exponencial"
31972806
31982807 #: src/language/stats/ks-one-sample.c:384
3199 #, fuzzy
32002808 msgid "Most Extreme Differences"
3201 msgstr "Diferencias Positivas"
2809 msgstr "Diferencias Más Extremas"
32022810
32032811 #: src/language/stats/ks-one-sample.c:387
32042812 msgid "Absolute"
3205 msgstr ""
2813 msgstr "Absoluto"
32062814
32072815 #: src/language/stats/ks-one-sample.c:390 src/language/stats/roc.c:1076
32082816 msgid "Positive"
32142822
32152823 #: src/language/stats/ks-one-sample.c:396
32162824 msgid "Kolmogorov-Smirnov Z"
3217 msgstr ""
2825 msgstr "Z de Kolmogorov-Smirnov"
32182826
32192827 #: src/language/stats/ks-one-sample.c:399
3220 #: src/language/stats/jonckheere-terpstra.c:385
32212828 #: src/language/stats/mann-whitney.c:267 src/language/stats/runs.c:399
32222829 #: src/language/stats/wilcoxon.c:318 src/language/stats/crosstabs.q:1236
32232830 msgid "Asymp. Sig. (2-tailed)"
32242831 msgstr "Sig. Asint. (2-colas)"
32252832
3226 #: src/language/stats/jonckheere-terpstra.c:364
3227 msgid "Jonckheere-Terpstra Test"
3228 msgstr ""
3229
3230 #: src/language/stats/jonckheere-terpstra.c:378
3231 #, fuzzy, c-format
3232 msgid "Number of levels in %s"
3233 msgstr "Número de ejecuciones"
3234
3235 #: src/language/stats/jonckheere-terpstra.c:381
3236 #, fuzzy
3237 msgid "Observed J-T Statistic"
3238 msgstr "Estadístico de Levene"
3239
3240 #: src/language/stats/jonckheere-terpstra.c:382
3241 #, fuzzy
3242 msgid "Mean J-T Statistic"
3243 msgstr "Estadístico de Levene"
3244
3245 #: src/language/stats/jonckheere-terpstra.c:383
3246 #, fuzzy
3247 msgid "Std. Deviation of J-T Statistic"
3248 msgstr "Desviación Estándar"
3249
3250 #: src/language/stats/jonckheere-terpstra.c:384
3251 #, fuzzy
3252 msgid "Std. J-T Statistic"
3253 msgstr "Pruebas Estadísticas"
3254
32552833 #: src/language/stats/mann-whitney.c:202 src/language/stats/wilcoxon.c:240
32562834 msgid "Sum of Ranks"
32572835 msgstr "Suma de Rangos"
32792857 msgid "Point Probability"
32802858 msgstr "Punto de Probabilidad"
32812859
3282 #: src/language/stats/means.c:411 src/language/stats/median.c:420
2860 #: src/language/stats/means.c:411 src/language/stats/median.c:422
32832861 #: src/ui/gui/frequencies-dialog.c:53 src/language/stats/examine.q:1468
32842862 #: src/language/stats/frequencies.q:107
32852863 msgid "Median"
32862864 msgstr "Mediana"
32872865
32882866 #: src/language/stats/means.c:412
3289 #, fuzzy
32902867 msgid "Group Median"
3291 msgstr "Mediana"
2868 msgstr "Mediana de Grupo"
32922869
32932870 #: src/language/stats/means.c:416
3294 #, fuzzy
32952871 msgid "Min"
3296 msgstr "Mediana"
2872 msgstr "Mínimo"
32972873
32982874 #: src/language/stats/means.c:417
3299 #, fuzzy
33002875 msgid "Max"
33012876 msgstr "Máximo"
33022877
33032878 #: src/language/stats/means.c:424
3304 #, fuzzy
33052879 msgid "First"
3306 msgstr "Primer caso"
2880 msgstr "Primero"
33072881
33082882 #: src/language/stats/means.c:425
3309 #, fuzzy
33102883 msgid "Last"
3311 msgstr "Último caso"
2884 msgstr "Último"
33122885
33132886 #: src/language/stats/means.c:427
3314 #, fuzzy
33152887 msgid "Percent N"
3316 msgstr "Porcentaje"
2888 msgstr "Porcentaje N"
33172889
33182890 #: src/language/stats/means.c:428
3319 #, fuzzy
33202891 msgid "Percent Sum"
3321 msgstr "Porcentaje"
2892 msgstr "Porcentaje Suma"
33222893
33232894 #: src/language/stats/means.c:430
33242895 msgid "Harmonic Mean"
3325 msgstr ""
2896 msgstr "Media Armónica"
33262897
33272898 #: src/language/stats/means.c:431
3328 #, fuzzy
33292899 msgid "Geom. Mean"
3330 msgstr "Err.Est.Media"
3331
3332 #: src/language/stats/means.c:1025 src/language/stats/reliability.c:507
2900 msgstr "Media Geom."
2901
2902 #: src/language/stats/means.c:1040 src/language/stats/reliability.c:501
33332903 #: src/language/stats/examine.q:1158
33342904 msgid "Case Processing Summary"
33352905 msgstr "Resumen del proceso de casos"
33362906
3337 #: src/language/stats/means.c:1036 src/language/stats/reliability.c:530
2907 #: src/language/stats/means.c:1051 src/language/stats/reliability.c:524
33382908 #: src/language/stats/crosstabs.q:828 src/language/stats/examine.q:1163
33392909 msgid "Cases"
33402910 msgstr "Casos"
33412911
3342 #: src/language/stats/means.c:1038
3343 #, fuzzy
2912 #: src/language/stats/means.c:1053
33442913 msgid "Included"
3345 msgstr "Excluido"
3346
3347 #: src/language/stats/means.c:1039 src/language/stats/reliability.c:536
2914 msgstr "Incluido"
2915
2916 #: src/language/stats/means.c:1054 src/language/stats/reliability.c:530
33482917 msgid "Excluded"
33492918 msgstr "Excluido"
33502919
3351 #: src/language/stats/means.c:1051 src/language/stats/crosstabs.q:839
2920 #: src/language/stats/means.c:1066 src/language/stats/crosstabs.q:839
33522921 #: src/language/stats/examine.q:1178 src/language/stats/frequencies.q:823
33532922 msgid "Percent"
33542923 msgstr "Porcentaje"
33552924
3356 #: src/language/stats/means.c:1081 src/language/stats/means.c:1090
3357 #: src/language/stats/means.c:1099
2925 #: src/language/stats/means.c:1096 src/language/stats/means.c:1105
2926 #: src/language/stats/means.c:1114
33582927 #, c-format
33592928 msgid "%g%%"
3360 msgstr ""
3361
3362 #: src/language/stats/means.c:1131
2929 msgstr "%g%%"
2930
2931 #: src/language/stats/means.c:1147
33632932 msgid "Report"
3364 msgstr ""
2933 msgstr "Informe"
33652934
33662935 #: src/language/stats/mcnemar.c:143
33672936 msgid "The McNemar test is appropriate only for dichotomous variables"
3368 msgstr ""
2937 msgstr "La prueba de McNemar es apropiada sólo para variables dicotómicas"
33692938
33702939 #: src/language/stats/mcnemar.c:265 src/language/stats/sign.c:136
33712940 #: src/language/stats/wilcoxon.c:323
33722941 msgid "Exact Sig. (1-tailed)"
33732942 msgstr "Sig. Exacta (1-cola)"
33742943
3375 #: src/language/stats/median.c:358
3376 #, fuzzy
2944 #: src/language/stats/median.c:360
33772945 msgid "> Median"
3378 msgstr "Mediana"
3379
3380 #: src/language/stats/median.c:361
3381 #, fuzzy
2946 msgstr "> Mediana"
2947
2948 #: src/language/stats/median.c:363
33822949 msgid "≤ Median"
3383 msgstr "Mediana"
3384
3385 #: src/language/stats/npar.c:537
2950 msgstr "≤ Mediana"
2951
2952 #: src/language/stats/npar.c:511
33862953 msgid "NPAR subcommand not currently implemented."
33872954 msgstr "Actualmente no está implementado el subcomando NPAR."
33882955
3389 #: src/language/stats/npar.c:691
2956 #: src/language/stats/npar.c:665
33902957 msgid "Expecting MEAN, MEDIAN, MODE or number"
33912958 msgstr "Se espera MEAN, MEDIAN, MODE o un número."
33922959
3393 #: src/language/stats/npar.c:841
3394 #, c-format
3395 msgid ""
3396 "The specified value of HI (%d) is lower than the specified value of LO (%d)"
3397 msgstr ""
3398 "El valor especificado para HI (%d) es menor que el especificado para LO (%d)"
3399
3400 #: src/language/stats/npar.c:891
3401 #, c-format
3402 msgid ""
3403 "%d expected values were given, but the specified range (%d-%d) requires "
3404 "exactly %d values."
3405 msgstr ""
3406 "Se han proporcionado %d valores esperados, pero el intervalo especificado "
3407 "(%d-%d) requiere exactamente %d valores."
3408
3409 #: src/language/stats/npar.c:1104 src/language/stats/t-test-parser.c:163
3410 #, c-format
3411 msgid ""
3412 "PAIRED was specified but the number of variables preceding WITH (%zu) did "
3413 "not match the number following (%zu)."
3414 msgstr ""
3415 "Se ha especificado PAIRED pero el número de variables antes de WITH (%zu) no "
3416 "coincide con el número de variables posterior (%zu)."
2960 #: src/language/stats/npar.c:815
2961 #, c-format
2962 msgid "The specified value of HI (%d) is lower than the specified value of LO (%d)"
2963 msgstr "El valor especificado para HI (%d) es menor que el especificado para LO (%d)"
2964
2965 #: src/language/stats/npar.c:865
2966 #, c-format
2967 msgid "%d expected values were given, but the specified range (%d-%d) requires exactly %d values."
2968 msgstr "Se han proporcionado %d valores esperados, pero el intervalo especificado (%d-%d) requiere exactamente %d valores."
2969
2970 #: src/language/stats/npar.c:1078 src/language/stats/t-test-parser.c:163
2971 #, c-format
2972 msgid "PAIRED was specified but the number of variables preceding WITH (%zu) did not match the number following (%zu)."
2973 msgstr "Se ha especificado PAIRED pero el número de variables antes de WITH (%zu) no coincide con el número de variables posterior (%zu)."
34172974
34182975 #: src/language/stats/npar-summary.c:142 src/language/stats/examine.q:1995
34192976 #: src/language/stats/examine.q:2012 src/language/stats/frequencies.q:1057
34352992
34362993 #: src/language/stats/oneway.c:358
34372994 msgid "LSD"
3438 msgstr ""
2995 msgstr "LSD"
34392996
34402997 #: src/language/stats/oneway.c:359
3441 #, fuzzy
34422998 msgid "Tukey HSD"
3443 msgstr "Tukey"
2999 msgstr "Tukey HSD"
34443000
34453001 #: src/language/stats/oneway.c:360
34463002 msgid "Bonferroni"
3447 msgstr ""
3003 msgstr "Bonferroni"
34483004
34493005 #: src/language/stats/oneway.c:361
34503006 msgid "Scheffé"
3451 msgstr ""
3007 msgstr "Scheffé"
34523008
34533009 #: src/language/stats/oneway.c:362
34543010 msgid "Games-Howell"
3455 msgstr ""
3011 msgstr "Games-Howell"
34563012
34573013 #: src/language/stats/oneway.c:363
34583014 msgid "Šidák"
3459 msgstr ""
3015 msgstr "Šidák"
34603016
34613017 #: src/language/stats/oneway.c:480
34623018 #, c-format
34633019 msgid "The post hoc analysis method %s is not supported."
3464 msgstr ""
3020 msgstr "El método post-hoc de análisis %s no está implementado."
34653021
34663022 #: src/language/stats/oneway.c:781
34673023 #, c-format
3468 msgid ""
3469 "Dependent variable %s has no non-missing values. No analysis for this "
3470 "variable will be done."
3471 msgstr ""
3024 msgid "Dependent variable %s has no non-missing values. No analysis for this variable will be done."
3025 msgstr "La variable dependiente %s carece de valores no-perdidos. No se realiza ningún análisis para tal variable."
34723026
34733027 #: src/language/stats/oneway.c:858
34743028 #, c-format
3475 msgid ""
3476 "In contrast list %zu, the number of coefficients (%zu) does not equal the "
3477 "number of groups (%d). This contrast list will be ignored."
3478 msgstr ""
3029 msgid "In contrast list %zu, the number of coefficients (%zu) does not equal the number of groups (%d). This contrast list will be ignored."
3030 msgstr "En la lista de contrate %zu, el número de coeficientes (%zu) difiere del numero de grupos (%d). Se ignora esta lista de contraste."
34793031
34803032 #: src/language/stats/oneway.c:869
34813033 #, c-format
35763128 msgstr "No se asume igualdad"
35773129
35783130 #: src/language/stats/oneway.c:1525
3579 #, fuzzy
35803131 msgid "Multiple Comparisons"
3581 msgstr "Conjuntos Multi-Respuesta"
3132 msgstr "Múltiples Comparaciones"
35823133
35833134 #: src/language/stats/oneway.c:1527
35843135 #, c-format
35853136 msgid "(I) %s"
3586 msgstr ""
3137 msgstr "(I) %s"
35873138
35883139 #: src/language/stats/oneway.c:1528
35893140 #, c-format
35903141 msgid "(J) %s"
3591 msgstr ""
3142 msgstr "(J) %s"
35923143
35933144 #: src/language/stats/oneway.c:1529 src/language/stats/t-test-indep.c:293
35943145 #: src/language/stats/t-test-one-sample.c:97
35973148
35983149 #: src/language/stats/oneway.c:1530
35993150 msgid "(I - J)"
3600 msgstr ""
3151 msgstr "(I - J)"
36013152
36023153 #: src/language/stats/oneway.c:1535
3603 #, fuzzy, c-format
3154 #, c-format
36043155 msgid "%g%% Confidence Interval"
3605 msgstr "Intervalo de Confianza del 95%%"
3156 msgstr "Intervalo de Confianza del %g%%"
36063157
36073158 #: src/language/stats/quick-cluster.c:361
36083159 msgid "Number of clusters may not be larger than the number of cases."
36253176 msgid "Number of Cases in each Cluster"
36263177 msgstr "Número de casos en cada Agrupación"
36273178
3628 #: src/language/stats/quick-cluster.c:476 src/language/stats/reliability.c:533
3179 #: src/language/stats/quick-cluster.c:476 src/language/stats/reliability.c:527
36293180 #: src/language/stats/crosstabs.q:829 src/language/stats/examine.q:1102
36303181 #: src/language/stats/frequencies.q:1042
36313182 msgid "Valid"
36333184
36343185 #: src/language/stats/rank.c:207
36353186 msgid "Cannot create new rank variable. All candidates in use."
3636 msgstr ""
3637 "No se puede crear la nueva variable de rangos. Todos los candidatos están "
3638 "en uso."
3187 msgstr "No se puede crear la nueva variable de rangos. Todos los candidatos están en uso."
36393188
36403189 #: src/language/stats/rank.c:326
36413190 #, c-format
36843233 msgid "Reliability on a single variable is not useful."
36853234 msgstr "El análisis factorial para una única variable es inútil."
36863235
3687 #: src/language/stats/reliability.c:268
3688 #, fuzzy
3689 msgid "The split point must be less than the number of variables"
3690 msgstr "El número de agrupaciones no puede ser mayor que el número de casos."
3691
3692 #: src/language/stats/reliability.c:481
3693 #, fuzzy, c-format
3694 msgid "Scale: %s"
3695 msgstr "Escala:"
3696
3697 #: src/language/stats/reliability.c:544
3236 #: src/language/stats/reliability.c:538
36983237 msgid "%"
36993238 msgstr "%"
37003239
3701 #: src/language/stats/reliability.c:589
3240 #: src/language/stats/reliability.c:583
37023241 msgid "Item-Total Statistics"
37033242 msgstr "Estadísticas de total de Ítems"
37043243
3705 #: src/language/stats/reliability.c:611
3244 #: src/language/stats/reliability.c:605
37063245 msgid "Scale Mean if Item Deleted"
37073246 msgstr "Escalar la mediana si se borra el elemento"
37083247
3709 #: src/language/stats/reliability.c:614
3248 #: src/language/stats/reliability.c:608
37103249 msgid "Scale Variance if Item Deleted"
37113250 msgstr "Escalar la varianza si se borra el elemento"
37123251
3713 #: src/language/stats/reliability.c:617
3252 #: src/language/stats/reliability.c:611
37143253 msgid "Corrected Item-Total Correlation"
37153254 msgstr "Correlación total-ítem corregida"
37163255
3717 #: src/language/stats/reliability.c:620
3256 #: src/language/stats/reliability.c:614
37183257 msgid "Cronbach's Alpha if Item Deleted"
37193258 msgstr "Alfa de Cronbach si se borra el elemento"
37203259
3721 #: src/language/stats/reliability.c:694
3260 #: src/language/stats/reliability.c:688
37223261 msgid "Reliability Statistics"
37233262 msgstr "Estadísticas de fiabilidad"
37243263
3725 #: src/language/stats/reliability.c:734 src/language/stats/reliability.c:753
3264 #: src/language/stats/reliability.c:728 src/language/stats/reliability.c:747
37263265 msgid "Cronbach's Alpha"
37273266 msgstr "Alfa de Cronbach"
37283267
3729 #: src/language/stats/reliability.c:737 src/language/stats/reliability.c:762
3730 #: src/language/stats/reliability.c:773
3268 #: src/language/stats/reliability.c:731 src/language/stats/reliability.c:756
3269 #: src/language/stats/reliability.c:767
37313270 msgid "N of Items"
37323271 msgstr "N de elementos"
37333272
3734 #: src/language/stats/reliability.c:756
3273 #: src/language/stats/reliability.c:750
37353274 msgid "Part 1"
37363275 msgstr "Parte 1"
37373276
3738 #: src/language/stats/reliability.c:767
3277 #: src/language/stats/reliability.c:761
37393278 msgid "Part 2"
37403279 msgstr "Parte 2"
37413280
3742 #: src/language/stats/reliability.c:778
3281 #: src/language/stats/reliability.c:772
37433282 msgid "Total N of Items"
37443283 msgstr "N total de elementos"
37453284
37463285 #
3747 #: src/language/stats/reliability.c:781
3286 #: src/language/stats/reliability.c:775
37483287 msgid "Correlation Between Forms"
37493288 msgstr "Correlación entre formas"
37503289
3751 #: src/language/stats/reliability.c:785
3290 #: src/language/stats/reliability.c:779
37523291 msgid "Spearman-Brown Coefficient"
37533292 msgstr "Coeficiente de Spearman-Brown"
37543293
3755 #: src/language/stats/reliability.c:788
3294 #: src/language/stats/reliability.c:782
37563295 msgid "Equal Length"
37573296 msgstr "Ancho igual"
37583297
3759 #: src/language/stats/reliability.c:791
3298 #: src/language/stats/reliability.c:785
37603299 msgid "Unequal Length"
37613300 msgstr "Ancho desigual"
37623301
3763 #: src/language/stats/reliability.c:795
3302 #: src/language/stats/reliability.c:789
37643303 msgid "Guttman Split-Half Coefficient"
37653304 msgstr "Coeficiente Guttman de División en Mitades"
37663305
38333372
38343373 #: src/language/stats/runs.c:167
38353374 #, c-format
3836 msgid ""
3837 "Multiple modes exist for varible `%s'. Using %g as the threshold value."
3838 msgstr ""
3839 "Existen múltiples modos para la variable `%s'. Se utiliza %g como valor de "
3840 "umbral."
3375 msgid "Multiple modes exist for varible `%s'. Using %g as the threshold value."
3376 msgstr "Existen múltiples modos para la variable `%s'. Se utiliza %g como valor de umbral."
38413377
38423378 #: src/language/stats/runs.c:322 src/ui/gui/runs.ui:7
38433379 msgid "Runs Test"
38643400 msgstr "Casos < Valor de Test"
38653401
38663402 #: src/language/stats/runs.c:387
3867 #, fuzzy
38683403 msgid "Cases ≥ Test Value"
3869 msgstr "Casos < Valor de Test"
3404 msgstr "Casos ≥ Valor de Prueba"
38703405
38713406 #: src/language/stats/runs.c:390
38723407 msgid "Total Cases"
39943529 msgstr "Error Est. Media"
39953530
39963531 #: src/language/stats/t-test-paired.c:329
3997 #, fuzzy, c-format
3532 #, c-format
39983533 msgid "%s - %s"
3999 msgstr "%s - Página %d"
3534 msgstr "%s - %s"
40003535
40013536 #: src/language/stats/t-test-parser.c:123
4002 msgid ""
4003 "When applying GROUPS to a string variable, two values must be specified."
4004 msgstr ""
4005 "Cuando se aplica GROUPS a una variable alfabética, se deben especificar dos "
4006 "valores."
3537 msgid "When applying GROUPS to a string variable, two values must be specified."
3538 msgstr "Cuando se aplica GROUPS a una variable alfabética, se deben especificar dos valores."
40073539
40083540 #: src/language/stats/t-test-parser.c:135
40093541 #: src/language/stats/t-test-parser.c:231
40123544
40133545 #: src/language/stats/t-test-parser.c:293
40143546 msgid "Exactly one of TESTVAL, GROUPS and PAIRS subcommands must be specified."
4015 msgstr ""
4016 "Debe especificarse sólo uno de los subcomandos TESTVAL, GROUPS y PAIRS."
3547 msgstr "Debe especificarse sólo uno de los subcomandos TESTVAL, GROUPS y PAIRS."
40173548
40183549 #: src/language/stats/wilcoxon.c:252
40193550 msgid "Negative Ranks"
40253556
40263557 #: src/language/stats/wilcoxon.c:361
40273558 msgid "Too many pairs to calculate exact significance."
4028 msgstr ""
3559 msgstr "Demasiados pares para calcular la significatividad exacta."
40293560
40303561 #: src/language/data-io/combine-files.c:212
40313562 msgid "Cannot specify the active dataset since none has been defined."
4032 msgstr ""
4033 "No se puede especificar el fichero de datos activo ya que ningún fichero "
4034 "activo ha sido definido."
3563 msgstr "No se puede especificar el fichero de datos activo ya que ningún fichero activo ha sido definido."
40353564
40363565 #: src/language/data-io/combine-files.c:218
4037 msgid ""
4038 "This command may not be used after TEMPORARY when the active dataset is an "
4039 "input source. Temporary transformations will be made permanent."
4040 msgstr ""
4041 "Este comando no puede ser utilizado después de TEMPORARY cuando el archivo "
4042 "de datos activo es una fuente de entrada. Las transformaciones temporales "
4043 "serán permanentes."
3566 msgid "This command may not be used after TEMPORARY when the active dataset is an input source. Temporary transformations will be made permanent."
3567 msgstr "Este comando no puede ser utilizado después de TEMPORARY cuando el archivo de datos activo es una fuente de entrada. Las transformaciones temporales serán permanentes."
40443568
40453569 #: src/language/data-io/combine-files.c:252
40463570 msgid "Multiple IN subcommands for a single FILE or TABLE."
40633587 msgstr "BY es necesario cuando se especifica %s."
40643588
40653589 #: src/language/data-io/combine-files.c:514
4066 msgid ""
4067 "Combining files with incompatible encodings. String data may not be "
4068 "represented correctly."
4069 msgstr ""
4070 "Combinando archivos con codificaciones incompatibles. Los datos de la cadena "
4071 "no podrán estar representados correctamente."
3590 msgid "Combining files with incompatible encodings. String data may not be represented correctly."
3591 msgstr "Combinando archivos con codificaciones incompatibles. Los datos de la cadena no podrán estar representados correctamente."
40723592
40733593 #: src/language/data-io/combine-files.c:555
40743594 #, c-format
4075 msgid ""
4076 "Variable %s in file %s has different type or width from the same variable in "
4077 "earlier file."
4078 msgstr ""
4079 "La variable %s en el archivo %s es de tipo o tamaño diferente respecto de la "
4080 "misma variable en un archivo anterior."
3595 msgid "Variable %s in file %s has different type or width from the same variable in earlier file."
3596 msgstr "La variable %s en el archivo %s es de tipo o tamaño diferente respecto de la misma variable en un archivo anterior."
40813597
40823598 #: src/language/data-io/combine-files.c:561
40833599 #, c-format
40973613 #: src/language/data-io/combine-files.c:572
40983614 #, c-format
40993615 msgid "In an earlier file, %s was a string variable with width %d."
4100 msgstr ""
4101 "En un archivo anterior, %s era una variable de cadena con un tamaño de %d."
3616 msgstr "En un archivo anterior, %s era una variable de cadena con un tamaño de %d."
41023617
41033618 #: src/language/data-io/combine-files.c:612
41043619 #, c-format
4105 msgid ""
4106 "Variable name %s specified on %s subcommand duplicates an existing variable "
4107 "name."
4108 msgstr ""
4109 "Nombre de la variable %s especificado en el subcomando %s duplica el nombre "
4110 "de la variable existente."
3620 msgid "Variable name %s specified on %s subcommand duplicates an existing variable name."
3621 msgstr "Nombre de la variable %s especificado en el subcomando %s duplica el nombre de la variable existente."
41113622
41123623 #: src/language/data-io/combine-files.c:774
41133624 #, c-format
41283639
41293640 #: src/language/data-io/data-list.c:245
41303641 msgid "Encoding should not be specified for inline data. It will be ignored."
4131 msgstr ""
4132 "La codificación no debe ser especificada por los datos en línea. Será "
4133 "ignorada."
3642 msgstr "La codificación no debe ser especificada por los datos en línea. Será ignorada."
41343643
41353644 #: src/language/data-io/data-list.c:254
41363645 msgid "The END subcommand may be used only with DATA LIST FIXED."
41593668 #: src/language/data-io/data-list.c:390
41603669 #, c-format
41613670 msgid "Cannot place variable %s on record %d when RECORDS=%d is specified."
4162 msgstr ""
4163 "No se puede poner la variable %s en el registro %d cuando RECORDS=%d está "
4164 "especificado."
3671 msgstr "No se puede poner la variable %s en el registro %d cuando RECORDS=%d está especificado."
41653672
41663673 #: src/language/data-io/data-parser.c:458
41673674 #: src/language/data-io/data-parser.c:467
41853692
41863693 #: src/language/data-io/data-parser.c:644
41873694 #, c-format
4188 msgid ""
4189 "Missing value(s) for all variables from %s onward. These will be filled "
4190 "with the system-missing value or blanks, as appropriate."
4191 msgstr ""
4192 "Valor(es) perdido(s) para todas las variables desde %st. Éstos se llenan "
4193 "con el valor perdido del sistema o espacios en blanco, según corresponda."
3695 msgid "Missing value(s) for all variables from %s onward. These will be filled with the system-missing value or blanks, as appropriate."
3696 msgstr "Valor(es) perdido(s) para todas las variables desde %st. Éstos se llenan con el valor perdido del sistema o espacios en blanco, según corresponda."
41943697
41953698 #: src/language/data-io/data-parser.c:664
41963699 msgid "Record ends in data not part of any field."
42323735 #: src/language/data-io/data-reader.c:148
42333736 #, c-format
42343737 msgid "Could not open `%s' for reading as a data file: %s."
4235 msgstr ""
4236 "No se ha podido abrir `%s' para la lectura como un archivo de datos: %s."
3738 msgstr "No se ha podido abrir `%s' para la lectura como un archivo de datos: %s."
42373739
42383740 #: src/language/data-io/data-reader.c:198
4239 msgid ""
4240 "Missing END DATA while reading inline data. This probably indicates a "
4241 "missing or incorrectly formatted END DATA command. END DATA must appear by "
4242 "itself on a single line with exactly one space between words."
4243 msgstr ""
4244 "Falta END DATA durante la lectura de datos en línea. Esto probablemente "
4245 "indica una pérdida o formato erróneo del comando END DATA. END DATA debe "
4246 "aparecer por sí misma en una sola línea con exactamente un espacio entre las "
4247 "palabras."
3741 msgid "Missing END DATA while reading inline data. This probably indicates a missing or incorrectly formatted END DATA command. END DATA must appear by itself on a single line with exactly one space between words."
3742 msgstr "Falta END DATA durante la lectura de datos en línea. Esto probablemente indica una pérdida o formato erróneo del comando END DATA. END DATA debe aparecer por sí misma en una sola línea con exactamente un espacio entre las palabras."
42483743
42493744 #: src/language/data-io/data-reader.c:219
42503745 #, c-format
42903785 msgstr "Intento de leer más allá de END DATA."
42913786
42923787 #: src/language/data-io/data-reader.c:706
4293 msgid ""
4294 "This command is not valid here since the current input program does not "
4295 "access the inline file."
4296 msgstr ""
4297 "Esta orden no es válida ya que el programa de entrada actual no tiene acceso "
4298 "al archivo en línea."
3788 msgid "This command is not valid here since the current input program does not access the inline file."
3789 msgstr "Esta orden no es válida ya que el programa de entrada actual no tiene acceso al archivo en línea."
42993790
43003791 #: src/language/data-io/data-writer.c:73
43013792 #, c-format
43023793 msgid "An error occurred while opening `%s' for writing as a data file: %s."
4303 msgstr ""
4304 "Se ha producido un error al abrir `%s' para escribir en él como un archivo "
4305 "de datos: %s."
3794 msgstr "Se ha producido un error al abrir `%s' para escribir en él como un archivo de datos: %s."
43063795
43073796 #: src/language/data-io/data-writer.c:190
43083797 #, c-format
43333822
43343823 #: src/language/data-io/get-data.c:293
43353824 #, c-format
4336 msgid ""
4337 "%s is allowed only with %s arrangement, but %s arrangement was stated or "
4338 "implied earlier in this command."
4339 msgstr ""
4340 "%s sólo se permite con configuración %s, pero previamente en este comando se "
4341 "ha establecido la configuración %s."
3825 msgid "%s is allowed only with %s arrangement, but %s arrangement was stated or implied earlier in this command."
3826 msgstr "%s sólo se permite con configuración %s, pero previamente en este comando se ha establecido la configuración %s."
43423827
43433828 #: src/language/data-io/get-data.c:362
43443829 msgid "Value of FIRSTCASE must be 1 or greater."
43573842 msgstr "Valor de PERCENT debe estar entre 1 y 100."
43583843
43593844 #: src/language/data-io/get-data.c:483
4360 msgid ""
4361 "In compatible syntax mode, the QUALIFIER string must contain exactly one "
4362 "character."
4363 msgstr ""
4364 "En el modo de sintaxis compatible, la cadena QUALIFIER debe contener "
4365 "exactamente un carácter."
3845 msgid "In compatible syntax mode, the QUALIFIER string must contain exactly one character."
3846 msgstr "En el modo de sintaxis compatible, la cadena QUALIFIER debe contener exactamente un carácter."
43663847
43673848 #: src/language/data-io/get-data.c:518
43683849 #: src/language/data-io/placement-parser.c:377
43693850 #, c-format
4370 msgid ""
4371 "The record number specified, %ld, is at or before the previous record, %d. "
4372 "Data fields must be listed in order of increasing record number."
4373 msgstr ""
4374 "El número de registro especificado, %ld, es en o antes del registro "
4375 "anterior, %d. Los campos de datos deben ser listados en orden incremental "
4376 "del número de registro."
3851 msgid "The record number specified, %ld, is at or before the previous record, %d. Data fields must be listed in order of increasing record number."
3852 msgstr "El número de registro especificado, %ld, es en o antes del registro anterior, %d. Los campos de datos deben ser listados en orden incremental del número de registro."
43773853
43783854 #: src/language/data-io/get-data.c:527
43793855 #, c-format
4380 msgid ""
4381 "The record number specified, %ld, exceeds the number of records per case "
4382 "specified on FIXCASE, %d."
4383 msgstr ""
4384 "El número de registro especificado, %ld, excede el número de registros para "
4385 "casos especificados en FIXCASE, %d."
3856 msgid "The record number specified, %ld, exceeds the number of records per case specified on FIXCASE, %d."
3857 msgstr "El número de registro especificado, %ld, excede el número de registros para casos especificados en FIXCASE, %d."
43863858
43873859 #: src/language/data-io/inpt-pgm.c:118
43883860 msgid "Unexpected end-of-file within INPUT PROGRAM."
43933865 msgstr "El programa de entrada no creó ninguna variable."
43943866
43953867 #: src/language/data-io/inpt-pgm.c:330
4396 msgid ""
4397 "REREAD: Column numbers must be positive finite numbers. Column set to 1."
4398 msgstr ""
4399 "REREAD: Los números de columna tienen que ser números positivos finitos. La "
4400 "columna se establece en 1."
3868 msgid "REREAD: Column numbers must be positive finite numbers. Column set to 1."
3869 msgstr "REREAD: Los números de columna tienen que ser números positivos finitos. La columna se establece en 1."
44013870
44023871 #: src/language/data-io/placement-parser.c:86
44033872 #, c-format
4404 msgid ""
4405 "Number of variables specified (%zu) differs from number of variable formats "
4406 "(%zu)."
4407 msgstr ""
4408 "Número de variables especificadas (%zu) difiere del número de formatos de la "
4409 "variable (%zu)."
3873 msgid "Number of variables specified (%zu) differs from number of variable formats (%zu)."
3874 msgstr "Número de variables especificadas (%zu) difiere del número de formatos de la variable (%zu)."
44103875
44113876 #: src/language/data-io/placement-parser.c:96
4412 msgid ""
4413 "SPSS-like or Fortran-like format specification expected after variable names."
4414 msgstr ""
4415 "Después del nombre de las variables se esperan especificaciones en formato "
4416 "tipo-SPSS o tipo-Fortran."
3877 msgid "SPSS-like or Fortran-like format specification expected after variable names."
3878 msgstr "Después del nombre de las variables se esperan especificaciones en formato tipo-SPSS o tipo-Fortran."
44173879
44183880 #: src/language/data-io/placement-parser.c:118
44193881 #, c-format
44203882 msgid "The %d columns %d-%d can't be evenly divided into %zu fields."
4421 msgstr ""
4422 "Las %d columnas %d-%d no pueden ser uniformemente dividas entre los campos "
4423 "%zu."
3883 msgstr "Las %d columnas %d-%d no pueden ser uniformemente dividas entre los campos %zu."
44243884
44253885 #: src/language/data-io/placement-parser.c:302
44263886 msgid "Column positions for fields must be positive."
44323892
44333893 #: src/language/data-io/placement-parser.c:343
44343894 msgid "The ending column for a field must be greater than the starting column."
4435 msgstr ""
4436 "La columna final de un campo tiene que ser mayor que la columna de inicio."
3895 msgstr "La columna final de un campo tiene que ser mayor que la columna de inicio."
44373896
44383897 #: src/language/data-io/print-space.c:115
44393898 msgid "The expression on PRINT SPACE evaluated to the system-missing value."
4440 msgstr ""
4441 "La expresión en PRINT SPACE se evalúa por el sistema de valores perdidos."
3899 msgstr "La expresión en PRINT SPACE se evalúa por el sistema de valores perdidos."
44423900
44433901 #: src/language/data-io/print-space.c:118
44443902 #, c-format
44523910 #: src/language/data-io/print.c:267
44533911 #, c-format
44543912 msgid "Output calls for %d records but %zu specified on RECORDS subcommand."
4455 msgstr ""
4456 "Resultados obtenidos para %d registros, pero %zu especificados en el "
4457 "subcomando RECORDS."
3913 msgstr "Resultados obtenidos para %d registros, pero %zu especificados en el subcomando RECORDS."
44583914
44593915 #: src/language/data-io/print.c:436
44603916 #, c-format
44833939
44843940 #: src/language/data-io/trim.c:89
44853941 #, c-format
4486 msgid ""
4487 "Cannot rename %s as %s because there already exists a variable named %s. To "
4488 "rename variables with overlapping names, use a single RENAME subcommand such "
4489 "as `/RENAME (A=B)(B=C)(C=A)', or equivalently, `/RENAME (A B C=B C A)'."
4490 msgstr ""
4491 "No se puede cambiar el nombre %s por %s porque ya existe una variable "
4492 "denominada %s. Para renombrar variables con nombres coincidentes, utilice "
4493 "un sólo subcomando RENAME como `/RENAME (A=B)(B=C)(C=A)', o "
4494 "equivalentemente, `/RENAME (A B C=B C A)'."
3942 msgid "Cannot rename %s as %s because there already exists a variable named %s. To rename variables with overlapping names, use a single RENAME subcommand such as `/RENAME (A=B)(B=C)(C=A)', or equivalently, `/RENAME (A B C=B C A)'."
3943 msgstr "No se puede cambiar el nombre %s por %s porque ya existe una variable denominada %s. Para renombrar variables con nombres coincidentes, utilice un sólo subcomando RENAME como `/RENAME (A=B)(B=C)(C=A)', o equivalentemente, `/RENAME (A B C=B C A)'."
44953944
44963945 #: src/language/data-io/trim.c:123
44973946 #, c-format
4498 msgid ""
4499 "Number of variables on left side of `=' (%zu) does not match number of "
4500 "variables on right side (%zu), in parenthesized group %d of RENAME "
4501 "subcommand."
4502 msgstr ""
4503 "El número de variables en el lado izquierdo de `=' (%zu) no coincide con el "
4504 "número de variables en el lado derecho (%zu), en el grupo entre paréntesis "
4505 "%d del subcomando RENAME."
3947 msgid "Number of variables on left side of `=' (%zu) does not match number of variables on right side (%zu), in parenthesized group %d of RENAME subcommand."
3948 msgstr "El número de variables en el lado izquierdo de `=' (%zu) no coincide con el número de variables en el lado derecho (%zu), en el grupo entre paréntesis %d del subcomando RENAME."
45063949
45073950 #: src/language/data-io/trim.c:136
45083951 #, c-format
45233966 msgstr "Nombre de la variable %s duplicado."
45243967
45253968 #: src/language/expressions/helpers.c:41
4526 msgid ""
4527 "One of the arguments to a DATE function is not an integer. The result will "
4528 "be system-missing."
4529 msgstr ""
4530 "Uno de los argumentos para función DATE no es un entero. El resultado será "
4531 "perdido por el sistema."
3969 msgid "One of the arguments to a DATE function is not an integer. The result will be system-missing."
3970 msgstr "Uno de los argumentos para función DATE no es un entero. El resultado será perdido por el sistema."
45323971
45333972 #: src/language/expressions/helpers.c:69
4534 msgid ""
4535 "The week argument to DATE.WKYR is not an integer. The result will be system-"
4536 "missing."
4537 msgstr ""
4538 "El argumento de semana para DATE.WKYR no es un entero. El resultado será "
4539 "perdido del sistema."
3973 msgid "The week argument to DATE.WKYR is not an integer. The result will be system-missing."
3974 msgstr "El argumento de semana para DATE.WKYR no es un entero. El resultado será perdido del sistema."
45403975
45413976 #: src/language/expressions/helpers.c:75
4542 msgid ""
4543 "The week argument to DATE.WKYR is outside the acceptable range of 1 to 53. "
4544 "The result will be system-missing."
4545 msgstr ""
4546 "El argumento de semana para DATE.WKYR está fuera del intervalo aceptable "
4547 "entre 1 y 53. El resultado será perdido del sistema."
3977 msgid "The week argument to DATE.WKYR is outside the acceptable range of 1 to 53. The result will be system-missing."
3978 msgstr "El argumento de semana para DATE.WKYR está fuera del intervalo aceptable entre 1 y 53. El resultado será perdido del sistema."
45483979
45493980 #: src/language/expressions/helpers.c:97
4550 msgid ""
4551 "The day argument to DATE.YRDAY is not an integer. The result will be system-"
4552 "missing."
4553 msgstr ""
4554 "El argumento de día para DATE.YRDAY no es un entero. El resultado será "
4555 "perdido del sistema."
3981 msgid "The day argument to DATE.YRDAY is not an integer. The result will be system-missing."
3982 msgstr "El argumento de día para DATE.YRDAY no es un entero. El resultado será perdido del sistema."
45563983
45573984 #: src/language/expressions/helpers.c:103
4558 msgid ""
4559 "The day argument to DATE.YRDAY is outside the acceptable range of 1 to 366. "
4560 "The result will be system-missing."
4561 msgstr ""
4562 "El argumento de día para DATE.YRDAY está fuera del intervalo aceptable entre "
4563 "1 y 366. El resultado será perdido del sistema."
3985 msgid "The day argument to DATE.YRDAY is outside the acceptable range of 1 to 366. The result will be system-missing."
3986 msgstr "El argumento de día para DATE.YRDAY está fuera del intervalo aceptable entre 1 y 366. El resultado será perdido del sistema."
45643987
45653988 #: src/language/expressions/helpers.c:125
4566 msgid ""
4567 "The year argument to YRMODA is greater than 47516. The result will be "
4568 "system-missing."
4569 msgstr ""
4570 "El argumento año para YRMODA es más grande que 47516. El resultado será "
4571 "perdido del sistema."
3989 msgid "The year argument to YRMODA is greater than 47516. The result will be system-missing."
3990 msgstr "El argumento año para YRMODA es más grande que 47516. El resultado será perdido del sistema."
45723991
45733992 #. TRANSLATORS: Don't translate the the actual unit names `weeks', `days' etc
45743993 #. They must remain in their original English.
45753994 #: src/language/expressions/helpers.c:180
45763995 #, c-format
4577 msgid ""
4578 "Unrecognized date unit `%.*s'. Valid date units are `years', `quarters', "
4579 "`months', `weeks', `days', `hours', `minutes', and `seconds'."
4580 msgstr ""
4581 "Unidad de fecha `%.*s' no reconocida. Las unidades de fecha válidas son "
4582 "`años', `trimestres', `meses', `semanas', `días', `horas', `minutos', y "
4583 "`segundos'."
3996 msgid "Unrecognized date unit `%.*s'. Valid date units are `years', `quarters', `months', `weeks', `days', `hours', `minutes', and `seconds'."
3997 msgstr "Unidad de fecha `%.*s' no reconocida. Las unidades de fecha válidas son `años', `trimestres', `meses', `semanas', `días', `horas', `minutos', y `segundos'."
45843998
45853999 #: src/language/expressions/helpers.c:330
45864000 msgid "Invalid DATESUM method. Valid choices are `closest' and `rollover'."
4587 msgstr ""
4588 "Método DATESUM inválido. Las opciones válidas son `cercana' y `cumplida'."
4001 msgstr "Método DATESUM inválido. Las opciones válidas son `cercana' y `cumplida'."
45894002
45904003 #: src/language/expressions/parse.c:260
45914004 #, c-format
4592 msgid ""
4593 "Type mismatch: expression has %s type, but a numeric value is required here."
4594 msgstr ""
4595 "Incompatibilidad de tipo: la expresión tiene tipo %s, pero aquí se pide un "
4596 "valor numérico."
4005 msgid "Type mismatch: expression has %s type, but a numeric value is required here."
4006 msgstr "Incompatibilidad de tipo: la expresión tiene tipo %s, pero aquí se pide un valor numérico."
45974007
45984008 #: src/language/expressions/parse.c:272
45994009 #, c-format
4600 msgid ""
4601 "Type mismatch: expression has %s type, but a string value is required here."
4602 msgstr ""
4603 "Incompatibilidad de tipo: la expresión tiene tipo %s, pero aquí se pide un "
4604 "valor de cadena."
4010 msgid "Type mismatch: expression has %s type, but a string value is required here."
4011 msgstr "Incompatibilidad de tipo: la expresión tiene tipo %s, pero aquí se pide un valor de cadena."
46054012
46064013 #: src/language/expressions/parse.c:434
46074014 #, c-format
46084015 msgid "Type mismatch while applying %s operator: cannot convert %s to %s."
4609 msgstr ""
4610 "Incompatibilidad de los tipos mientras se aplica el operador %s: no se puede "
4611 "convertir %s en %s."
4016 msgstr "Incompatibilidad de los tipos mientras se aplica el operador %s: no se puede convertir %s en %s."
46124017
46134018 #: src/language/expressions/parse.c:648
4614 msgid ""
4615 "Chaining relational operators (e.g. `a < b < c') will not produce the "
4616 "mathematically expected result. Use the AND logical operator to fix the "
4617 "problem (e.g. `a < b AND b < c'). If chaining is really intended, "
4618 "parentheses will disable this warning (e.g. `(a < b) < c'.)"
4619 msgstr ""
4620 "Los operadores relacionales de encadenamiento (p.e. `a < b < c') no "
4621 "produciran el resultado esperado matemáticamente. Utilizar el operador "
4622 "lógico AND para solucionar el problema (p.e. `a < b AND b < c'). Si el "
4623 "encadenamiento es realmente intencionado, los paréntesis desactivaran esta "
4624 "alerta (p.e. `(a < b) < c'.)"
4019 msgid "Chaining relational operators (e.g. `a < b < c') will not produce the mathematically expected result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < c'). If chaining is really intended, parentheses will disable this warning (e.g. `(a < b) < c'.)"
4020 msgstr "Los operadores relacionales de encadenamiento (p.e. `a < b < c') no produciran el resultado esperado matemáticamente. Utilizar el operador lógico AND para solucionar el problema (p.e. `a < b AND b < c'). Si el encadenamiento es realmente intencionado, los paréntesis desactivaran esta alerta (p.e. `(a < b) < c'.)"
46254021
46264022 #: src/language/expressions/parse.c:750
4627 msgid ""
4628 "The exponentiation operator (`**') is left-associative, even though right-"
4629 "associative semantics are more useful. That is, `a**b**c' equals `(a**b)"
4630 "**c', not as `a**(b**c)'. To disable this warning, insert parentheses."
4631 msgstr ""
4632 "El operador de exponenciación (`**') aparece a la izquierda, aunque si "
4633 "aparece a la derecha es más útil. Es decir, `a**b**c' equivale a `(a**b)"
4634 "**c', no a `a**(b**c)'. Para desactivar esta alerta, insertar paréntesis."
4023 msgid "The exponentiation operator (`**') is left-associative, even though right-associative semantics are more useful. That is, `a**b**c' equals `(a**b)**c', not as `a**(b**c)'. To disable this warning, insert parentheses."
4024 msgstr "El operador de exponenciación (`**') aparece a la izquierda, aunque si aparece a la derecha es más útil. Es decir, `a**b**c' equivale a `(a**b)**c', no a `a**(b**c)'. Para desactivar esta alerta, insertar paréntesis."
46354025
46364026 #: src/language/expressions/parse.c:830
46374027 #, c-format
46704060
46714061 #: src/language/expressions/parse.c:1137
46724062 #, c-format
4673 msgid ""
4674 "With %s, using minimum valid argument count of %d does not make sense when "
4675 "passing only %d arguments in list."
4676 msgstr ""
4677 "Con %s, no tiene sentido utilizar %d como recuento mínimo de argumento "
4678 "válido si se pasan únicamente %d argumentos en la lista."
4063 msgid "With %s, using minimum valid argument count of %d does not make sense when passing only %d arguments in list."
4064 msgstr "Con %s, no tiene sentido utilizar %d como recuento mínimo de argumento válido si se pasan únicamente %d argumentos en la lista."
46794065
46804066 #: src/language/expressions/parse.c:1191
46814067 #, c-format
47264112 msgstr "escribiendo en un archivo temporal"
47274113
47284114 #: src/libpspp/inflate.c:89
4729 #, fuzzy, c-format
4115 #, c-format
47304116 msgid "Cannot initialize inflator: %s"
4731 msgstr "no puede inicializar el controlador de salida `%s' de la clase `%s'"
4117 msgstr "No se puede inicializar el inflador: %s"
47324118
47334119 #: src/libpspp/inflate.c:144
4734 #, fuzzy, c-format
4120 #, c-format
47354121 msgid "Error inflating: %s"
4736 msgstr "error en crear \"%s\""
4122 msgstr "Error generando: %s"
47374123
47384124 #: src/libpspp/message.c:85
47394125 msgid "error"
47504136 #: src/libpspp/message.c:280
47514137 #, c-format
47524138 msgid "Notes (%d) exceed limit (%d). Suppressing further notes."
4753 msgstr ""
4754 "Las notas (%d) han superado el límite (%d). Se suprimen las posteriores "
4755 "notas."
4139 msgstr "Las notas (%d) han superado el límite (%d). Se suprimen las posteriores notas."
47564140
47574141 #: src/libpspp/message.c:288
47584142 #, c-format
47594143 msgid "Warnings (%d) exceed limit (%d). Syntax processing will be halted."
4760 msgstr ""
4761 "Las advertencias (%d) han superado el límite (%d). Se detiene el "
4762 "procesamiento de sintaxis."
4144 msgstr "Las advertencias (%d) han superado el límite (%d). Se detiene el procesamiento de sintaxis."
47634145
47644146 #: src/libpspp/message.c:291
47654147 #, c-format
47664148 msgid "Errors (%d) exceed limit (%d). Syntax processing will be halted."
4767 msgstr ""
4768 "Los errores (%d) han superado el límite (%d). Se detiene el procesamiento de "
4769 "sintaxis."
4770
4771 #: src/libpspp/zip-reader.c:88
4149 msgstr "Los errores (%d) han superado el límite (%d). Se detiene el procesamiento de sintaxis."
4150
4151 #: src/libpspp/zip-reader.c:87
47724152 #, c-format
47734153 msgid "Unsupported compression type (%d)"
4774 msgstr ""
4775
4776 #: src/libpspp/zip-reader.c:201
4154 msgstr "Tipo de compresión no definido (%d)"
4155
4156 #: src/libpspp/zip-reader.c:181
47774157 #, c-format
47784158 msgid "Corrupt file at 0x%llx: Expected %<PRIx32>; got %<PRIx32>"
4779 msgstr ""
4780
4781 #: src/libpspp/zip-reader.c:325
4159 msgstr "Archivo corrompido en 0x%llx: Se esperaba %<PRIx32>; se encontró %<PRIx32>"
4160
4161 #: src/libpspp/zip-reader.c:312
47824162 msgid "Cannot find central directory"
4783 msgstr ""
4784
4785 #: src/libpspp/zip-reader.c:334
4786 #, fuzzy, c-format
4163 msgstr "No se pudo encontrar el directorio central"
4164
4165 #: src/libpspp/zip-reader.c:321
4166 #, c-format
47874167 msgid "Failed to seek to end of central directory record: %s"
4788 msgstr "error al crear el directorio temporal"
4789
4790 #: src/libpspp/zip-reader.c:360
4791 #, fuzzy, c-format
4168 msgstr "Fallo al buscar el registro al final del directorio central: %s"
4169
4170 #: src/libpspp/zip-reader.c:347
4171 #, c-format
47924172 msgid "Failed to seek to central directory: %s"
4793 msgstr "error al crear el directorio temporal"
4794
4795 #: src/libpspp/zip-reader.c:412
4173 msgstr "Fallo al buscar el directorio central: %s"
4174
4175 #: src/libpspp/zip-reader.c:399
47964176 #, c-format
47974177 msgid "Failed to seek to start of member `%s': %s"
4798 msgstr ""
4799
4800 #: src/libpspp/zip-reader.c:443
4801 #, c-format
4802 msgid ""
4803 "Name mismatch in zip archive. Central directory says `%s'; local file header "
4804 "says `%s'"
4805 msgstr ""
4178 msgstr "Fallo al buscar el inicio del miembro `%s': %s"
4179
4180 #: src/libpspp/zip-reader.c:430
4181 #, c-format
4182 msgid "Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"
4183 msgstr "Nombre incorrecto en archivo zip. El directorio central dice `%s'; la cabezera del archivo local dice `%s'"
48064184
48074185 #: src/libpspp/zip-writer.c:92
48084186 #, c-format
48414219
48424220 #: src/output/ascii.c:331
48434221 #, c-format
4844 msgid ""
4845 "ascii: page excluding margins and headers must be at least %d characters "
4846 "wide by %d lines long, but as configured is only %d characters by %d lines"
4847 msgstr ""
4848 "ascii: excluyendo los margenes y encabezamientos la página debe tener como "
4849 "mínimo %d caracteres de ancho por %d líneas de largo, pero tal como está "
4850 "configurada, sólo hay %d caracteres y %d líneas"
4222 msgid "ascii: page excluding margins and headers must be at least %d characters wide by %d lines long, but as configured is only %d characters by %d lines"
4223 msgstr "ascii: excluyendo los margenes y encabezamientos la página debe tener como mínimo %d caracteres de ancho por %d líneas de largo, pero tal como está configurada, sólo hay %d caracteres y %d líneas"
48514224
48524225 #: src/output/ascii.c:377
48534226 #, c-format
48784251 #. TRANSLATORS: Don't translate the words `terminal' or `listing'.
48794252 #: src/output/driver.c:319
48804253 #, c-format
4881 msgid ""
4882 "%s is not a valid device type (the choices are `terminal' and `listing')"
4883 msgstr ""
4884 "%s no es un tipo de dispositivo válido (las opciones son `terminal' y "
4885 "`listing')"
4254 msgid "%s is not a valid device type (the choices are `terminal' and `listing')"
4255 msgstr "%s no es un tipo de dispositivo válido (las opciones son `terminal' y `listing')"
48864256
48874257 #: src/output/driver.c:332
48884258 #, c-format
49704340 #: src/output/options.c:326
49714341 #, c-format
49724342 msgid "%s: `%s' is `%s' but a file name that contains `#' is required."
4973 msgstr ""
4974 "%s: `%s' es `%s', pero se requiere un nombre de fichero que contenga `#'."
4343 msgstr "%s: `%s' es `%s', pero se requiere un nombre de fichero que contenga `#'."
49754344
49764345 #: src/output/tab.c:207
49774346 #, c-format
49784347 msgid "bad vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
4979 msgstr ""
4980 "incorrecta vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) en tabla de medida (%d,"
4981 "%d)\n"
4348 msgstr "incorrecta vline: x=%d+%d=%d y=(%d+%d=%d,%d+%d=%d) en tabla de medida (%d,%d)\n"
49824349
49834350 #: src/output/tab.c:245
49844351 #, c-format
49854352 msgid "bad hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d in table size (%d,%d)\n"
4986 msgstr ""
4987 "incorrecta hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d en tabla de medida (%d,"
4988 "%d)\n"
4353 msgstr "incorrecta hline: x=(%d+%d=%d,%d+%d=%d) y=%d+%d=%d en tabla de medida (%d,%d)\n"
49894354
49904355 #: src/output/tab.c:289
49914356 #, c-format
4992 msgid ""
4993 "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
4994 msgstr ""
4995 "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) en taula amb mida (%d,%d)\n"
4357 msgid "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) in table size (%d,%d)\n"
4358 msgstr "bad box: (%d+%d=%d,%d+%d=%d)-(%d+%d=%d,%d+%d=%d) en taula amb mida (%d,%d)\n"
49964359
49974360 #: src/output/cairo.c:225
49984361 #, c-format
50064369
50074370 #: src/output/cairo.c:417
50084371 #, c-format
5009 msgid ""
5010 "The defined page is not wide enough to hold at least %d characters in the "
5011 "default font. In fact, there's only room for %d characters."
5012 msgstr ""
5013 "La página definida no es suficientemente ancha como para contener al menos "
5014 "%d caracteres de la fuente por defecto. De hecho, sólo hay espacio para %d "
5015 "caracteres."
4372 msgid "The defined page is not wide enough to hold at least %d characters in the default font. In fact, there's only room for %d characters."
4373 msgstr "La página definida no es suficientemente ancha como para contener al menos %d caracteres de la fuente por defecto. De hecho, sólo hay espacio para %d caracteres."
50164374
50174375 #: src/output/cairo.c:427
50184376 #, c-format
5019 msgid ""
5020 "The defined page is not long enough to hold at least %d lines in the default "
5021 "font. In fact, there's only room for %d lines."
5022 msgstr ""
5023 "La página definida no es suficientemente larga como para contener al menos "
5024 "%d líneas en la fuente por defecto. De hecho, sólo hay espacio para %d "
5025 "líneas."
4377 msgid "The defined page is not long enough to hold at least %d lines in the default font. In fact, there's only room for %d lines."
4378 msgstr "La página definida no es suficientemente larga como para contener al menos %d líneas en la fuente por defecto. De hecho, sólo hay espacio para %d líneas."
50264379
50274380 #: src/output/cairo.c:478
50284381 #, c-format
50944447 msgstr "Error detectado mientras está activo ERROR=STOP."
50954448
50964449 #: src/ui/terminal/main.c:153
5097 msgid ""
5098 "Stopping syntax file processing here to avoid a cascade of dependent command "
5099 "failures."
5100 msgstr ""
5101 "Deteniendo el procesamiento del archivo de sintaxis aquí para evitar una "
5102 "cascada de errores derivados."
4450 msgid "Stopping syntax file processing here to avoid a cascade of dependent command failures."
4451 msgstr "Deteniendo el procesamiento del archivo de sintaxis aquí para evitar una cascada de errores derivados."
51034452
51044453 #: src/ui/terminal/terminal-opts.c:122
51054454 #, c-format
51524501 "PSPP, un programa de análisis estadístic para datos de muestreo.\n"
51534502 "Uso: %s [OPTION]... FILE...\n"
51544503 "\n"
5155 "Los arguments para options largas también se aplican a opciones cortas "
5156 "equivalentes.\n"
4504 "Los arguments para options largas también se aplican a opciones cortas equivalentes.\n"
51574505 "\n"
51584506 "Opciones de salida:\n"
5159 " -o, --output=FILE salida a FILE, format por defecto según el "
5160 "nombre de FILE\n"
4507 " -o, --output=FILE salida a FILE, format por defecto según el nombre de FILE\n"
51614508 " -O format=FORMAT sobreescribir el formato por el previo -o\n"
5162 " -O OPTION=VALUE establecer opciones de salida a las previas "
5163 "personalizadas -o\n"
5164 " -O device={terminal|listing} sustituir el tipo de dispositivo por el "
5165 "previo -o\n"
4509 " -O OPTION=VALUE establecer opciones de salida a las previas personalizadas -o\n"
4510 " -O device={terminal|listing} sustituir el tipo de dispositivo por el previo -o\n"
51664511 " -e, --error-file=FILE añade errores, advertencias, y notas a FILE\n"
51674512 " --no-output desactivar el dispositivo de salida por defecto\n"
51684513 "Formatos de salida soportados: %s\n"
51724517 " -I-, --no-include limpiar la ruta de búsqueda\n"
51734518 " -r, --no-statrc desactivar el archivo que ejectuta rc al inicio\n"
51744519 " -a, --algorithm={compatible|enhanced}\n"
5175 " establecer a `compatible' si se quiere una "
5176 "salida\n"
4520 " establecer a `compatible' si se quiere una salida\n"
51774521 " calculada a partir de algoritmos rotos\n"
51784522 " -x, --syntax={compatible|enhanced}\n"
5179 " establecer a `compatible' para desactivar las "
5180 "extensiones PSPP\n"
4523 " establecer a `compatible' para desactivar las extensiones PSPP\n"
51814524 " -b, --batch interpretar la sintaxis en modo paquete\n"
51824525 " -i, --interactive interpretar la sintaxis en modo interactivo\n"
5183 " --syntax-encoding=ENCODING especificar codificación para los archivos de "
5184 "sintaxis\n"
4526 " --syntax-encoding=ENCODING especificar codificación para los archivos de sintaxis\n"
51854527 " -s, --safer no permitir algunas operaciones poco seguras\n"
51864528 "Ruta de búsqueda por defecto: %s\n"
51874529 "\n"
51894531 " -h, --help muestra esta ayuda y acaba\n"
51904532 " -V, --version información sobre versión de salida y acaba\n"
51914533 "\n"
5192 "Los argumentos sin opción son interpretados como archivos de sintaxis para "
5193 "ser ejecutados.\n"
4534 "Los argumentos sin opción son interpretados como archivos de sintaxis para ser ejecutados.\n"
51944535
51954536 #: src/ui/terminal/terminal.c:62
51964537 #, c-format
52124553 msgstr "Archivo de destino para agregación"
52134554
52144555 #: src/ui/gui/aggregate-dialog.c:174 src/ui/gui/psppire-data-window.c:504
5215 #: src/ui/gui/psppire-window.c:733
4556 #: src/ui/gui/psppire-window.c:754
52164557 msgid "System Files (*.sav)"
52174558 msgstr "Archivos de Sistema (*.sav)"
52184559
52194560 #: src/ui/gui/aggregate-dialog.c:179 src/ui/gui/psppire-data-window.c:509
5220 #: src/ui/gui/psppire-window.c:738
4561 #: src/ui/gui/psppire-window.c:759
52214562 msgid "Portable Files (*.por) "
52224563 msgstr "Archivos Portátiles (*.por) "
52234564
53174658 msgstr "Expresión regular incorrecta: %s"
53184659
53194660 #: src/ui/gui/factor-dialog.c:348
5320 #, fuzzy, c-format
4661 #, c-format
53214662 msgid "_Eigenvalues over %4.2f times the mean eigenvalue"
5322 msgstr "Algunos valores propios superan %4.2f veces el valor-propio medio"
4663 msgstr "_Valores propios por encima de %4.2f veces el valor-propio medio"
53234664
53244665 #: src/ui/gui/frequencies-dialog.c:45
53254666 msgid "Standard error of the mean"
53494690
53504691 #: src/ui/gui/help-menu.c:106
53514692 #, c-format
5352 msgid ""
5353 "Cannot open reference manual: %s. The PSPP user manual is also available at "
5354 "%s"
5355 msgstr ""
5356 "No puede abrirse el manual de referencia: %s. El manual de usuario de PSPP "
5357 "también está disponible en %s"
4693 msgid "Cannot open reference manual: %s. The PSPP user manual is also available at %s"
4694 msgstr "No puede abrirse el manual de referencia: %s. El manual de usuario de PSPP también está disponible en %s"
53584695
53594696 #: src/ui/gui/help-menu.c:133
53604697 msgid "_Help"
53654702 msgstr "Manual de _Referencia"
53664703
53674704 #: src/ui/gui/main.c:83
5368 #, fuzzy, c-format
4705 #, c-format
53694706 msgid ""
53704707 "PSPPIRE, a GUI for PSPP, a program for statistical analysis of sample data.\n"
53714708 "Usage: %s [OPTION]... FILE\n"
53914728 " -h, --help display this help and exit\n"
53924729 " -V, --version output version information and exit\n"
53934730 "\n"
5394 "A non-option argument is interpreted as a .sav file, a .por file or a "
5395 "syntax\n"
5396 "file to load.\n"
4731 "A non-option argument is interpreted as a .sav or .por file to load.\n"
53974732 msgstr ""
5398 "PSPPIRE, un entorno gráfico (GUI) para PSPP, un programa de análisis "
5399 "estadístico para datos de muestreo.\n"
4733 "PSPPIRE, un entorno gráfico (GUI) para PSPP, un programa de análisis estadístico para datos de muestreo.\n"
54004734 "Uso: %s [OPTION]... FILE\n"
54014735 "\n"
5402 "Argumentos para opciones largas también se aplican a opciones cortas "
5403 "equivalentes.\n"
4736 "Argumentos para opciones largas también se aplican a opciones cortas equivalentes.\n"
54044737 "\n"
54054738 "Opciones gráficas:\n"
5406 " -q, --no-splash no mostrar la pantalla inicial druante el "
5407 "arranque\n"
4739 " -q, --no-splash no mostrar la pantalla inicial druante el arranque\n"
54084740 "\n"
54094741 "%sOpciones de lenguaje:\n"
54104742 " -I, --include=DIR añadir DIR a la ruta de búsqueda\n"
54114743 " -I-, --no-include limpiar la ruta de búsqueda\n"
54124744 " -a, --algorithm={compatible|enhanced}\n"
5413 " establecer a `compatible' si se desean "
5414 "resultados\n"
4745 " establecer a `compatible' si se desean resultados\n"
54154746 " calculados mediante algoritmos rotos\n"
54164747 " -x, --syntax={compatible|enhanced}\n"
5417 " establecer a `compatible' para desactivar "
5418 "extensiones PSPP\n"
4748 " establecer a `compatible' para desactivar extensiones PSPP\n"
54194749 " -i, --interactive interpretar la sintaxis en modo interactivo\n"
54204750 " -s, --safer no permitir algunas operaciones poco seguras\n"
54214751 "Ruta de búsqueda por defecto: %s\n"
54244754 " -h, --help muestra esta ayuda y acaba\n"
54254755 " -V, --version información de versión de salida y acaba\n"
54264756 "\n"
5427 "Un argumento sin opciones es interpretado como un archivo .sav or .por para "
5428 "ser cargado.\n"
4757 "Un argumento sin opciones es interpretado como un archivo .sav or .por para ser cargado.\n"
54294758
54304759 #: src/ui/gui/missing-val-dialog.c:114 src/ui/gui/missing-val-dialog.c:167
54314760 msgid "Incorrect value for variable type"
54404769 msgid "Contrast %d of %d"
54414770 msgstr "Contraste %d de %d"
54424771
5443 #: src/ui/gui/psppire.c:242
4772 #: src/ui/gui/psppire.c:227
54444773 msgid "_Reset"
54454774 msgstr "_Reiniciar"
54464775
5447 #: src/ui/gui/psppire.c:243
4776 #: src/ui/gui/psppire.c:228
54484777 msgid "_Select"
54494778 msgstr "_Selecionar"
54504779
54954824 msgstr "Guardar"
54964825
54974826 #: src/ui/gui/psppire-data-window.c:514 src/ui/gui/psppire-syntax-window.c:608
5498 #: src/ui/gui/psppire-window.c:749
4827 #: src/ui/gui/psppire-window.c:770
54994828 msgid "All Files"
55004829 msgstr "Todos los archivos"
55014830
55084837 msgstr "Eliminar el archivo de datos existente?"
55094838
55104839 #: src/ui/gui/psppire-data-window.c:588
5511 #, fuzzy, c-format
5512 msgid ""
5513 "Renaming \"%s\" to \"%s\" will destroy the existing dataset named \"%s\". "
5514 "Are you sure that you want to do this?"
5515 msgstr ""
5516 "Renombrar \"%s\" como \"%s\" eliminará el archivo existente llamado \"%s\". "
5517 "Está seguro de querer hacer eso?"
4840 #, c-format
4841 msgid "Renaming \"%s\" to \"%s\" will delete destroy the existing dataset named \"%s\". Are you sure that you want to do this?"
4842 msgstr "Renombrar \"%s\" como \"%s\" eliminará el archivo existente llamado \"%s\". Está seguro de querer hacer eso?"
55184843
55194844 #: src/ui/gui/psppire-data-window.c:616
55204845 #, c-format
55804905 msgstr "VAR%05d"
55814906
55824907 #: src/ui/gui/psppire-dict.c:537
5583 #, fuzzy
55844908 msgid "Duplicate variable name."
5585 msgstr "Nombre de la variable %s duplicado."
4909 msgstr "Nombre de la variable duplicado."
55864910
55874911 #: src/ui/gui/psppire-encoding-selector.c:153
55884912 msgid "Automatically Detect"
5589 msgstr ""
4913 msgstr "Detección Automática"
55904914
55914915 #: src/ui/gui/psppire-encoding-selector.c:154
5592 #, fuzzy
55934916 msgid "Locale Encoding"
5594 msgstr "Tipo Little-Endian"
4917 msgstr "Codificación Local"
55954918
55964919 #: src/ui/gui/psppire-encoding-selector.c:158
55974920 msgid "Arabic"
5598 msgstr ""
4921 msgstr "Arábigo"
55994922
56004923 #: src/ui/gui/psppire-encoding-selector.c:160
56014924 msgid "Armenian"
5602 msgstr ""
4925 msgstr "Armenio"
56034926
56044927 #: src/ui/gui/psppire-encoding-selector.c:161
56054928 msgid "Baltic"
5606 msgstr ""
4929 msgstr "Báltico"
56074930
56084931 #: src/ui/gui/psppire-encoding-selector.c:163
56094932 msgid "Celtic"
5610 msgstr ""
4933 msgstr "Céltico"
56114934
56124935 #: src/ui/gui/psppire-encoding-selector.c:164
56134936 msgid "Central European"
5614 msgstr ""
4937 msgstr "Central Europeo"
56154938
56164939 #: src/ui/gui/psppire-encoding-selector.c:166
56174940 msgid "Chinese Simplified"
5618 msgstr ""
4941 msgstr "Chino Simplificado"
56194942
56204943 #: src/ui/gui/psppire-encoding-selector.c:168
56214944 msgid "Chinese Traditional"
5622 msgstr ""
4945 msgstr "Chino Tradicional"
56234946
56244947 #: src/ui/gui/psppire-encoding-selector.c:170
56254948 msgid "Croatian"
5626 msgstr ""
4949 msgstr "Croata"
56274950
56284951 #: src/ui/gui/psppire-encoding-selector.c:171
56294952 msgid "Cyrillic"
5630 msgstr ""
4953 msgstr "Cirílico"
56314954
56324955 #: src/ui/gui/psppire-encoding-selector.c:173
56334956 msgid "Cyrillic/Russian"
5634 msgstr ""
4957 msgstr "Cirílico/Ruso"
56354958
56364959 #: src/ui/gui/psppire-encoding-selector.c:174
56374960 msgid "Cyrillic/Ukrainian"
5638 msgstr ""
4961 msgstr "Cirílico/Ucraniano"
56394962
56404963 #: src/ui/gui/psppire-encoding-selector.c:176
56414964 msgid "Georgian"
5642 msgstr ""
4965 msgstr "Georgiano"
56434966
56444967 #: src/ui/gui/psppire-encoding-selector.c:177
56454968 msgid "Greek"
5646 msgstr ""
4969 msgstr "Griego"
56474970
56484971 #: src/ui/gui/psppire-encoding-selector.c:178
56494972 msgid "Gujarati"
5650 msgstr ""
4973 msgstr "Gujarati"
56514974
56524975 #: src/ui/gui/psppire-encoding-selector.c:179
56534976 msgid "Gurmukhi"
5654 msgstr ""
4977 msgstr "Gurmukhi"
56554978
56564979 #: src/ui/gui/psppire-encoding-selector.c:180
56574980 msgid "Hebrew"
5658 msgstr ""
4981 msgstr "Hebreo"
56594982
56604983 #: src/ui/gui/psppire-encoding-selector.c:182
56614984 msgid "Hebrew Visual"
5662 msgstr ""
4985 msgstr "Hebreo Visual"
56634986
56644987 #: src/ui/gui/psppire-encoding-selector.c:183
56654988 msgid "Hindi"
5666 msgstr ""
4989 msgstr "Hindi"
56674990
56684991 #: src/ui/gui/psppire-encoding-selector.c:184
56694992 msgid "Icelandic"
5670 msgstr ""
4993 msgstr "Islandés"
56714994
56724995 #: src/ui/gui/psppire-encoding-selector.c:185
56734996 msgid "Japanese"
5674 msgstr ""
4997 msgstr "Japonés"
56754998
56764999 #: src/ui/gui/psppire-encoding-selector.c:187
56775000 msgid "Korean"
5678 msgstr ""
5001 msgstr "Coreano"
56795002
56805003 #: src/ui/gui/psppire-encoding-selector.c:189
56815004 msgid "Nordic"
5682 msgstr ""
5005 msgstr "Nórdico"
56835006
56845007 #: src/ui/gui/psppire-encoding-selector.c:190
56855008 msgid "Romanian"
5686 msgstr ""
5009 msgstr "Rumano"
56875010
56885011 #: src/ui/gui/psppire-encoding-selector.c:192
56895012 msgid "South European"
5690 msgstr ""
5013 msgstr "Sur Europeo"
56915014
56925015 #: src/ui/gui/psppire-encoding-selector.c:193
56935016 msgid "Thai"
5694 msgstr ""
5017 msgstr "Tailandés"
56955018
56965019 #: src/ui/gui/psppire-encoding-selector.c:195
56975020 msgid "Turkish"
5698 msgstr ""
5021 msgstr "Turco"
56995022
57005023 #: src/ui/gui/psppire-encoding-selector.c:197
57015024 msgid "Vietnamese"
5702 msgstr ""
5025 msgstr "Vietnamita"
57035026
57045027 #: src/ui/gui/psppire-encoding-selector.c:199
57055028 msgid "Western European"
5706 msgstr ""
5029 msgstr "Europeo Occidental"
57075030
57085031 #: src/ui/gui/psppire-encoding-selector.c:222
57095032 msgid "Character Encoding: "
5710 msgstr ""
5711
5712 #: src/ui/gui/psppire-means-layer.c:45
5713 #, fuzzy, c-format
5714 msgid "Layer %d of %d"
5715 msgstr "Contraste %d de %d"
5033 msgstr "Codificación de carácteres: "
57165034
57175035 #: src/ui/gui/psppire-output-window.c:358
57185036 msgid "Message"
5719 msgstr ""
5037 msgstr "Mensaje"
57205038
57215039 #: src/ui/gui/psppire-output-window.c:519
57225040 msgid "Infer file type from extension"
57725090 msgid "Save Syntax"
57735091 msgstr "Guardar sintaxis"
57745092
5775 #: src/ui/gui/psppire-syntax-window.c:602 src/ui/gui/psppire-window.c:743
5093 #: src/ui/gui/psppire-syntax-window.c:602 src/ui/gui/psppire-window.c:764
57765094 msgid "Syntax Files (*.sps) "
57775095 msgstr "Archivos de Sintàxis (*.sps) "
57785096
58555173 msgid "{%s,`%s'}_"
58565174 msgstr "{%s,`%s'}_"
58575175
5858 #: src/ui/gui/psppire-window.c:505
5176 #: src/ui/gui/psppire-window.c:526
58595177 #, c-format
58605178 msgid "Save the changes to `%s' before closing?"
58615179 msgstr "¿Guardar los cambios en `%s' antes de salir?"
58625180
5863 #: src/ui/gui/psppire-window.c:512
5864 #, c-format
5865 msgid ""
5866 "If you don't save, changes from the last %ld seconds will be permanently "
5867 "lost."
5868 msgstr ""
5869 "Si no se guarda ahora, los cambios de los últims %ld segundos se perderan "
5870 "permanentemente."
5871
5872 #: src/ui/gui/psppire-window.c:516
5181 #: src/ui/gui/psppire-window.c:533
5182 #, c-format
5183 msgid "If you don't save, changes from the last %ld seconds will be permanently lost."
5184 msgstr "Si no se guarda ahora, los cambios de los últims %ld segundos se perderan permanentemente."
5185
5186 #: src/ui/gui/psppire-window.c:537
58735187 msgid "Close _without saving"
58745188 msgstr "Cerrar sin guardar"
58755189
5876 #: src/ui/gui/psppire-window.c:716
5190 #: src/ui/gui/psppire-window.c:737
58775191 msgid "Open"
58785192 msgstr "Abrir"
58795193
5880 #: src/ui/gui/psppire-window.c:725
5194 #: src/ui/gui/psppire-window.c:746
58815195 msgid "Data and Syntax Files"
58825196 msgstr "Ficheros de Datos y Sintaxsi"
58835197
59405254
59415255 #: src/ui/gui/text-data-import-dialog.c:472
59425256 #, c-format
5943 msgid ""
5944 "Failed to read `%s', because it contains a line over %d bytes long and "
5945 "therefore appears not to be a text file."
5946 msgstr ""
5947 "Error leyendo `%s', porque contiene una linea más allá de %d bytes y por "
5948 "tanto parece que no es un archivo de texto."
5257 msgid "Failed to read `%s', because it contains a line over %d bytes long and therefore appears not to be a text file."
5258 msgstr "Error leyendo `%s', porque contiene una linea más allá de %d bytes y por tanto parece que no es un archivo de texto."
59495259
59505260 #: src/ui/gui/text-data-import-dialog.c:486
59515261 #, c-format
59725282
59735283 #: src/ui/gui/text-data-import-dialog.c:767
59745284 msgid ""
5975 "This assistant will guide you through the process of importing data into "
5976 "PSPP from a text file with one line per case, in which fields are separated "
5977 "by tabs, commas, or other delimiters.\n"
5285 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case, in which fields are separated by tabs, commas, or other delimiters.\n"
59785286 "\n"
59795287 msgstr ""
5980 "Este asistente te quiará a lo largo del proceso de importar datos en PSPP "
5981 "desde un archivo de texto con una línea por caso, en el que los campos "
5982 "estan separados por tabuladores, comas, u otros delimitadores.\n"
5288 "Este asistente te quiará a lo largo del proceso de importar datos en PSPP desde un archivo de texto con una línea por caso, en el que los campos estan separados por tabuladores, comas, u otros delimitadores.\n"
59835289 "\n"
59845290
59855291 #: src/ui/gui/text-data-import-dialog.c:773
59935299 #, c-format
59945300 msgid "The selected file contains approximately %lu line of text. "
59955301 msgid_plural "The selected file contains approximately %lu lines of text. "
5996 msgstr[0] ""
5997 "El archivo seleccionado contiene aproximadamente %lu línea de texto. "
5998 msgstr[1] ""
5999 "El archivo seleccionado contiene aproximadamente %lu líneas de texto. "
5302 msgstr[0] "El archivo seleccionado contiene aproximadamente %lu línea de texto. "
5303 msgstr[1] "El archivo seleccionado contiene aproximadamente %lu líneas de texto. "
60005304
60015305 #: src/ui/gui/text-data-import-dialog.c:787
60025306 #, c-format
6003 msgid ""
6004 "Only the first %zu line of the file will be shown for preview purposes in "
6005 "the following screens. "
6006 msgid_plural ""
6007 "Only the first %zu lines of the file will be shown for preview purposes in "
6008 "the following screens. "
6009 msgstr[0] ""
6010 "Únicamente la primera %zu líneas del archivo se previsualizaran en las "
6011 "siguientes pantallas. "
6012 msgstr[1] ""
6013 "Únicamente las primeras %zu líneas del archivo se previsualizaran en las "
6014 "siguientes pantallas. "
5307 msgid "Only the first %zu line of the file will be shown for preview purposes in the following screens. "
5308 msgid_plural "Only the first %zu lines of the file will be shown for preview purposes in the following screens. "
5309 msgstr[0] "Únicamente la primera %zu líneas del archivo se previsualizaran en las siguientes pantallas. "
5310 msgstr[1] "Únicamente las primeras %zu líneas del archivo se previsualizaran en las siguientes pantallas. "
60155311
60165312 #: src/ui/gui/text-data-import-dialog.c:794
60175313 msgid "You may choose below how much of the file should actually be imported."
6018 msgstr ""
6019 "Puedes escoger a continuación que parte del archivo va a ser importado."
5314 msgstr "Puedes escoger a continuación que parte del archivo va a ser importado."
60205315
60215316 #: src/ui/gui/text-data-import-dialog.c:877
60225317 msgid "Text"
60255320 #: src/ui/gui/text-data-import-dialog.c:1541
60265321 #: src/ui/gui/text-data-import-dialog.c:1787
60275322 msgid "This input line has too few separators to fill in this field."
6028 msgstr ""
6029 "Esta línea de entrada no tiene suficientes separadores para llenar el campo."
5323 msgstr "Esta línea de entrada no tiene suficientes separadores para llenar el campo."
60305324
60315325 #: src/ui/gui/text-data-import-dialog.c:1778
60325326 #, c-format
60435337 msgstr "Intervalo de Confianza: %2d %%"
60445338
60455339 #: src/ui/gui/t-test-paired-samples.c:93
6046 #, fuzzy
60475340 msgid "_Options"
6048 msgstr "Opciones"
5341 msgstr "_Opciones"
60495342
60505343 #: src/ui/gui/t-test-paired-samples.c:105
60515344 msgid "Paired Samples T Test"
60565349 msgstr "Tipo de Test"
60575350
60585351 #: src/ui/gui/npar-two-sample-related.c:136
6059 #, fuzzy
60605352 msgid "_Wilcoxon"
6061 msgstr "W de Wilcoxon"
5353 msgstr "_W de Wilcoxon"
60625354
60635355 #: src/ui/gui/npar-two-sample-related.c:137
60645356 msgid "_Sign"
6065 msgstr ""
5357 msgstr "_Signo"
60665358
60675359 #: src/ui/gui/npar-two-sample-related.c:138
60685360 msgid "_McNemar"
6069 msgstr ""
5361 msgstr "_McNemar"
60705362
60715363 #: src/ui/gui/npar-two-sample-related.c:153
6072 #, fuzzy
60735364 msgid "Two-Related-Samples Tests"
6074 msgstr "Prueba de muestras emparejadas"
5365 msgstr "Prueba para Dos muestras emparejadas"
60755366
60765367 #: src/ui/gui/val-labs-dialog.c:511
60775368 #, c-format
60885379 msgid "Weight cases by %s"
60895380 msgstr "Ponderar los casos por %s"
60905381
6091 #: src/language/utilities/set.q:159 src/language/utilities/set.q:166
6092 #, fuzzy, c-format
5382 #: src/language/utilities/set.q:156 src/language/utilities/set.q:163
5383 #, c-format
60935384 msgid "%s must be at least 1."
6094 msgstr "LENGTH debe ser como mínimo 1."
6095
6096 #: src/language/utilities/set.q:173 src/language/data-io/file-handle.q:102
6097 #, fuzzy, c-format
5385 msgstr "%s debe ser como mínimo 1."
5386
5387 #: src/language/utilities/set.q:170 src/language/data-io/file-handle.q:102
5388 #, c-format
60985389 msgid "%s must not be negative."
6099 msgstr "%s no es un nombre de variable."
6100
6101 #: src/language/utilities/set.q:192
5390 msgstr "%s no puedes ser negativo."
5391
5392 #: src/language/utilities/set.q:189
61025393 msgid "WORKSPACE must be at least 1MB"
61035394 msgstr "WORKSPACE debe ser como mínimo 1 Mb"
61045395
6105 #: src/language/utilities/set.q:194
6106 #, fuzzy
5396 #: src/language/utilities/set.q:191
61075397 msgid "WORKSPACE must be positive"
6108 msgstr "WORKSPACE debe ser como mínimo 1 Mb"
6109
6110 #: src/language/utilities/set.q:200 src/language/utilities/set.q:202
6111 #: src/language/utilities/set.q:204 src/language/utilities/set.q:206
6112 #: src/language/utilities/set.q:208 src/language/utilities/set.q:210
6113 #: src/language/utilities/set.q:212 src/language/utilities/set.q:214
6114 #: src/language/utilities/set.q:216 src/language/utilities/set.q:218
6115 #: src/language/utilities/set.q:220
5398 msgstr "WORKSPACE debe ser positivo"
5399
5400 #: src/language/utilities/set.q:197 src/language/utilities/set.q:199
5401 #: src/language/utilities/set.q:201 src/language/utilities/set.q:203
5402 #: src/language/utilities/set.q:205 src/language/utilities/set.q:207
5403 #: src/language/utilities/set.q:209 src/language/utilities/set.q:211
5404 #: src/language/utilities/set.q:213 src/language/utilities/set.q:215
5405 #: src/language/utilities/set.q:217
61165406 #, c-format
61175407 msgid "%s is obsolete."
61185408 msgstr "%s está obsoleto."
61195409
6120 #: src/language/utilities/set.q:226
5410 #: src/language/utilities/set.q:223
61215411 msgid "Active file compression is not implemented."
61225412 msgstr "La compresión de archivos no está implementada."
61235413
6124 #: src/language/utilities/set.q:373
5414 #: src/language/utilities/set.q:370
61255415 msgid "EPOCH must be 1500 or later."
61265416 msgstr "EPOCH debe ser 1500 o posterior."
61275417
6128 #: src/language/utilities/set.q:380
5418 #: src/language/utilities/set.q:377
61295419 msgid "expecting AUTOMATIC or year"
61305420 msgstr "esperando AUTOMATICA o año"
61315421
6132 #: src/language/utilities/set.q:408
5422 #: src/language/utilities/set.q:405
61335423 msgid "LENGTH must be at least 1."
61345424 msgstr "LENGTH debe ser como mínimo 1."
61355425
6136 #: src/language/utilities/set.q:444
5426 #: src/language/utilities/set.q:441
61375427 #, c-format
61385428 msgid "%s is not a recognized encoding or locale name"
61395429 msgstr "%s no es una codificación o un nombre local reconocido"
61405430
6141 #: src/language/utilities/set.q:505
5431 #: src/language/utilities/set.q:502
61425432 msgid "WIDTH must be at least 40."
61435433 msgstr "WIDTH debe ser como mínimo 40."
61445434
6145 #: src/language/utilities/set.q:532
6146 #, c-format
6147 msgid ""
6148 "FORMAT requires numeric output format as an argument. Specified format %s "
6149 "is of type string."
6150 msgstr ""
6151 "FORMAT requiere formato de resultado numérico como argumento. El formato %s "
6152 "especificado es de tipo cadena."
6153
6154 #: src/language/utilities/set.q:746
5435 #: src/language/utilities/set.q:529
5436 #, c-format
5437 msgid "FORMAT requires numeric output format as an argument. Specified format %s is of type string."
5438 msgstr "FORMAT requiere formato de resultado numérico como argumento. El formato %s especificado es de tipo cadena."
5439
5440 #: src/language/utilities/set.q:743
61555441 msgid "ISL (32-bit IEEE 754 single, little-endian)"
61565442 msgstr "ISL (32-bit IEEE 754 single, little-endian)"
61575443
6158 #: src/language/utilities/set.q:749
5444 #: src/language/utilities/set.q:746
61595445 msgid "ISB (32-bit IEEE 754 single, big-endian)"
61605446 msgstr "ISB (32-bit IEEE 754 single, big-endian)"
61615447
6162 #: src/language/utilities/set.q:752
5448 #: src/language/utilities/set.q:749
61635449 msgid "IDL (64-bit IEEE 754 double, little-endian)"
61645450 msgstr "IDL (64-bit IEEE 754 double, little-endian)"
61655451
6166 #: src/language/utilities/set.q:755
5452 #: src/language/utilities/set.q:752
61675453 msgid "IDB (64-bit IEEE 754 double, big-endian)"
61685454 msgstr "IDB (64-bit IEEE 754 double, big-endian)"
61695455
6170 #: src/language/utilities/set.q:759
5456 #: src/language/utilities/set.q:756
61715457 msgid "VF (32-bit VAX F, VAX-endian)"
61725458 msgstr "VF (32-bit VAX F, VAX-endian)"
61735459
6174 #: src/language/utilities/set.q:762
5460 #: src/language/utilities/set.q:759
61755461 msgid "VD (64-bit VAX D, VAX-endian)"
61765462 msgstr "VD (64-bit VAX D, VAX-endian)"
61775463
6178 #: src/language/utilities/set.q:765
5464 #: src/language/utilities/set.q:762
61795465 msgid "VG (64-bit VAX G, VAX-endian)"
61805466 msgstr "VG (64-bit VAX G, VAX-endian)"
61815467
6182 #: src/language/utilities/set.q:769
5468 #: src/language/utilities/set.q:766
61835469 msgid "ZS (32-bit IBM Z hexadecimal short, big-endian)"
61845470 msgstr "ZS (32-bit IBM Z hexadecimal short, big-endian)"
61855471
6186 #: src/language/utilities/set.q:772
5472 #: src/language/utilities/set.q:769
61875473 msgid "ZL (64-bit IBM Z hexadecimal long, big-endian)"
61885474 msgstr "ZL (64-bit IBM Z hexadecimal long, big-endian)"
61895475
6190 #: src/language/utilities/set.q:912
5476 #: src/language/utilities/set.q:870
61915477 #, c-format
61925478 msgid "%s is %s."
61935479 msgstr "%s es %s."
61945480
6195 #: src/language/utilities/set.q:1016
6196 #, c-format
6197 msgid ""
6198 "Too many PRESERVE commands without a RESTORE: at most %d levels of saved "
6199 "settings are allowed."
6200 msgstr ""
6201 "Demasiados comandos PRESERVE sin un RESTORE: se permiten al menos %d niveles "
6202 "de configuraciones salvadas."
6203
6204 #: src/language/utilities/set.q:1035
5481 #: src/language/utilities/set.q:973
5482 #, c-format
5483 msgid "Too many PRESERVE commands without a RESTORE: at most %d levels of saved settings are allowed."
5484 msgstr "Demasiados comandos PRESERVE sin un RESTORE: se permiten al menos %d niveles de configuraciones salvadas."
5485
5486 #: src/language/utilities/set.q:992
62055487 msgid "RESTORE without matching PRESERVE."
62065488 msgstr "RESTORE sin el correspondiente PRESERVE."
62075489
62085490 #: src/language/stats/crosstabs.q:294
6209 msgid ""
6210 "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE."
6211 msgstr ""
6212 "El INFORME de perdidos no está disponible en el modo general. Se asume "
6213 "MISSING=TABLE."
5491 msgid "Missing mode REPORT not allowed in general mode. Assuming MISSING=TABLE."
5492 msgstr "El INFORME de perdidos no está disponible en el modo general. Se asume MISSING=TABLE."
62145493
62155494 #: src/language/stats/crosstabs.q:404
62165495 msgid "Too many cross-tabulation variables or dimensions."
64745753
64755754 #: src/language/stats/frequencies.q:398
64765755 #, c-format
6477 msgid ""
6478 "MAX for histogram must be greater than or equal to MIN, but MIN was "
6479 "specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
6480 msgstr ""
6481 "Para el histograma, MAX debe ser mayor o igual a MIN, pero MIN se ha "
6482 "especificado como %15g y MAX como %15g. MIN y MAX serán ignorados."
5756 msgid "MAX for histogram must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
5757 msgstr "Para el histograma, MAX debe ser mayor o igual a MIN, pero MIN se ha especificado como %15g y MAX como %15g. MIN y MAX serán ignorados."
64835758
64845759 #: src/language/stats/frequencies.q:419
64855760 #, c-format
6486 msgid ""
6487 "MAX for pie chart must be greater than or equal to MIN, but MIN was "
6488 "specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
6489 msgstr ""
6490 "Para el gráfico de sectores, MAX debe ser mayor o igual a MIN, pero MIN se "
6491 "ha especificado como %15g y MAX como %15g. MIN y MAX serán ignorados."
5761 msgid "MAX for pie chart must be greater than or equal to MIN, but MIN was specified as %.15g and MAX as %.15g. MIN and MAX will be ignored."
5762 msgstr "Para el gráfico de sectores, MAX debe ser mayor o igual a MIN, pero MIN se ha especificado como %15g y MAX como %15g. MIN y MAX serán ignorados."
64925763
64935764 #: src/language/stats/frequencies.q:722
64945765 #, c-format
64955766 msgid "Variables %s specified multiple times on GROUPED subcommand."
6496 msgstr ""
6497 "La variable %s se ha especificado más de una vez en el subcomando GROUPED."
5767 msgstr "La variable %s se ha especificado más de una vez en el subcomando GROUPED."
64985768
64995769 #: src/language/stats/frequencies.q:732
65005770 #, c-format
65255795 #: src/language/stats/frequencies.q:1217
65265796 #, c-format
65275797 msgid "Omitting pie chart for %s, which has only %d unique values."
6528 msgstr ""
6529 "Se omite el gráfico de sectores para %s, que sólo tiene %d valores únicos."
5798 msgstr "Se omite el gráfico de sectores para %s, que sólo tiene %d valores únicos."
65305799
65315800 #: src/language/stats/frequencies.q:1220
65325801 #, c-format
65335802 msgid "Omitting pie chart for %s, which has over 50 unique values."
6534 msgstr ""
6535 "Se omite el gráfico de sectores para %s, que tiene más de 50 valores únicos."
5803 msgstr "Se omite el gráfico de sectores para %s, que tiene más de 50 valores únicos."
65365804
65375805 #: src/language/stats/regression.q:158
65385806 msgid "R Square"
65795847 msgstr "Correlaciones de Coeficientes"
65805848
65815849 #: src/language/stats/regression.q:787
6582 msgid ""
6583 "The dependent variable is equal to the independent variable.The least "
6584 "squares line is therefore Y=X.Standard errors and related statistics may be "
6585 "meaningless."
6586 msgstr ""
6587 "La variable dependiente es igual a la variable independiente. La línea de "
6588 "minimos cuadrados es por tanto Y=X. Los errores estándard y los estadísticos "
6589 "relacionados podrian ser irrelevantes."
5850 msgid "The dependent variable is equal to the independent variable.The least squares line is therefore Y=X.Standard errors and related statistics may be meaningless."
5851 msgstr "La variable dependiente es igual a la variable independiente. La línea de minimos cuadrados es por tanto Y=X. Los errores estándard y los estadísticos relacionados podrian ser irrelevantes."
65905852
65915853 #: src/language/stats/regression.q:938
65925854 msgid "REGRESSION requires numeric variables."
65985860
65995861 #: src/language/data-io/file-handle.q:70
66005862 #, c-format
6601 msgid ""
6602 "File handle %s is already defined. Use CLOSE FILE HANDLE before redefining "
6603 "a file handle."
6604 msgstr ""
6605 "El manipulador de archivo %s ya está definido. Usar CLOSE FILE HANDLE antes "
6606 "de redefinir un manipulador de archivos."
5863 msgid "File handle %s is already defined. Use CLOSE FILE HANDLE before redefining a file handle."
5864 msgstr "El manipulador de archivo %s ya está definido. Usar CLOSE FILE HANDLE antes de redefinir un manipulador de archivos."
66075865
66085866 #: src/language/data-io/file-handle.q:127
66095867 msgid "RECFORM must be specified with MODE=360."
66115869
66125870 #: src/language/data-io/file-handle.q:138
66135871 #, c-format
6614 msgid ""
6615 "The specified file mode requires LRECL. Assuming %zu-character records."
6616 msgstr ""
6617 "El modo de fichero especificado requiere LRECL. Se asumen registros de %zu "
6618 "caracteres."
5872 msgid "The specified file mode requires LRECL. Assuming %zu-character records."
5873 msgstr "El modo de fichero especificado requiere LRECL. Se asumen registros de %zu caracteres."
66195874
66205875 #: src/language/data-io/file-handle.q:142
66215876 #, c-format
6622 msgid ""
6623 "Record length (%ld) must be between 1 and %lu bytes. Assuming %zu-character "
6624 "records."
6625 msgstr ""
6626 "El tamaño de registro (%ld) debe estar entre 1 y %lu bytes. Se asume %zu-"
6627 "registros de carácter."
5877 msgid "Record length (%ld) must be between 1 and %lu bytes. Assuming %zu-character records."
5878 msgstr "El tamaño de registro (%ld) debe estar entre 1 y %lu bytes. Se asume %zu-registros de carácter."
66285879
66295880 #: src/language/data-io/file-handle.q:183
66305881 msgid "file"
66455896
66465897 #: src/language/data-io/list.q:98
66475898 #, c-format
6648 msgid ""
6649 "The first case (%ld) specified precedes the last case (%ld) specified. The "
6650 "values will be swapped."
6651 msgstr ""
6652 "El primer caso (%ld) especificado precede al último caso (%ld) "
6653 "especificado. Los valores se intercanviarán."
5899 msgid "The first case (%ld) specified precedes the last case (%ld) specified. The values will be swapped."
5900 msgstr "El primer caso (%ld) especificado precede al último caso (%ld) especificado. Los valores se intercanviarán."
66545901
66555902 #: src/language/data-io/list.q:106
66565903 #, c-format
6657 msgid ""
6658 "The first case (%ld) to list is less than 1. The value is being reset to 1."
5904 msgid "The first case (%ld) to list is less than 1. The value is being reset to 1."
66595905 msgstr "EL primer caso (%ld) a listar es menor que 1. El valor se ajusta a 1."
66605906
66615907 #: src/language/data-io/list.q:112
66625908 #, c-format
6663 msgid ""
6664 "The last case (%ld) to list is less than 1. The value is being reset to 1."
5909 msgid "The last case (%ld) to list is less than 1. The value is being reset to 1."
66655910 msgstr "El último caso (%ld) a listar es menor que 1. El valor se ajusta a 1."
66665911
66675912 #: src/language/data-io/list.q:118
67115956
67125957 #: src/ui/gui/aggregate.ui:393
67135958 msgid "_Write a new data file containing only the aggregated variables"
6714 msgstr ""
6715 "Escribir un nuevo archivo de datos que contenga sólo las variables agregadas"
5959 msgstr "Escribir un nuevo archivo de datos que contenga sólo las variables agregadas"
67165960
67175961 #: src/ui/gui/aggregate.ui:430
67185962 msgid "label"
67325976
67335977 #: src/ui/gui/autorecode.ui:7
67345978 msgid "Automatic Recode"
6735 msgstr ""
5979 msgstr "Recodificación Automática"
67365980
67375981 #: src/ui/gui/autorecode.ui:92
6738 #, fuzzy
67395982 msgid "Variable -> New Name"
6740 msgstr "Nombre de Variable: "
5983 msgstr "Variable -> Nuevo nombre"
67415984
67425985 #: src/ui/gui/autorecode.ui:115
6743 #, fuzzy
67445986 msgid "_Lowest value"
6745 msgstr "Valor Superior"
5987 msgstr "_Valor Inferior"
67465988
67475989 #: src/ui/gui/autorecode.ui:131
6748 #, fuzzy
67495990 msgid "_Highest value"
6750 msgstr "Valor Superior"
5991 msgstr "_Valor Superior"
67515992
67525993 #: src/ui/gui/autorecode.ui:153
67535994 msgid "Recode starting from"
6754 msgstr ""
5995 msgstr "Recodificación comienza desde"
67555996
67565997 #: src/ui/gui/autorecode.ui:175
6757 #, fuzzy
67585998 msgid "_New Name"
6759 msgstr "Nuevo Valor"
5999 msgstr "_Nuevo Nombre"
67606000
67616001 #: src/ui/gui/autorecode.ui:193
67626002 msgid "_Add New Name"
6763 msgstr ""
6003 msgstr "_Añadir Nuevo Nombre"
67646004
67656005 #: src/ui/gui/autorecode.ui:235
67666006 msgid "_Use the same recoding scheme for all variables"
6767 msgstr ""
6007 msgstr "_Usar el mismo esquema de codificación para todas las variables"
67686008
67696009 #: src/ui/gui/autorecode.ui:250
67706010 msgid "Treat _blank string values as missing"
6771 msgstr ""
6011 msgstr "Tratar los valores de cadena en _blanco como perdidos"
67726012
67736013 #: src/ui/gui/binomial.ui:63
67746014 msgid "_Test Variable List:"
68656105
68666106 #: src/ui/gui/count.ui:7
68676107 msgid "Count Occurrences of Values within Cases"
6868 msgstr ""
6108 msgstr "Contar Ocurrencias de Valores dentro de Casos"
68696109
68706110 #: src/ui/gui/count.ui:97
6871 #, fuzzy
68726111 msgid "Numeric _Variables:"
6873 msgstr "Nombre de Variable:"
6112 msgstr "_Variables Numéricas:"
68746113
68756114 #: src/ui/gui/count.ui:132
6876 #, fuzzy
68776115 msgid "_Target Variable:"
6878 msgstr "Variable objetivo:"
6116 msgstr "_Variable Objetivo:"
68796117
68806118 #: src/ui/gui/count.ui:164
6881 #, fuzzy
68826119 msgid "Target _Label:"
6883 msgstr "Variable objetivo:"
6120 msgstr "_Etiqueta de Objetivo:"
68846121
68856122 #: src/ui/gui/count.ui:179
6886 #, fuzzy
68876123 msgid "_Define Values..."
6888 msgstr "Ponderar Casos..."
6124 msgstr "_Definir Valores..."
68896125
68906126 #: src/ui/gui/count.ui:229
68916127 msgid "Count Values within Cases: Values to Count"
6892 msgstr ""
6128 msgstr "Contar Valores en Casos: Valores a Contar"
68936129
68946130 #: src/ui/gui/count.ui:271
6895 #, fuzzy
68966131 msgid "Values _to Count:"
6897 msgstr "Valor de constraste"
6132 msgstr "Valorers _a Contar:"
68986133
68996134 #: src/ui/gui/crosstabs.ui:7
69006135 msgid "Crosstabs"
69016136 msgstr "Tablas _Contingencia"
69026137
69036138 #: src/ui/gui/crosstabs.ui:57
6904 #, fuzzy
69056139 msgid "_Rows"
6906 msgstr "Filas"
6140 msgstr "_Filas"
69076141
69086142 #: src/ui/gui/crosstabs.ui:100
6909 #, fuzzy
69106143 msgid "_Columns"
6911 msgstr "Columnas"
6144 msgstr "_Columnas"
69126145
69136146 #: src/ui/gui/crosstabs.ui:139
6914 #, fuzzy
69156147 msgid "_Format..."
6916 msgstr "Formato..."
6148 msgstr "_Formato..."
69176149
69186150 #: src/ui/gui/crosstabs.ui:153
6919 #, fuzzy
69206151 msgid "_Statistics..."
6921 msgstr "Estadísticos..."
6152 msgstr "_Estadísticos..."
69226153
69236154 #: src/ui/gui/crosstabs.ui:167
6924 #, fuzzy
69256155 msgid "Ce_lls..."
6926 msgstr "Celdas..."
6156 msgstr "Ce_ldas..."
69276157
69286158 #: src/ui/gui/crosstabs.ui:248
69296159 msgid "Crosstabs: Format"
69906220 msgstr "Valores Esperados:"
69916221
69926222 #: src/ui/gui/chi-square.ui:317
6993 #, fuzzy
69946223 msgid "Test _Variables"
6995 msgstr "Variables de _Test:"
6224 msgstr "_Variables de Prueba"
69966225
69976226 #: src/ui/gui/descriptives.ui:115 src/ui/gui/factor.ui:183
6998 #, fuzzy
69996227 msgid "_Variables:"
7000 msgstr "Variables:"
6228 msgstr "_Variables:"
70016229
70026230 #: src/ui/gui/descriptives.ui:159
7003 #, fuzzy
70046231 msgid "S_tatistics:"
7005 msgstr "Estadísticas:"
6232 msgstr "Es_tadísticos:"
70066233
70076234 #: src/ui/gui/descriptives.ui:198
7008 #, fuzzy
70096235 msgid "_Exclude entire case if any selected variable is missing"
7010 msgstr "Excluir todo el caso si cualquier variable tiene valor perdido"
6236 msgstr "_Excluir todo el caso si cualquier variable seleccionada tiene valor perdido"
70116237
70126238 #: src/ui/gui/descriptives.ui:214
7013 #, fuzzy
70146239 msgid "_Include user-missing data in analysis"
7015 msgstr "Incluir los valores perdidos de usuario en el análisis"
6240 msgstr "_Incluir los valores perdidos de usuario en el análisis"
70166241
70176242 #: src/ui/gui/descriptives.ui:230
7018 #, fuzzy
70196243 msgid "Save _Z-scores of selected variables as new variables"
7020 msgstr ""
7021 "Guardar puntuaciones-Z de las variables seleccionadas como nuevas variables"
6244 msgstr "Guardar puntuaciones-_Z de las variables seleccionadas como nuevas variables"
70226245
70236246 #: src/ui/gui/descriptives.ui:252
70246247 msgid "Options:"
71146337 msgstr "Análisis Factorial: Extracción"
71156338
71166339 #: src/ui/gui/factor.ui:228
7117 #, fuzzy
71186340 msgid "_Method: "
7119 msgstr "Método: "
6341 msgstr "_Método: "
71206342
71216343 #: src/ui/gui/factor.ui:280
7122 #, fuzzy
71236344 msgid "Co_rrelation matrix"
7124 msgstr "Matriz de Correlaciones"
6345 msgstr "Matriz de Co_rrelaciones"
71256346
71266347 #: src/ui/gui/factor.ui:295
7127 #, fuzzy
71286348 msgid "Co_variance matrix"
7129 msgstr "Matriz de Covariancias"
6349 msgstr "Matriz de Co_variancias"
71306350
71316351 #: src/ui/gui/factor.ui:316
71326352 msgid "Analyze"
71336353 msgstr "_Analizar"
71346354
71356355 #: src/ui/gui/factor.ui:340
7136 #, fuzzy
71376356 msgid "_Unrotated factor solution"
7138 msgstr "Solución factorial sin rotar"
6357 msgstr "Solución factorial _sin rotar"
71396358
71406359 #: src/ui/gui/factor.ui:355
7141 #, fuzzy
71426360 msgid "_Scree plot"
7143 msgstr "Gráfico de sedimentación"
6361 msgstr "Gráfico de _sedimentación"
71446362
71456363 #: src/ui/gui/factor.ui:375 src/ui/gui/roc.ui:288
71466364 msgid "Display"
71476365 msgstr "Contenido"
71486366
71496367 #: src/ui/gui/factor.ui:448
7150 #, fuzzy
71516368 msgid "_Number of factors:"
7152 msgstr "Número de factores:"
6369 msgstr "_Número de factores:"
71536370
71546371 #: src/ui/gui/factor.ui:480
71556372 msgid "Extract"
71566373 msgstr "Extracción"
71576374
71586375 #: src/ui/gui/factor.ui:495 src/ui/gui/factor.ui:687
7159 #, fuzzy
71606376 msgid "Ma_ximum iterations for convergence:"
7161 msgstr "Iteraciones máximas para la convergencia:"
6377 msgstr "Iteraciones má_ximas para la convergencia:"
71626378
71636379 #: src/ui/gui/factor.ui:560
71646380 msgid "Factor Analysis: Rotation"
72176433 msgstr "Buscar hacia atrás"
72186434
72196435 #: src/ui/gui/frequencies.ui:107
7220 #, fuzzy
72216436 msgid "_Variable(s):"
7222 msgstr "Variable(s):"
6437 msgstr "_Variable(s):"
72236438
72246439 #: src/ui/gui/frequencies.ui:148
7225 #, fuzzy
72266440 msgid "_Statistics:"
7227 msgstr "Estadísticas:"
6441 msgstr "_Estadísticos:"
72286442
72296443 #: src/ui/gui/frequencies.ui:161
7230 #, fuzzy
72316444 msgid "Include _missing values"
7232 msgstr "Incluye valores perdidos"
6445 msgstr "Incluir valores _perdidos"
72336446
72346447 #: src/ui/gui/frequencies.ui:179
72356448 msgid "Charts..."
73326545 msgstr "<b>Diagramas de Sectores</b>"
73336546
73346547 #: src/ui/gui/k-means.ui:7
7335 #, fuzzy
73366548 msgid "K-Means Cluster Analysis"
7337 msgstr "Análisis Factorial"
6549 msgstr "Análisis de Conglomerados K-Medias"
73386550
73396551 #: src/ui/gui/k-means.ui:93
7340 #, fuzzy
73416552 msgid "N_umber of Clusters: "
7342 msgstr "Número de casos"
6553 msgstr "_Número de Conglomerados: "
73436554
73446555 #: src/ui/gui/k-related.ui:7
73456556 msgid "Tests for Several Related Samples"
73626573 msgstr "Q de _Cochran"
73636574
73646575 #: src/ui/gui/ks-one-sample.ui:108
7365 #, fuzzy
73666576 msgid "Test _Variable List:"
7367 msgstr "Lista de Variable _Test:"
6577 msgstr "Lista de Variables de _Prueba:"
73686578
73696579 #: src/ui/gui/ks-one-sample.ui:139
7370 #, fuzzy
73716580 msgid "_Normal"
7372 msgstr "Formato"
6581 msgstr "_Normal"
73736582
73746583 #: src/ui/gui/ks-one-sample.ui:150
73756584 msgid "_Poisson"
7376 msgstr ""
6585 msgstr "_Poisson"
73776586
73786587 #: src/ui/gui/ks-one-sample.ui:164
7379 #, fuzzy
73806588 msgid "_Uniform"
7381 msgstr "_Transformar"
6589 msgstr "_Uniforme"
73826590
73836591 #: src/ui/gui/ks-one-sample.ui:178
73846592 msgid "_Exponential"
7385 msgstr ""
6593 msgstr "_Exponencial"
73866594
73876595 #: src/ui/gui/ks-one-sample.ui:199
73886596 msgid "Test Distribution"
7389 msgstr ""
7390
7391 #: src/ui/gui/means.ui:8
7392 #, fuzzy
7393 msgid "Means"
7394 msgstr "Media"
7395
7396 #: src/ui/gui/means.ui:110
7397 #, fuzzy
7398 msgid "_Dependent List:"
7399 msgstr "Lista de Dependientes:"
7400
7401 #: src/ui/gui/means.ui:139
7402 #, fuzzy
7403 msgid "_Independent List:"
7404 msgstr "Lista de Dependientes:"
6597 msgstr "Distribución de Prueba"
74056598
74066599 #: src/ui/gui/oneway.ui:8
74076600 msgid "One-Way ANOVA"
74446637 msgstr "Contraste 1 de 1"
74456638
74466639 #: src/ui/gui/paired-samples.ui:113
7447 #, fuzzy
74486640 msgid "Test _Pair(s):"
7449 msgstr "Variable(s) de contraste:"
6641 msgstr "_Pareja(s) de Prueba:"
74506642
74516643 #: src/ui/gui/psppire.ui:7
74526644 msgid "Weight Cases"
76056797 msgstr "Rango asignado a empates"
76066798
76076799 #: src/ui/gui/runs.ui:113
7608 #, fuzzy
76096800 msgid "_Median"
7610 msgstr "Mediana"
6801 msgstr "_Mediana"
76116802
76126803 #: src/ui/gui/runs.ui:123
76136804 msgid "M_ean"
7614 msgstr ""
6805 msgstr "M_edia"
76156806
76166807 #: src/ui/gui/runs.ui:137
76176808 msgid "Mo_de"
7618 msgstr ""
6809 msgstr "M_oda"
76196810
76206811 #: src/ui/gui/runs.ui:154
7621 #, fuzzy
76226812 msgid "_Custom:"
7623 msgstr "De usuario"
6813 msgstr "_Personalizado:"
76246814
76256815 #: src/ui/gui/runs.ui:193
7626 #, fuzzy
76276816 msgid "Cut Point"
7628 msgstr "Punto de corte:"
6817 msgstr "Punto de corte"
76296818
76306819 #: src/ui/gui/sort.ui:8
76316820 msgid "Sort Cases"
77286917 msgstr "Valores anteriores y nuevos"
77296918
77306919 #: src/ui/gui/regression.ui:32
7731 #, fuzzy
77326920 msgid "S_tatistics..."
7733 msgstr "Estadísticos..."
6921 msgstr "E_stadísticos..."
77346922
77356923 #: src/ui/gui/regression.ui:47
7736 #, fuzzy
77376924 msgid "_Save..."
7738 msgstr "Guardar..."
6925 msgstr "_Guardar..."
77396926
77406927 #: src/ui/gui/regression.ui:165
7741 #, fuzzy
77426928 msgid "_Dependent"
7743 msgstr "Dependiente"
6929 msgstr "_Dependiente"
77446930
77456931 #: src/ui/gui/regression.ui:213
7746 #, fuzzy
77476932 msgid "_Independent"
7748 msgstr "Independiente"
6933 msgstr "_Independiente"
77496934
77506935 #: src/ui/gui/regression.ui:252
77516936 msgid "Regression: Save"
77526937 msgstr "Regresión: Guardar"
77536938
77546939 #: src/ui/gui/regression.ui:267 src/ui/gui/univariate.ui:222
7755 #, fuzzy
77566940 msgid "_Predicted values"
7757 msgstr "Valores predichos"
6941 msgstr "Valores _Predichos"
77586942
77596943 #: src/ui/gui/regression.ui:281 src/ui/gui/univariate.ui:236
7760 #, fuzzy
77616944 msgid "_Residuals"
7762 msgstr "Residuales"
6945 msgstr "_Residuales"
77636946
77646947 #: src/ui/gui/regression.ui:317
77656948 msgid "Regression: Statistics"
77666949 msgstr "Regresión: Estadísticos"
77676950
77686951 #: src/ui/gui/regression.ui:358 src/ui/gui/univariate.ui:313
7769 #, fuzzy
77706952 msgid "S_tatistics"
7771 msgstr "Estadísticas"
6953 msgstr "Es_tadísticos"
77726954
77736955 #: src/ui/gui/reliability.ui:26
77746956 msgid "Reliability Analysis"
77796961 msgstr "_Items:"
77806962
77816963 #: src/ui/gui/reliability.ui:142
7782 #, fuzzy
77836964 msgid "_Model: "
7784 msgstr "Modelo:\t"
6965 msgstr "_Modelo: "
77856966
77866967 #: src/ui/gui/reliability.ui:183
7787 #, fuzzy
77886968 msgid "_Variables in first split:"
7789 msgstr "Variables a primera división:"
6969 msgstr "_Variables en la primera segmentación:"
77906970
77916971 #: src/ui/gui/reliability.ui:222
7792 #, fuzzy
77936972 msgid "Show _descriptives for scale if item is deleted"
7794 msgstr "Muestra descriptivos para escalas si el _item es eliminado"
6973 msgstr "Muestra _descriptivos para escalas si el item es eliminado"
77956974
77966975 #: src/ui/gui/roc.ui:115
77976976 msgid "_Test Variable:"
79347113 msgstr "Prueba T para una muestra"
79357114
79367115 #: src/ui/gui/t-test.ui:630
7937 #, fuzzy
79387116 msgid "Test _Value: "
7939 msgstr "Valor de Contraste: "
7117 msgstr "_Valor de Prueba: "
79407118
79417119 #: src/ui/gui/text-data-import.ui:8
79427120 msgid "Importing Textual Data"
79447122
79457123 #: src/ui/gui/text-data-import.ui:19
79467124 msgid ""
7947 "This assistant will guide you through the process of importing data into "
7948 "PSPP from a text file with one line per case, in which fields are separated "
7949 "by tabs, commas, or other delimiters.\n"
7125 "This assistant will guide you through the process of importing data into PSPP from a text file with one line per case, in which fields are separated by tabs, commas, or other delimiters.\n"
79507126 "\n"
7951 "The selected file contains N lines of text. Only the first M of these will "
7952 "be shown for preview purposes in the following screens. You may choose "
7953 "below how much of the file should actually be imported."
7127 "The selected file contains N lines of text. Only the first M of these will be shown for preview purposes in the following screens. You may choose below how much of the file should actually be imported."
79547128 msgstr ""
7955 "Este asistente te quiará a lo largo del proceso de importar datos al PSPP "
7956 "desde un archivo de texto con una línea por caso, en el cual los campos "
7957 "están separados por tabuladores, comas, u otros delimitadores.\n"
7129 "Este asistente te quiará a lo largo del proceso de importar datos al PSPP desde un archivo de texto con una línea por caso, en el cual los campos están separados por tabuladores, comas, u otros delimitadores.\n"
79587130 "\n"
7959 "El archivo seleccionado contiene N líneas de texto. Solo las primeras M se "
7960 "mostrarán como previsualización en las pantallas siguientes. Puedes escoger "
7961 "a continuación qué parte del archivo ha de ser importado."
7131 "El archivo seleccionado contiene N líneas de texto. Solo las primeras M se mostrarán como previsualización en las pantallas siguientes. Puedes escoger a continuación qué parte del archivo ha de ser importado."
79627132
79637133 #: src/ui/gui/text-data-import.ui:95
79647134 msgid "All cases"
79787148
79797149 #: src/ui/gui/text-data-import.ui:174
79807150 msgid "Line above selected line contains variable names"
7981 msgstr ""
7982 "La línea por encima de la seleccionada contiene los nombres de las variables"
7151 msgstr "La línea por encima de la seleccionada contiene los nombres de las variables"
79837152
79847153 #: src/ui/gui/text-data-import.ui:192
79857154 msgid "Choose Separators"
80507219 msgstr "Ajustar formato de variables"
80517220
80527221 #: src/ui/gui/text-data-import.ui:551
8053 msgid ""
8054 "Check the data formats displayed below and fix any that are incorrect. You "
8055 "may set other variable properties now or later."
8056 msgstr ""
8057 "Comprueba los formatos de los datos mostrados a continuación y corrige los "
8058 "problemas. Se pueden asignar propiedades de las variables ahora o más "
8059 "adelante."
7222 msgid "Check the data formats displayed below and fix any that are incorrect. You may set other variable properties now or later."
7223 msgstr "Comprueba los formatos de los datos mostrados a continuación y corrige los problemas. Se pueden asignar propiedades de las variables ahora o más adelante."
80607224
80617225 #: src/ui/gui/text-data-import.ui:595
80627226 msgid "<b>Variables</b>"
80677231 msgstr "<b>Previsualización de datos</b>"
80687232
80697233 #: src/ui/gui/univariate.ui:7
8070 #, fuzzy
80717234 msgid "Univariate"
8072 msgstr "Covarianza"
7235 msgstr "Univariado"
80737236
80747237 #: src/ui/gui/univariate.ui:110
8075 #, fuzzy
80767238 msgid "_Dependent Variable"
8077 msgstr "_Variable(s) Dependientes:"
7239 msgstr "Variable _Dependiente"
80787240
80797241 #: src/ui/gui/univariate.ui:159
8080 #, fuzzy
80817242 msgid "_Fixed Factors"
8082 msgstr "_Factor:"
7243 msgstr "_Factores Fijos:"
80837244
80847245 #: src/ui/gui/univariate.ui:207
80857246 msgid "Univariate: Save"
8086 msgstr ""
7247 msgstr "Univariado: Guardar"
80877248
80887249 #: src/ui/gui/univariate.ui:272
8089 #, fuzzy
80907250 msgid "Univariate: Statistics"
8091 msgstr "Explorar: Estadísticos"
7251 msgstr "Univariado: Estadísticos"
80927252
80937253 #: src/ui/gui/var-sheet-dialogs.ui:7
80947254 msgid "Variable Type"
83347494 msgstr "_Calcular..."
83357495
83367496 #: src/ui/gui/data-editor.ui:301
8337 #, fuzzy
83387497 msgid "Cou_nt..."
8339 msgstr "_Fuentes..."
7498 msgstr "Recue_nto..."
83407499
83417500 #: src/ui/gui/data-editor.ui:307
83427501 msgid "Ran_k Cases..."
83447503
83457504 #: src/ui/gui/data-editor.ui:313
83467505 msgid "Auto_matic Recode..."
8347 msgstr ""
7506 msgstr "Recodificación Auto_mática..."
83487507
83497508 #: src/ui/gui/data-editor.ui:319
83507509 msgid "Recode into _Same Variables..."
83827541 msgid "Compare _Means"
83837542 msgstr "Comparar _Medias"
83847543
8385 #: src/ui/gui/data-editor.ui:382
8386 #, fuzzy
8387 msgid "_Means..."
8388 msgstr "_Media"
8389
8390 #: src/ui/gui/data-editor.ui:388
7544 #: src/ui/gui/data-editor.ui:381
83917545 msgid "_One Sample T Test..."
83927546 msgstr "Prueba T para Una Muestra..."
83937547
8394 #: src/ui/gui/data-editor.ui:394
7548 #: src/ui/gui/data-editor.ui:387
83957549 msgid "_Independent Samples T Test..."
83967550 msgstr "Prueba T para Muestras _Independientes..."
83977551
8398 #: src/ui/gui/data-editor.ui:400
7552 #: src/ui/gui/data-editor.ui:393
83997553 msgid "_Paired Samples T Test..."
84007554 msgstr "Prueba T para Muestras Em_parejadas..."
84017555
8402 #: src/ui/gui/data-editor.ui:406
7556 #: src/ui/gui/data-editor.ui:399
84037557 msgid "One Way _ANOVA..."
84047558 msgstr "_ANOVA de un factor..."
84057559
8406 #: src/ui/gui/data-editor.ui:412
8407 #, fuzzy
7560 #: src/ui/gui/data-editor.ui:405
84087561 msgid "_Univariate Analysis..."
8409 msgstr "_Análisis Factorial..."
8410
8411 #: src/ui/gui/data-editor.ui:420
7562 msgstr "Análisis Univariado..."
7563
7564 #: src/ui/gui/data-editor.ui:413
84127565 msgid "Bivariate _Correlation..."
84137566 msgstr "_Correlación Bivariada..."
84147567
8415 #: src/ui/gui/data-editor.ui:427
7568 #: src/ui/gui/data-editor.ui:420
84167569 msgid "_K-Means Cluster..."
8417 msgstr ""
8418
8419 #: src/ui/gui/data-editor.ui:433
7570 msgstr "Conglomerado K-Medias..."
7571
7572 #: src/ui/gui/data-editor.ui:426
84207573 msgid "Factor _Analysis..."
84217574 msgstr "_Análisis Factorial..."
84227575
8423 #: src/ui/gui/data-editor.ui:440
7576 #: src/ui/gui/data-editor.ui:433
84247577 msgid "Re_liability..."
84257578 msgstr "Fiabi_lidad..."
84267579
8427 #: src/ui/gui/data-editor.ui:446
7580 #: src/ui/gui/data-editor.ui:439
84287581 msgid "Linear _Regression..."
84297582 msgstr "_Regresión Lineal..."
84307583
8431 #: src/ui/gui/data-editor.ui:452
7584 #: src/ui/gui/data-editor.ui:445
84327585 msgid "_Non-Parametric Statistics"
84337586 msgstr "Pruebas _No-Paramétricas"
84347587
8435 #: src/ui/gui/data-editor.ui:458
7588 #: src/ui/gui/data-editor.ui:451
84367589 msgid "_Chi-Square..."
84377590 msgstr "_Chi-cuadrado..."
84387591
8439 #: src/ui/gui/data-editor.ui:464
7592 #: src/ui/gui/data-editor.ui:457
84407593 msgid "_Binomial..."
84417594 msgstr "_Binomial..."
84427595
8443 #: src/ui/gui/data-editor.ui:470
8444 #, fuzzy
7596 #: src/ui/gui/data-editor.ui:463
84457597 msgid "R_uns..."
8446 msgstr "Vínculos..."
8447
8448 #: src/ui/gui/data-editor.ui:476
8449 #, fuzzy
7598 msgstr "Ejec_ución..."
7599
7600 #: src/ui/gui/data-editor.ui:469
84507601 msgid "1-Sample _K-S..."
8451 msgstr "Muestra..."
8452
8453 #: src/ui/gui/data-editor.ui:482
8454 #, fuzzy
7602 msgstr "_K-S para Una Muestra..."
7603
7604 #: src/ui/gui/data-editor.ui:475
84557605 msgid "2 _Related Samples..."
8456 msgstr "K Muestra_s Emparejadas..."
8457
8458 #: src/ui/gui/data-editor.ui:488
7606 msgstr "Dos Muestras Empa_rejadas..."
7607
7608 #: src/ui/gui/data-editor.ui:481
84597609 msgid "K Related _Samples..."
84607610 msgstr "K Muestra_s Emparejadas..."
84617611
8462 #: src/ui/gui/data-editor.ui:495
7612 #: src/ui/gui/data-editor.ui:488
84637613 msgid "ROC Cur_ve..."
84647614 msgstr "Curva ROC"
84657615
8466 #: src/ui/gui/data-editor.ui:501
7616 #: src/ui/gui/data-editor.ui:494
84677617 msgid "_Utilities"
84687618 msgstr "_Utilidades"
84697619
8470 #: src/ui/gui/data-editor.ui:508
7620 #: src/ui/gui/data-editor.ui:501
84717621 msgid "_Variables..."
84727622 msgstr "_Variables..."
84737623
8474 #: src/ui/gui/data-editor.ui:509
7624 #: src/ui/gui/data-editor.ui:502
84757625 msgid "Jump to variable"
84767626 msgstr "Ir a la variable"
84777627
8478 #: src/ui/gui/data-editor.ui:516
7628 #: src/ui/gui/data-editor.ui:509
84797629 msgid "Data File _Comments..."
84807630 msgstr "_Comentarios del Archivo de Datos..."
84817631
8482 #: src/ui/gui/data-editor.ui:522 src/ui/gui/output-viewer.ui:47
7632 #: src/ui/gui/data-editor.ui:515 src/ui/gui/output-viewer.ui:47
84837633 #: src/ui/gui/syntax-editor.ui:143
84847634 msgid "_Windows"
84857635 msgstr "_Ventanas"
84867636
8487 #: src/ui/gui/data-editor.ui:528 src/ui/gui/output-viewer.ui:53
7637 #: src/ui/gui/data-editor.ui:521 src/ui/gui/output-viewer.ui:53
84887638 #: src/ui/gui/syntax-editor.ui:149
84897639 msgid "_Minimize All Windows"
84907640 msgstr "_Minimizar todas las ventanas"
84917641
8492 #: src/ui/gui/data-editor.ui:534
7642 #: src/ui/gui/data-editor.ui:527
84937643 msgid "_Split"
84947644 msgstr "Dividir"
84957645
8496 #: src/ui/gui/data-editor.ui:719
7646 #: src/ui/gui/data-editor.ui:711
84977647 msgid "Information Area"
84987648 msgstr "Área de Información"
84997649
8500 #: src/ui/gui/data-editor.ui:741
7650 #: src/ui/gui/data-editor.ui:733
85017651 msgid "Processor Area"
85027652 msgstr "Área del procesador"
85037653
8504 #: src/ui/gui/data-editor.ui:766
7654 #: src/ui/gui/data-editor.ui:758
85057655 msgid "Case Counter Area"
85067656 msgstr "Área de Recuento"
85077657
8508 #: src/ui/gui/data-editor.ui:791
7658 #: src/ui/gui/data-editor.ui:783
85097659 msgid "Filter Use Status Area"
85107660 msgstr "Área de uso de Filtro"
85117661
8512 #: src/ui/gui/data-editor.ui:817
7662 #: src/ui/gui/data-editor.ui:809
85137663 msgid "Weight Status Area"
85147664 msgstr "Área de Ponderación"
85157665
8516 #: src/ui/gui/data-editor.ui:843
7666 #: src/ui/gui/data-editor.ui:835
85177667 msgid "Split File Status Area"
85187668 msgstr "Área de División de Archivo"
85197669
85457695 msgid "To End"
85467696 msgstr "Hasta el final"
85477697
8548 #: src/ui/gui/gen-dot-desktop.sh:14
8549 #, fuzzy
8550 msgid "Statistical Software"
8551 msgstr "Estadístico"
8552
8553 #: src/ui/gui/gen-dot-desktop.sh:15
8554 msgid "Analyze statistical data with a free alternative to SPSS"
8555 msgstr ""
8556
8557 #~ msgid "OK"
8558 #~ msgstr "Ok"
8559
8560 #~ msgid "Go To"
8561 #~ msgstr "Ir a"
8562
8563 #~ msgid "Cancel"
8564 #~ msgstr "Cancelar"
8565
8566 #~ msgid "Help"
8567 #~ msgstr "Ayuda"
8568
8569 #~ msgid "Reset"
8570 #~ msgstr "Reiniciar"
8571
8572 #~ msgid "Paste"
8573 #~ msgstr "Pegar"
8574
85757698 #~ msgid "Unknown variable format %<PRIu8>."
85767699 #~ msgstr "Formato de variable %<PRIu8> desconocido."
85777700
85847707 #~ msgid "write"
85857708 #~ msgstr "escribir"
85867709
8587 #~ msgid ""
8588 #~ "%s is allowed only before the active dataset has been defined or inside "
8589 #~ "INPUT PROGRAM."
8590 #~ msgstr ""
8591 #~ "%s sólo se permite antes que el archivo de datos activo se haya definido "
8592 #~ "o dentro de INPUT PROGRAM."
8593
8594 #~ msgid ""
8595 #~ "%s is allowed only after the active dataset has been defined or inside "
8596 #~ "INPUT PROGRAM."
8597 #~ msgstr ""
8598 #~ "%s sólo se permite después que el archivo de datos activo se ha definido "
8599 #~ "o dentro de INPUT PROGRAM."
7710 #~ msgid "%s is allowed only before the active dataset has been defined or inside INPUT PROGRAM."
7711 #~ msgstr "%s sólo se permite antes que el archivo de datos activo se haya definido o dentro de INPUT PROGRAM."
7712
7713 #~ msgid "%s is allowed only after the active dataset has been defined or inside INPUT PROGRAM."
7714 #~ msgstr "%s sólo se permite después que el archivo de datos activo se ha definido o dentro de INPUT PROGRAM."
86007715
86017716 #~ msgid "missing required subcommand %s"
86027717 #~ msgstr "suborden requerida %s ausente"
86207735 #~ msgstr "Se espera `(' en el subcomando %s."
86217736
86227737 #~ msgid "`)' expected following variable names on REORDER subcommand."
8623 #~ msgstr ""
8624 #~ "`)' se esperaba seguido de los nombres de la variable en el subcomando "
8625 #~ "REORDER."
8626
8627 #~ msgid ""
8628 #~ "`=' expected between lists of new and old variable names on RENAME "
8629 #~ "subcommand."
8630 #~ msgstr ""
8631 #~ "`=' esperado entre las listas de nombres de variables nuevas y viejas en "
8632 #~ "el subcomando RENAME."
7738 #~ msgstr "`)' se esperaba seguido de los nombres de la variable en el subcomando REORDER."
7739
7740 #~ msgid "`=' expected between lists of new and old variable names on RENAME subcommand."
7741 #~ msgstr "`=' esperado entre las listas de nombres de variables nuevas y viejas en el subcomando RENAME."
86337742
86347743 #~ msgid "`)' expected after variable lists on RENAME subcommand."
8635 #~ msgstr ""
8636 #~ "`)' esperado después de las listas de variables en el subcomando RENAME."
7744 #~ msgstr "`)' esperado después de las listas de variables en el subcomando RENAME."
86377745
86387746 #~ msgid "`/' or `.' expected."
86397747 #~ msgstr "'/' o '.' esperado."
86427750 #~ msgstr "'(' esperado."
86437751
86447752 #~ msgid "`=' expected between lists of new and old variable names."
8645 #~ msgstr ""
8646 #~ "`=' esperado entre listas de nuevos y antiguos nombres de la variable."
7753 #~ msgstr "`=' esperado entre listas de nuevos y antiguos nombres de la variable."
86477754
86487755 #~ msgid "`)' expected after variable names."
86497756 #~ msgstr "`)' esperado después de los nombres de variables."
86617768 #~ msgstr "El subcomando %s sólo puede utilizarse una vez."
86627769
86637770 #~ msgid "Number of contrast coefficients must equal the number of groups"
8664 #~ msgstr ""
8665 #~ "El número de coeficientes de contraste debe ser igual al número de grupos"
7771 #~ msgstr "El número de coeficientes de contraste debe ser igual al número de grupos"
86667772
86677773 #~ msgid "Variables cannot be parsed"
86687774 #~ msgstr "No se pueden generar las variables"
86897795 #~ msgstr "Tipo de registro 7 no reconocido, subtipo %d."
86907796
86917797 #~ msgid "Bad size (%zu) or count (%zu) field on record type 7, subtype 3."
8692 #~ msgstr ""
8693 #~ "Campo de longitud (%zu) o cantidad (%zu) inválidos en el registro tipo 7, "
8694 #~ "subtipo 3."
7798 #~ msgstr "Campo de longitud (%zu) o cantidad (%zu) inválidos en el registro tipo 7, subtipo 3."
86957799
86967800 #~ msgid "Bad size (%zu) or count (%zu) on extension 4."
86977801 #~ msgstr "Longitud (%zu) o cantidad (%zu) de la extensión 4 no válida."
86997803 #~ msgid "Missing space following `%c' at offset %zu in MRSETS record"
87007804 #~ msgstr "Espacio perdido tras `%c' en la posición %zu del registro MRSETS"
87017805
8702 #~ msgid ""
8703 #~ "Unexpected label source value `%s' following `E' at offset %zu in MRSETS "
8704 #~ "record"
8705 #~ msgstr ""
8706 #~ "Valor de fuente de etiqueta inesperado `%s' tras `E' en la posición %zu "
8707 #~ "del registro MRSETS"
7806 #~ msgid "Unexpected label source value `%s' following `E' at offset %zu in MRSETS record"
7807 #~ msgstr "Valor de fuente de etiqueta inesperado `%s' tras `E' en la posición %zu del registro MRSETS"
87087808
87097809 #~ msgid "Bad size %zu on extension 11."
87107810 #~ msgstr "Longitud no válida %zu en la extensión 11."
87217821 #~ msgid "Bad count %zu for extended number of cases."
87227822 #~ msgstr "Recuento incorrecto %zu para un número extenso de casos."
87237823
8724 #~ msgid ""
8725 #~ "Variable name length in long string value label record (%d) exceeds %d-"
8726 #~ "byte limit."
8727 #~ msgstr ""
8728 #~ "La longitud del nombre de la variable en el registro de la etiqueta del "
8729 #~ "valor de cadena larga (%d) supera el límite %d-byte."
7824 #~ msgid "Variable name length in long string value label record (%d) exceeds %d-byte limit."
7825 #~ msgstr "La longitud del nombre de la variable en el registro de la etiqueta del valor de cadena larga (%d) supera el límite %d-byte."
87307826
87317827 #~ msgid "`)' expected after GROUPED interval list."
87327828 #~ msgstr "`)' esperada después de la lista de variables GRUPED."
87337829
8734 #~ msgid ""
8735 #~ "FRACTION has been specified, but NORMAL and PROPORTION rank functions "
8736 #~ "have not been requested. The FRACTION subcommand will be ignored."
8737 #~ msgstr ""
8738 #~ "Se ha especificado FRACTION, pero no se han pedido funciones de rango "
8739 #~ "NORMAL o PROPORTION. La suborden FRACTION será ignorada."
7830 #~ msgid "FRACTION has been specified, but NORMAL and PROPORTION rank functions have not been requested. The FRACTION subcommand will be ignored."
7831 #~ msgstr "Se ha especificado FRACTION, pero no se han pedido funciones de rango NORMAL o PROPORTION. La suborden FRACTION será ignorada."
87407832
87417833 #~ msgid "One or more VARIABLES must be specified."
87427834 #~ msgstr "Una o más VARIABLES deben ser especificadas."
87537845 #~ msgid "Labeling"
87547846 #~ msgstr "Etiquetando"
87557847
8756 #~ msgid ""
8757 #~ "Scratch file handle %s has not yet been written, using SAVE or another "
8758 #~ "procedure, so it cannot yet be used for reading."
8759 #~ msgstr ""
8760 #~ "El manipulador de archivos de trabajo %s aún no se ha escrito, utilizando "
8761 #~ "SAVE u otro procedimiento, de forma que aún no se puede leer."
7848 #~ msgid "Scratch file handle %s has not yet been written, using SAVE or another procedure, so it cannot yet be used for reading."
7849 #~ msgstr "El manipulador de archivos de trabajo %s aún no se ha escrito, utilizando SAVE u otro procedimiento, de forma que aún no se puede leer."
87627850
87637851 #~ msgid "scratch file"
87647852 #~ msgstr "archivo de trabajo"
87677855 #~ msgstr "Sufijo de la variable demasiado grande."
87687856
87697857 #~ msgid "Missing space following `%c' at UTF-8 offset %zu in MRSETS record."
8770 #~ msgstr ""
8771 #~ "Espacio perdido tras `%c' en la posición UTF-8 %zu del registro MRSETS."
8772
8773 #~ msgid ""
8774 #~ "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in "
8775 #~ "MRSETS record."
8776 #~ msgstr ""
8777 #~ "Etiqueta de valor fuente inesperada `%s' tras 'E' en la posición UTF-8 "
8778 #~ "%zu del registro MRSETS."
7858 #~ msgstr "Espacio perdido tras `%c' en la posición UTF-8 %zu del registro MRSETS."
7859
7860 #~ msgid "Unexpected label source value `%s' following `E' at UTF-8 offset %zu in MRSETS record."
7861 #~ msgstr "Etiqueta de valor fuente inesperada `%s' tras 'E' en la posición UTF-8 %zu del registro MRSETS."
87797862
87807863 #~ msgid "PSPP-data"
87817864 #~ msgstr "datos-PSPP"
88107893 #~ msgid "Duplicate variable name %s in position %d."
88117894 #~ msgstr "Nombre de la variable %s duplicado en la posición %d."
88127895
8813 #~ msgid ""
8814 #~ "Recoded variable name duplicates an existing `%s' within system file."
8815 #~ msgstr ""
8816 #~ "El nombre de la variable recodificada duplica `%s' existente dentro del "
8817 #~ "archivo del sistema."
7896 #~ msgid "Recoded variable name duplicates an existing `%s' within system file."
7897 #~ msgstr "El nombre de la variable recodificada duplica `%s' existente dentro del archivo del sistema."
88187898
88197899 #~ msgid "Duplicate variable name `%s' within system file."
88207900 #~ msgstr "Nombre de variable '%s' duplicado dentro del archivo de sistema."
88267906 #~ msgstr "Espacio perdido tras 'E' en la posición %zu del registro MRSETS"
88277907
88287908 #~ msgid "Duplicate long variable name `%s' within system file."
8829 #~ msgstr ""
8830 #~ "Nombre de la variable larga '%s' duplicada dentro del archivo de sistema."
7909 #~ msgstr "Nombre de la variable larga '%s' duplicada dentro del archivo de sistema."
88317910
88327911 #~ msgid "Invalid number of labels: %d. Ignoring labels."
88337912 #~ msgstr "Número de etiquetas inválido: %d. Ignorando etiquetas."
88797958 #~ msgstr "%s es demasiado largo para un nombre de variable."
88807959
88817960 #~ msgid "%zu-byte string needed but %zu-byte string supplied."
8882 #~ msgstr ""
8883 #~ "Se necesita cadena de %zu-byte pero se han suministrado de %zu-byte."
7961 #~ msgstr "Se necesita cadena de %zu-byte pero se han suministrado de %zu-byte."
88847962
88857963 #~ msgid "Hexadecimal floating constant too long."
88867964 #~ msgstr "Constante hexadecimal flotante demasiado larga."
88877965
8888 #~ msgid ""
8889 #~ "%s conversion of %s from %s to %s should have produced %s but actually "
8890 #~ "produced %s."
8891 #~ msgstr ""
8892 #~ "conversión %s de %s desde %s en %s debería haber producido %s pero "
8893 #~ "actualmente ha producido %s."
7966 #~ msgid "%s conversion of %s from %s to %s should have produced %s but actually produced %s."
7967 #~ msgstr "conversión %s de %s desde %s en %s debería haber producido %s pero actualmente ha producido %s."
88947968
88957969 #~ msgid "Too many values in single command."
88967970 #~ msgstr "Demasiados valores en un sólo comando."
89538027 #~ msgstr "Los errores (%d) exceden el límite (%d)."
89548028
89558029 #~ msgid "Field content \"%.*s\" cannot be parsed in format %s."
8956 #~ msgstr ""
8957 #~ "El contenido del campo \"%.*s\" no puede ser analizado en formato %s."
8030 #~ msgstr "El contenido del campo \"%.*s\" no puede ser analizado en formato %s."
89588031
89598032 #~ msgid "expecting BY"
89608033 #~ msgstr "esperando BY"
91068179 #~ msgid "unexpected end of line expecting string"
91078180 #~ msgstr "final de línea inesperado cuando se esperaba una cadena"
91088181
9109 #~ msgid ""
9110 #~ "ascii: bad index value for `box' key: syntax is box[INDEX], 0 <= INDEX < "
9111 #~ "%d decimal, with INDEX expressed in base 4"
9112 #~ msgstr ""
9113 #~ "ascii: índice de valor defectuoso para la clave `box' : la sintaxis es la "
9114 #~ "box[INDEX], 0 <= INDEX < %d decimal, con INDEX expresado en base 4"
8182 #~ msgid "ascii: bad index value for `box' key: syntax is box[INDEX], 0 <= INDEX < %d decimal, with INDEX expressed in base 4"
8183 #~ msgstr "ascii: índice de valor defectuoso para la clave `box' : la sintaxis es la box[INDEX], 0 <= INDEX < %d decimal, con INDEX expresado en base 4"
91158184
91168185 #~ msgid "ascii: multiple values for %s"
91178186 #~ msgstr "ascii: valores múltiples para %s"
91188187
91198188 #~ msgid "ascii: only screen devices may have `auto' length or width"
9120 #~ msgstr ""
9121 #~ "ascii: únicamente los dispositivos de pantalla pueden tener largo o ancho "
9122 #~ "`auto'"
8189 #~ msgstr "ascii: únicamente los dispositivos de pantalla pueden tener largo o ancho `auto'"
91238190
91248191 #~ msgid "ascii: positive integer required as `%s' value"
91258192 #~ msgstr "ascii: entero positivo requerido como valor `%s'"
91268193
91278194 #~ msgid "ascii: `emphasis' value must be `bold', `underline', or `none'"
9128 #~ msgstr ""
9129 #~ "ascii: el valor de `emphasis' tiene que ser `bold', `underline', o `none'"
8195 #~ msgstr "ascii: el valor de `emphasis' tiene que ser `bold', `underline', o `none'"
91308196
91318197 #~ msgid "ascii: zero or positive integer required as `%s' value"
91328198 #~ msgstr "ascii: cero o entero positivo requerido como valor `%s'"
91448210 #~ msgstr "abriendo archivo de resultado HTML: %s"
91458211
91468212 #~ msgid "unknown configuration parameter `%s' for HTML device driver"
9147 #~ msgstr ""
9148 #~ "parámetro de configuración `%s' desconocido para el dispositivo "
9149 #~ "controlador HTML"
8213 #~ msgstr "parámetro de configuración `%s' desconocido para el dispositivo controlador HTML"
91508214
91518215 #~ msgid "unknown output driver `%s'"
91528216 #~ msgstr "driver de resultado desconocido `%s'"
91578221 #~ msgid "using default output driver configuration"
91588222 #~ msgstr "utilizando driver de configuración de resultados por defecto"
91598223
9160 #~ msgid ""
9161 #~ "cannot find output initialization file (use `-vv' to view search path)"
9162 #~ msgstr ""
9163 #~ "no se puede encontrar el archivo de inicialización de resultados "
9164 #~ "(utilizar `-vv' para ver la ruta de búsqueda)"
8224 #~ msgid "cannot find output initialization file (use `-vv' to view search path)"
8225 #~ msgstr "no se puede encontrar el archivo de inicialización de resultados (utilizar `-vv' para ver la ruta de búsqueda)"
91658226
91668227 #~ msgid "cannot open \"%s\""
91678228 #~ msgstr "no se puede abrir \"%s\""
91858246 #~ "Clases de controlador:\n"
91868247 #~ "\t"
91878248
9188 #~ msgid ""
9189 #~ "reached end of options inside quoted string parsing options for \"%s\" "
9190 #~ "driver"
9191 #~ msgstr ""
9192 #~ "Llegado al final de opciones dentro de la cadena entre comillas "
9193 #~ "analitzando opciones para el controlador \"%s\""
8249 #~ msgid "reached end of options inside quoted string parsing options for \"%s\" driver"
8250 #~ msgstr "Llegado al final de opciones dentro de la cadena entre comillas analitzando opciones para el controlador \"%s\""
91948251
91958252 #~ msgid "syntax error in string constant parsing options for \"%s\" driver"
9196 #~ msgstr ""
9197 #~ "error de sintaxis en una constante de cadena analizando opciones para el "
9198 #~ "controlador \"%s\""
8253 #~ msgstr "error de sintaxis en una constante de cadena analizando opciones para el controlador \"%s\""
91998254
92008255 #~ msgid "syntax error expecting `=' parsing options for driver \"%s\""
9201 #~ msgstr ""
9202 #~ "error de sintaxis cuando se esperaba `=' analizando las opciones para el "
9203 #~ "controlador \"%s\""
8256 #~ msgstr "error de sintaxis cuando se esperaba `=' analizando las opciones para el controlador \"%s\""
92048257
92058258 #~ msgid "unknown output driver class `%.*s'"
92068259 #~ msgstr "controlador de salida de clase desconocida `%.*s'"
92098262 #~ msgstr "tipo de dispositivo desconocido `%.*s'"
92108263
92118264 #~ msgid "driver definition line missing driver name or class name"
9212 #~ msgstr ""
9213 #~ "línea de definición del controlador sin nombre del controlador o nombre "
9214 #~ "de la clase"
8265 #~ msgstr "línea de definición del controlador sin nombre del controlador o nombre de la clase"
92158266
92168267 #~ msgid "opening PostScript output file \"%s\""
92178268 #~ msgstr "abriendo el archivo de salida PostScript \"%s\""
92208271 #~ msgstr "cierre el archivo de salida PostScript \"%s\""
92218272
92228273 #~ msgid "unknown configuration parameter `%s' for PostScript device driver"
9223 #~ msgstr ""
9224 #~ "parámetro de configuración desconocido`%s' para el controlador del "
9225 #~ "dispositivo PostScript"
9226
9227 #~ msgid ""
9228 #~ "unknown orientation `%s' (valid orientations are `portrait' and "
9229 #~ "`landscape')"
9230 #~ msgstr ""
9231 #~ "orientación desconocida `%s' (las orientaciones válidas son `retrato' i "
9232 #~ "`paisaje')"
8274 #~ msgstr "parámetro de configuración desconocido`%s' para el controlador del dispositivo PostScript"
8275
8276 #~ msgid "unknown orientation `%s' (valid orientations are `portrait' and `landscape')"
8277 #~ msgstr "orientación desconocida `%s' (las orientaciones válidas son `retrato' i `paisaje')"
92338278
92348279 #~ msgid "boolean value expected for %s"
92358280 #~ msgstr "valor booleano esperado para %s"
92378282 #~ msgid "positive integer value required for `%s'"
92388283 #~ msgstr "valor entero positivo necesario para `%s'"
92398284
9240 #~ msgid ""
9241 #~ "default font size must be at least 1 point (value of 1000 for key `%s')"
9242 #~ msgstr ""
9243 #~ "la medida de carácter por defecto tiene que ser como mínimo 1 punto "
9244 #~ "(valor de 1000 por la clave `%s')"
8285 #~ msgid "default font size must be at least 1 point (value of 1000 for key `%s')"
8286 #~ msgstr "la medida de carácter por defecto tiene que ser como mínimo 1 punto (valor de 1000 por la clave `%s')"
92458287
92468288 #~ msgid "could not find AFM file \"%s\""
92478289 #~ msgstr "no se puede encontrar el archivo AFM \"%s\""
92708312 #~ msgid "creating \"%s\""
92718313 #~ msgstr "creando \"%s\""
92728314
9273 #~ msgid ""
9274 #~ "set to `compatible' if you want output calculated from broken algorithms"
9275 #~ msgstr ""
9276 #~ "active `compatible' si quiere obtener resultados calculados a partir de "
9277 #~ "algoritmos rotos"
8315 #~ msgid "set to `compatible' if you want output calculated from broken algorithms"
8316 #~ msgstr "active `compatible' si quiere obtener resultados calculados a partir de algoritmos rotos"
92788317
92798318 #~ msgid "Append DIR to include path"
92808319 #~ msgstr "Adjuntar DIR en la ruta de inclusión"
92918330 #~ msgid "Don't allow some unsafe operations"
92928331 #~ msgstr "No permite algunas operaciones inseguras"
92938332
9294 #~ msgid ""
9295 #~ "Set to `compatible' if you want only to accept SPSS compatible syntax"
9296 #~ msgstr ""
9297 #~ "Active `compatible' si únicamente quiere aceptar la sintaxis compatible "
9298 #~ "de SPSS"
8333 #~ msgid "Set to `compatible' if you want only to accept SPSS compatible syntax"
8334 #~ msgstr "Active `compatible' si únicamente quiere aceptar la sintaxis compatible de SPSS"
92998335
93008336 #~ msgid "PSPP --- A program for statistical analysis"
93018337 #~ msgstr "PSPP ---Un programa de análisis estadístico"
93138349 #~ msgstr "Opciones que afectan a la sintaxis y al comportamiento:"
93148350
93158351 #~ msgid "Cannot open %s (%s). Writing errors to stdout instead.\n"
9316 #~ msgstr ""
9317 #~ "No se puede abrir %s (%s). Alternativamente, escribiendo errores a "
9318 #~ "stdout.\n"
8352 #~ msgstr "No se puede abrir %s (%s). Alternativamente, escribiendo errores a stdout.\n"
93198353
93208354 #~ msgid "Terminating execution of syntax file due to error."
93218355 #~ msgstr "Finalizando la ejecución del archivo de sintaxis debido a un error."
93278361 #~ msgstr "Enviar mensajes de error a FILE (anexa)"
93288362
93298363 #~ msgid "Select output driver DEVICE and disable defaults"
9330 #~ msgstr ""
9331 #~ "Seleccionar el controlador de salida DEVICE y desactivar los valores por "
9332 #~ "defecto"
8364 #~ msgstr "Seleccionar el controlador de salida DEVICE y desactivar los valores por defecto"
93338365
93348366 #~ msgid "Print a list of known driver classes, then exit"
9335 #~ msgstr ""
9336 #~ "Imprimir una lista de clases de controladores conocidos, después salir"
8367 #~ msgstr "Imprimir una lista de clases de controladores conocidos, después salir"
93378368
93388369 #~ msgid "Start an interactive session"
93398370 #~ msgstr "Inicio de una sesión interactiva"
94958526 #~ msgid "Messages Reported"
94968527 #~ msgstr "Se han generado mensajes"
94978528
9498 #~ msgid ""
9499 #~ "The PSPP processor reported # errors. The first # and last # are shown "
9500 #~ "below:"
9501 #~ msgstr ""
9502 #~ "El procesador de PSPP ha generado # errores. Los # primeros y los # "
9503 #~ "últimos se muestran a continuación:"
8529 #~ msgid "The PSPP processor reported # errors. The first # and last # are shown below:"
8530 #~ msgstr "El procesador de PSPP ha generado # errores. Los # primeros y los # últimos se muestran a continuación:"
95048531
95058532 #~ msgid "gtk-close"
95068533 #~ msgstr "gtk-close"
95308557 #~ "Alpha\n"
95318558 #~ "Dividido"
95328559
9533 #~ msgid ""
9534 #~ "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will "
9535 #~ "be assumed. Argument values will be given precedence increasing along "
9536 #~ "the order given."
9537 #~ msgstr ""
9538 #~ "Al menos se ha de declarar un tipo de entre BARCHART, HISTOGRAM o HBAR. "
9539 #~ "Se asume HBAR. (Argument values will be given precedence increasing "
9540 #~ "along the order given)."
8560 #~ msgid "At most one of BARCHART, HISTOGRAM, or HBAR should be given. HBAR will be assumed. Argument values will be given precedence increasing along the order given."
8561 #~ msgstr "Al menos se ha de declarar un tipo de entre BARCHART, HISTOGRAM o HBAR. Se asume HBAR. (Argument values will be given precedence increasing along the order given)."
95418562
95428563 #~ msgid "Variable %s specified multiple times on VARIABLES subcommand."
9543 #~ msgstr ""
9544 #~ "La variable %s se ha especificado más de una vez en el subcomando "
9545 #~ "VARIABLES."
8564 #~ msgstr "La variable %s se ha especificado más de una vez en el subcomando VARIABLES."
95468565
95478566 #~ msgid "Cum"
95488567 #~ msgstr "Acum."
95608579 #~ msgstr "N de elementos"
95618580
95628581 #~ msgid "`/FORMAT WEIGHT' specified, but weighting is not on."
9563 #~ msgstr ""
9564 #~ "`/FORMAT WEIGHT' especificado, pero la ponderación no está activada."
8582 #~ msgstr "`/FORMAT WEIGHT' especificado, pero la ponderación no está activada."
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
925925 md4_process_bytes (&size, sizeof size, ctx);
926926 }
927927
928 for (rsn = range_set_first (axis->available); rsn != NULL;
929 rsn = range_set_next (axis->available, rsn))
928 RANGE_SET_FOR_EACH (rsn, axis->available)
930929 {
931930 unsigned long int start = range_set_node_get_start (rsn);
932931 unsigned long int end = range_set_node_get_end (rsn);
977976 axis_make_available (struct axis *axis,
978977 unsigned long int start, unsigned long int width)
979978 {
980 range_set_insert (axis->available, start, width);
979 range_set_set1 (axis->available, start, width);
981980 }
982981
983982 /* Extends the total physical length of AXIS by WIDTH and returns
12271226 size_t row_size = n_bytes + 4 * sizeof (void *);
12281227 size_t max_memory_rows = settings_get_workspace () / row_size;
12291228 source->avail = range_set_create ();
1230 range_set_insert (source->avail, 0, n_bytes);
1229 range_set_set1 (source->avail, 0, n_bytes);
12311230 source->data = sparse_xarray_create (n_bytes, MAX (max_memory_rows, 4));
12321231 source->backing = NULL;
12331232 source->backing_rows = 0;
12461245 size_t n_columns;
12471246 size_t i;
12481247
1249 range_set_delete (source->avail, 0, n_bytes);
1248 range_set_set0 (source->avail, 0, n_bytes);
12501249 source->backing = reader;
12511250 source->backing_rows = casereader_count_cases (reader);
12521251
13001299 source_release_column (struct source *source, int ofs, int width)
13011300 {
13021301 assert (width >= 0);
1303 range_set_insert (source->avail, ofs, width_to_n_bytes (width));
1302 range_set_set1 (source->avail, ofs, width_to_n_bytes (width));
13041303 if (source->backing != NULL)
13051304 source->n_used--;
13061305 }
599599 {
600600 int dict_index = var_get_dict_index (v);
601601 const int case_index = var_get_case_index (v);
602 const int width = var_get_width (v);
603602
604603 assert (dict_contains_var (d, v));
605604
627626
628627 /* Free memory. */
629628 var_clear_vardict (v);
630 var_destroy (v);
631629
632630 if ( d->changed ) d->changed (d, d->changed_data);
633631
634632 invalidate_proto (d);
635633 if (d->callbacks && d->callbacks->var_deleted )
636 d->callbacks->var_deleted (d, dict_index, case_index, width, d->cb_data);
634 d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
635
636 var_destroy (v);
637637 }
638638
639639 /* Deletes the COUNT variables listed in VARS from D. This is
176176 struct dict_callbacks
177177 {
178178 void (*var_added) (struct dictionary *, int, void *);
179 void (*var_deleted) (struct dictionary *, int, int, int, void *);
179 void (*var_deleted) (struct dictionary *, const struct variable *,
180 int dict_index, int case_index, void *);
180181 void (*var_changed) (struct dictionary *, int, void *);
181182 void (*var_resized) (struct dictionary *, int, int, void *);
182183 void (*weight_changed) (struct dictionary *, int, void *);
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
2525 #include "data/dataset.h"
2626 #include "data/file-name.h"
2727 #include "data/variable.h"
28 #include "libpspp/cast.h"
2829 #include "libpspp/compiler.h"
30 #include "libpspp/hash-functions.h"
2931 #include "libpspp/hmap.h"
3032 #include "libpspp/i18n.h"
3133 #include "libpspp/message.h"
3234 #include "libpspp/str.h"
33 #include "libpspp/hash-functions.h"
3435
3536 #include "gl/xalloc.h"
3637
4950 /* FH_REF_FILE only. */
5051 char *file_name; /* File name as provided by user. */
5152 enum fh_mode mode; /* File mode. */
52 const char *encoding; /* File encoding. */
5353
5454 /* FH_REF_FILE and FH_REF_INLINE only. */
5555 size_t record_width; /* Length of fixed-format records. */
5656 size_t tab_width; /* Tab width, 0=do not expand tabs. */
57 char *encoding; /* Charset for contents. */
5758
5859 /* FH_REF_DATASET only. */
5960 struct dataset *ds; /* Dataset. */
7071 static struct file_handle *inline_file;
7172
7273 static struct file_handle *create_handle (const char *id,
73 char *name, enum fh_referent);
74 char *name, enum fh_referent,
75 const char *encoding);
7476 static void free_handle (struct file_handle *);
7577 static void unname_handle (struct file_handle *);
7678
8183 void
8284 fh_init (void)
8385 {
84 inline_file = create_handle ("INLINE", xstrdup ("INLINE"), FH_REF_INLINE);
86 inline_file = create_handle ("INLINE", xstrdup ("INLINE"), FH_REF_INLINE,
87 "Auto");
8588 inline_file->record_width = 80;
8689 inline_file->tab_width = 8;
8790 }
109112 free (handle->id);
110113 free (handle->name);
111114 free (handle->file_name);
115 free (handle->encoding);
112116 free (handle);
113117 }
114118
188192 The new handle is not fully initialized. The caller is
189193 responsible for completing its initialization. */
190194 static struct file_handle *
191 create_handle (const char *id, char *handle_name, enum fh_referent referent)
195 create_handle (const char *id, char *handle_name, enum fh_referent referent,
196 const char *encoding)
192197 {
193198 struct file_handle *handle = xzalloc (sizeof *handle);
194199
196201 handle->id = id != NULL ? xstrdup (id) : NULL;
197202 handle->name = handle_name;
198203 handle->referent = referent;
204 handle->encoding = xstrdup (encoding);
199205
200206 if (id != NULL)
201207 {
230236 struct file_handle *handle;
231237
232238 handle_name = id != NULL ? xstrdup (id) : xasprintf ("`%s'", file_name);
233 handle = create_handle (id, handle_name, FH_REF_FILE);
239 handle = create_handle (id, handle_name, FH_REF_FILE, properties->encoding);
234240 handle->file_name = xstrdup (file_name);
235241 handle->mode = properties->mode;
236242 handle->record_width = properties->record_width;
237243 handle->tab_width = properties->tab_width;
238 handle->encoding = properties->encoding;
239244 return handle;
240245 }
241246
252257 if (name[0] == '\0')
253258 name = _("active dataset");
254259
255 handle = create_handle (NULL, xstrdup (name), FH_REF_DATASET);
260 handle = create_handle (NULL, xstrdup (name), FH_REF_DATASET, C_ENCODING);
256261 handle->ds = ds;
257262 return handle;
258263 }
262267 fh_default_properties (void)
263268 {
264269 static const struct fh_properties default_properties
265 = {FH_MODE_TEXT, 1024, 4, C_ENCODING};
270 = {FH_MODE_TEXT, 1024, 4, (char *) "Auto"};
266271 return &default_properties;
267272 }
268273
332337
333338 /* Returns the encoding of characters read from HANDLE. */
334339 const char *
335 fh_get_legacy_encoding (const struct file_handle *handle)
336 {
337 assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE));
338 return (handle->referent == FH_REF_FILE ? handle->encoding : C_ENCODING);
340 fh_get_encoding (const struct file_handle *handle)
341 {
342 return handle->encoding;
339343 }
340344
341345 /* Returns the dataset handle associated with HANDLE.
5454 enum fh_mode mode; /* File mode. */
5555 size_t record_width; /* Length of fixed-format records. */
5656 size_t tab_width; /* Tab width, 0=do not expand tabs. */
57 const char *encoding; /* ASCII or EBCDIC? */
57 char *encoding; /* Charset for contents. */
5858 };
5959
6060 void fh_init (void);
8181 const char *fh_get_id (const struct file_handle *);
8282 const char *fh_get_name (const struct file_handle *);
8383 enum fh_referent fh_get_referent (const struct file_handle *);
84 const char *fh_get_encoding (const struct file_handle *);
8485
8586 /* Properties of FH_REF_FILE file handles. */
8687 const char *fh_get_file_name (const struct file_handle *);
8990 /* Properties of FH_REF_FILE and FH_REF_INLINE file handles. */
9091 size_t fh_get_record_width (const struct file_handle *);
9192 size_t fh_get_tab_width (const struct file_handle *);
92 const char *fh_get_legacy_encoding (const struct file_handle *);
9393
9494 /* Properties of FH_REF_DATASET file handles. */
9595 struct dataset *fh_get_dataset (const struct file_handle *);
4545
4646 bool is_fmt_type (enum fmt_type);
4747
48 static bool valid_width (enum fmt_type, int width, bool for_input);
48 static bool valid_width (enum fmt_type, int width, enum fmt_use);
4949
5050 static int max_digits_for_bytes (int bytes);
51 static void fmt_clamp_width (struct fmt_spec *, enum fmt_use);
52 static void fmt_clamp_decimals (struct fmt_spec *, enum fmt_use);
5153
5254 static void fmt_affix_set (struct fmt_affix *, const char *);
5355 static void fmt_affix_free (struct fmt_affix *);
310312 : fmt_for_output (FMT_A, width, 0));
311313 }
312314
313 /* Checks whether SPEC is valid as an input format (if FOR_INPUT)
314 or an output format (otherwise) and returns nonzero if so.
315 /* Checks whether SPEC is valid for USE and returns nonzero if so.
315316 Otherwise, emits an error message and returns zero. */
316317 bool
317 fmt_check (const struct fmt_spec *spec, bool for_input)
318 {
319 const char *io_fmt = for_input ? _("Input format") : _("Output format");
318 fmt_check (const struct fmt_spec *spec, enum fmt_use use)
319 {
320 const char *io_fmt;
320321 char str[FMT_STRING_LEN_MAX + 1];
321322 int min_w, max_w, max_d;
322323
323324 assert (is_fmt_type (spec->type));
324325 fmt_to_string (spec, str);
325326
326 if (for_input && !fmt_usable_for_input (spec->type))
327 io_fmt = use == FMT_FOR_INPUT ? _("Input format") : _("Output format");
328 if (use == FMT_FOR_INPUT && !fmt_usable_for_input (spec->type))
327329 {
328330 msg (SE, _("Format %s may not be used for input."), str);
329331 return false;
337339 return false;
338340 }
339341
340 min_w = fmt_min_width (spec->type, for_input);
341 max_w = fmt_max_width (spec->type, for_input);
342 min_w = fmt_min_width (spec->type, use);
343 max_w = fmt_max_width (spec->type, use);
342344 if (spec->w < min_w || spec->w > max_w)
343345 {
344346 msg (SE, _("%s %s specifies width %d, but "
347349 return false;
348350 }
349351
350 max_d = fmt_max_decimals (spec->type, spec->w, for_input);
352 max_d = fmt_max_decimals (spec->type, spec->w, use);
351353 if (!fmt_takes_decimals (spec->type) && spec->d != 0)
352354 {
353355 msg (SE, ngettext ("%s %s specifies %d decimal place, but "
386388 bool
387389 fmt_check_input (const struct fmt_spec *spec)
388390 {
389 return fmt_check (spec, true);
391 return fmt_check (spec, FMT_FOR_INPUT);
390392 }
391393
392394 /* Checks whether SPEC is valid as an output format and returns
394396 bool
395397 fmt_check_output (const struct fmt_spec *spec)
396398 {
397 return fmt_check (spec, false);
399 return fmt_check (spec, FMT_FOR_OUTPUT);
398400 }
399401
400402 /* Checks that FORMAT is appropriate for a variable of the given
493495 }
494496 }
495497
496 /* Adjusts FMT's width and decimal places to be valid for an
497 input format (if FOR_INPUT) or an output format (if
498 !FOR_INPUT). */
498 /* Adjusts FMT's width and decimal places to be valid for USE. */
499499 void
500 fmt_fix (struct fmt_spec *fmt, bool for_input)
501 {
502 unsigned int step;
503 int min_w, max_w;
504 int max_d;
505
500 fmt_fix (struct fmt_spec *fmt, enum fmt_use use)
501 {
506502 /* Clamp width to those allowed by format. */
507 min_w = fmt_min_width (fmt->type, for_input);
508 max_w = fmt_max_width (fmt->type, for_input);
509 if (fmt->w < min_w)
510 fmt->w = min_w;
511 else if (fmt->w > max_w)
512 fmt->w = max_w;
513
514 /* Round width to step. */
515 step = fmt_step_width (fmt->type);
516 fmt->w = ROUND_DOWN (fmt->w, step);
503 fmt_clamp_width (fmt, use);
517504
518505 /* If FMT has more decimal places than allowed, attempt to increase FMT's
519506 width until that number of decimal places can be achieved. */
520 if (fmt->d > fmt_max_decimals (fmt->type, fmt->w, for_input)
507 if (fmt->d > fmt_max_decimals (fmt->type, fmt->w, use)
521508 && fmt_takes_decimals (fmt->type))
522509 {
523 int max_w = fmt_max_width (fmt->type, for_input);
510 int max_w = fmt_max_width (fmt->type, use);
524511 for (; fmt->w < max_w; fmt->w++)
525 if (fmt->d <= fmt_max_decimals (fmt->type, fmt->w, for_input))
512 if (fmt->d <= fmt_max_decimals (fmt->type, fmt->w, use))
526513 break;
527514 }
528515
529516 /* Clamp decimals to those allowed by format and width. */
530 max_d = fmt_max_decimals (fmt->type, fmt->w, for_input);
531 if (fmt->d < 0)
532 fmt->d = 0;
533 else if (fmt->d > max_d)
534 fmt->d = max_d;
517 fmt_clamp_decimals (fmt, use);
535518 }
536519
537520 /* Adjusts FMT's width and decimal places to be valid for an
539522 void
540523 fmt_fix_input (struct fmt_spec *fmt)
541524 {
542 fmt_fix (fmt, true);
525 fmt_fix (fmt, FMT_FOR_INPUT);
543526 }
544527
545528 /* Adjusts FMT's width and decimal places to be valid for an
547530 void
548531 fmt_fix_output (struct fmt_spec *fmt)
549532 {
550 fmt_fix (fmt, false);
533 fmt_fix (fmt, FMT_FOR_OUTPUT);
534 }
535
536 /* Sets FMT's width to WIDTH (or the nearest width allowed by FMT's type) and
537 reduces its decimal places as necessary (if necessary) for that width. */
538 void
539 fmt_change_width (struct fmt_spec *fmt, int width, enum fmt_use use)
540 {
541 fmt->w = width;
542 fmt_clamp_width (fmt, use);
543 fmt_clamp_decimals (fmt, use);
544 }
545
546 /* Sets FMT's decimal places to DECIMALS (or the nearest number of decimal
547 places allowed by FMT's type) and increases its width as necessary (if
548 necessary) for that number of decimal places. */
549 void
550 fmt_change_decimals (struct fmt_spec *fmt, int decimals, enum fmt_use use)
551 {
552 fmt->d = decimals;
553 fmt_fix (fmt, use);
551554 }
552555
553556 /* Describes a display format. */
593596 return fmt_max_output_decimals (type, fmt_max_output_width (type)) > 0;
594597 }
595598
596 /* Returns the minimum width of the given format TYPE,
597 for input if FOR_INPUT is true,
598 for output otherwise. */
599 int
600 fmt_min_width (enum fmt_type type, bool for_input)
601 {
602 return for_input ? fmt_min_input_width (type) : fmt_min_output_width (type);
599 /* Returns the minimum width of the given format TYPE for the given USE. */
600 int
601 fmt_min_width (enum fmt_type type, enum fmt_use use)
602 {
603 return (use == FMT_FOR_INPUT
604 ? fmt_min_input_width (type)
605 : fmt_min_output_width (type));
603606 }
604607
605608 /* Returns the maximum width of the given format TYPE,
606609 for input if FOR_INPUT is true,
607610 for output otherwise. */
608611 int
609 fmt_max_width (enum fmt_type type, bool for_input UNUSED)
612 fmt_max_width (enum fmt_type type, enum fmt_use use UNUSED)
610613 {
611614 /* Maximum width is actually invariant of whether the format is
612615 for input or output, so FOR_INPUT is unused. */
636639 }
637640
638641 /* Returns the maximum number of decimal places allowed for the
639 given format TYPE with a width of WIDTH places,
640 for input if FOR_INPUT is true,
641 for output otherwise. */
642 int
643 fmt_max_decimals (enum fmt_type type, int width, bool for_input)
642 given format TYPE with a width of WIDTH places, for the given USE. */
643 int
644 fmt_max_decimals (enum fmt_type type, int width, enum fmt_use use)
644645 {
645646 int max_d;
646647
649650 case FMT_F:
650651 case FMT_COMMA:
651652 case FMT_DOT:
652 max_d = for_input ? width : width - 1;
653 max_d = use == FMT_FOR_INPUT ? width : width - 1;
653654 break;
654655
655656 case FMT_DOLLAR:
656657 case FMT_PCT:
657 max_d = for_input ? width : width - 2;
658 max_d = use == FMT_FOR_INPUT ? width : width - 2;
658659 break;
659660
660661 case FMT_E:
661 max_d = for_input ? width : width - 7;
662 max_d = use == FMT_FOR_INPUT ? width : width - 7;
662663 break;
663664
664665 case FMT_CCA:
666667 case FMT_CCC:
667668 case FMT_CCD:
668669 case FMT_CCE:
669 assert (!for_input);
670 assert (use == FMT_FOR_OUTPUT);
670671 max_d = width - 1;
671672 break;
672673
751752 int
752753 fmt_max_input_width (enum fmt_type type)
753754 {
754 return fmt_max_width (type, true);
755 return fmt_max_width (type, FMT_FOR_INPUT);
755756 }
756757
757758 /* Returns the maximum number of decimal places allowed in an
760761 fmt_max_input_decimals (enum fmt_type type, int width)
761762 {
762763 assert (valid_width (type, width, true));
763 return fmt_max_decimals (type, width, true);
764 return fmt_max_decimals (type, width, FMT_FOR_INPUT);
764765 }
765766
766767 /* Returns the minimum acceptable width for an output field
776777 int
777778 fmt_max_output_width (enum fmt_type type)
778779 {
779 return fmt_max_width (type, false);
780 return fmt_max_width (type, FMT_FOR_OUTPUT);
780781 }
781782
782783 /* Returns the maximum number of decimal places allowed in an
785786 fmt_max_output_decimals (enum fmt_type type, int width)
786787 {
787788 assert (valid_width (type, width, false));
788 return fmt_max_decimals (type, width, false);
789 return fmt_max_decimals (type, width, FMT_FOR_OUTPUT);
789790 }
790791
791792 /* Returns the width step for a field formatted with the given
973974 }
974975
975976 /* Returns true if WIDTH is a valid width for the given format
976 TYPE,
977 for input if FOR_INPUT is true,
978 for output otherwise. */
977 TYPE, for the given USE. */
979978 static bool
980 valid_width (enum fmt_type type, int width, bool for_input)
981 {
982 return (width >= fmt_min_width (type, for_input)
983 && width <= fmt_max_width (type, for_input));
979 valid_width (enum fmt_type type, int width, enum fmt_use use)
980 {
981 return (width >= fmt_min_width (type, use)
982 && width <= fmt_max_width (type, use));
984983 }
985984
986985 /* Returns the maximum number of decimal digits in an unsigned
991990 int map[8] = {3, 5, 8, 10, 13, 15, 17, 20};
992991 assert (bytes > 0 && bytes <= sizeof map / sizeof *map);
993992 return map[bytes - 1];
993 }
994
995 /* Clamp FMT's width to the range and values allowed by FMT's type. */
996 static void
997 fmt_clamp_width (struct fmt_spec *fmt, enum fmt_use use)
998 {
999 unsigned int step;
1000 int min_w, max_w;
1001
1002 min_w = fmt_min_width (fmt->type, use);
1003 max_w = fmt_max_width (fmt->type, use);
1004 if (fmt->w < min_w)
1005 fmt->w = min_w;
1006 else if (fmt->w > max_w)
1007 fmt->w = max_w;
1008
1009 /* Round width to step. */
1010 step = fmt_step_width (fmt->type);
1011 fmt->w = ROUND_DOWN (fmt->w, step);
1012 }
1013
1014 /* Clamp FMT's decimal places to the range allowed by FMT's type and width. */
1015 static void
1016 fmt_clamp_decimals (struct fmt_spec *fmt, enum fmt_use use)
1017 {
1018 int max_d;
1019
1020 max_d = fmt_max_decimals (fmt->type, fmt->w, use);
1021 if (fmt->d < 0)
1022 fmt->d = 0;
1023 else if (fmt->d > max_d)
1024 fmt->d = max_d;
9941025 }
9951026
9961027 /* Sets AFFIX's string value to S, a UTF-8 encoded string. */
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2006, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
2121 #include <stdbool.h>
2222 #include "data/val-type.h"
2323 #include "libpspp/str.h"
24
25 /* How a format is going to be used. */
26 enum fmt_use
27 {
28 FMT_FOR_INPUT, /* For parsing data input, e.g. data_in(). */
29 FMT_FOR_OUTPUT /* For formatting data output, e.g. data_out(). */
30 };
2431
2532 /* Format type categories.
2633
6572 {
6673 enum fmt_type type; /* One of FMT_*. */
6774 int w; /* Width. */
68 int d; /* Number of implied decimal places. */
75 int d; /* Number of decimal places. */
6976 };
7077
7178 /* Maximum width of any numeric format. */
7885 struct fmt_spec fmt_default_for_width (int width);
7986
8087 /* Verifying formats. */
81 bool fmt_check (const struct fmt_spec *, bool for_input);
88 bool fmt_check (const struct fmt_spec *, enum fmt_use);
8289 bool fmt_check_input (const struct fmt_spec *);
8390 bool fmt_check_output (const struct fmt_spec *);
8491 bool fmt_check_type_compat (const struct fmt_spec *, enum val_type);
9097 bool fmt_equal (const struct fmt_spec *, const struct fmt_spec *);
9198 void fmt_resize (struct fmt_spec *, int new_width);
9299
93 void fmt_fix (struct fmt_spec *, bool for_input);
100 void fmt_fix (struct fmt_spec *, enum fmt_use);
94101 void fmt_fix_input (struct fmt_spec *);
95102 void fmt_fix_output (struct fmt_spec *);
103
104 void fmt_change_width (struct fmt_spec *, int width, enum fmt_use);
105 void fmt_change_decimals (struct fmt_spec *, int decimals, enum fmt_use);
96106
97107 /* Format types. */
98108 bool is_fmt_type (enum fmt_type);
102112
103113 bool fmt_takes_decimals (enum fmt_type) PURE_FUNCTION;
104114
105 int fmt_min_width (enum fmt_type, bool for_input) PURE_FUNCTION;
106 int fmt_max_width (enum fmt_type, bool for_input) PURE_FUNCTION;
107 int fmt_max_decimals (enum fmt_type, int width, bool for_input) PURE_FUNCTION;
115 int fmt_min_width (enum fmt_type, enum fmt_use) PURE_FUNCTION;
116 int fmt_max_width (enum fmt_type, enum fmt_use) PURE_FUNCTION;
117 int fmt_max_decimals (enum fmt_type, int width, enum fmt_use) PURE_FUNCTION;
108118 int fmt_min_input_width (enum fmt_type) PURE_FUNCTION;
109119 int fmt_max_input_width (enum fmt_type) PURE_FUNCTION;
110120 int fmt_max_input_decimals (enum fmt_type, int width) PURE_FUNCTION;
712712 {
713713 return the_settings.var_output_style;
714714 }
715
716
717 void
718 settings_set_var_style (enum settings_var_style s)
719 {
720 the_settings.var_output_style = s;
721 }
120120 enum settings_var_style settings_get_var_style (void);
121121
122122 void settings_set_value_style (enum settings_value_style s);
123 void settings_set_var_style (enum settings_value_style s);
123 void settings_set_var_style (enum settings_var_style s);
124124
125125
126126 enum behavior_mode {
15901590 while (read_variable_to_value_pair (r, dict, text, &var, &long_name))
15911591 {
15921592 /* Validate long name. */
1593 /* XXX need to reencode name to UTF-8 */
15941593 if (!dict_id_is_valid (dict, long_name, false))
15951594 {
15961595 sys_warn (r, record->pos,
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
255255 return (vls == NULL ? NULL
256256 : val_labs_lookup__ (vls, value, value_hash (value, vls->width, 0)));
257257 }
258
259 /* Searches VLS for a value label whose label is exactly LABEL. If successful,
260 returns the corresponding value. Otherwise, returns a null pointer.
261
262 Returns a null pointer if VLS is null.
263
264 This function is O(n) in the number of labels in VLS. */
265 const union value *
266 val_labs_find_value (const struct val_labs *vls, const char *label_)
267 {
268 const union value *value = NULL;
269
270 if (vls != NULL)
271 {
272 const struct val_lab *vl;
273 const char *label;
274
275 label = intern_new (label_);
276 HMAP_FOR_EACH (vl, struct val_lab, node, &vls->labels)
277 if (vl->label == label)
278 {
279 value = &vl->value;
280 break;
281 }
282 intern_unref (label);
283 }
284
285 return value;
286 }
258287
259288 /* Returns the first value label in VLS, in arbitrary order, or a
260289 null pointer if VLS is empty or if VLS is a null pointer. If
332361 {
333362 const struct val_lab *label;
334363
335 if (val_labs_count (a) != val_labs_count (b) || a->width != b->width)
364 if (val_labs_count (a) != val_labs_count (b))
365 return false;
366
367 if (a == NULL || b == NULL)
368 return true;
369
370 if (a->width != b->width)
336371 return false;
337372
338373 HMAP_FOR_EACH (label, struct val_lab, node, &a->labels)
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2009, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2009, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
9292 const char *val_labs_find (const struct val_labs *, const union value *);
9393 struct val_lab *val_labs_lookup (const struct val_labs *,
9494 const union value *);
95 const union value *val_labs_find_value (const struct val_labs *,
96 const char *label);
9597
9698 /* Basic properties. */
9799 size_t val_labs_count (const struct val_labs *);
5353 struct fmt_spec write; /* Default format for WRITE. */
5454 struct val_labs *val_labs; /* Value labels. */
5555 char *label; /* Variable label. */
56 struct string name_and_label; /* The name and label in the same string */
5657
5758 /* GUI information. */
5859 enum measure measure; /* Nominal, ordinal, or continuous. */
9091
9192 assert (width >= 0 && width <= MAX_STRING);
9293
93 v = xmalloc (sizeof *v);
94 v->vardict = NULL;
95 v->name = NULL;
94 v = xzalloc (sizeof *v);
9695 var_set_name (v, name);
9796 v->width = width;
9897 mv_init (&v->miss, width);
102101 v->measure = var_default_measure (type);
103102 v->display_width = var_default_display_width (width);
104103 v->print = v->write = var_default_formats (width);
105 v->val_labs = NULL;
106 v->label = NULL;
107 v->short_names = NULL;
108 v->short_name_cnt = 0;
109 v->aux = NULL;
110 v->aux_dtor = NULL;
111104 attrset_init (&v->attributes);
105 ds_init_empty (&v->name_and_label);
112106
113107 return v;
114108 }
159153 var_clear_label (v);
160154 attrset_destroy (var_get_attributes (v));
161155 free (v->name);
156 ds_destroy (&v->name_and_label);
162157 free (v);
163158 }
164159 }
172167 return v->name;
173168 }
174169
170
171
175172 /* Sets V's name to NAME, a UTF-8 encoded string.
176173 Do not use this function for a variable in a dictionary. Use
177174 dict_rename_var instead. */
183180
184181 free (v->name);
185182 v->name = xstrdup (name);
183 ds_destroy (&v->name_and_label);
184 ds_init_empty (&v->name_and_label);
186185 dict_var_changed (v);
187186 }
188187
581580 ? fmt_for_output (FMT_F, 8, 2)
582581 : fmt_for_output (FMT_A, width, 0));
583582 }
584
583
584
585
586
587 /* Update the combined name and label string if necessary */
588 static void
589 update_vl_string (const struct variable *v)
590 {
591 /* Cast away const! */
592 struct string *str = (struct string *) &v->name_and_label;
593
594 if (ds_is_empty (str))
595 {
596 if (v->label)
597 ds_put_format (str, _("%s (%s)"), v->label, v->name);
598 else
599 ds_put_cstr (str, v->name);
600 }
601 }
602
603
585604 /* Return a string representing this variable, in the form most
586605 appropriate from a human factors perspective, that is, its
587606 variable label if it has one, otherwise its name. */
588607 const char *
589608 var_to_string (const struct variable *v)
590609 {
591 return v->label != NULL ? v->label : v->name;
610 enum settings_var_style style = settings_get_var_style ();
611
612 switch (style)
613 {
614 case SETTINGS_VAR_STYLE_NAMES:
615 return v->name;
616 break;
617 case SETTINGS_VAR_STYLE_LABELS:
618 return v->label != NULL ? v->label : v->name;
619 break;
620 case SETTINGS_VAR_STYLE_BOTH:
621 update_vl_string (v);
622 return ds_cstr (&v->name_and_label);
623 break;
624 default:
625 NOT_REACHED ();
626 break;
627 };
592628 }
593629
594630 /* Returns V's variable label, or a null pointer if it has none. */
639675
640676 v->label = ss_xstrdup (s);
641677 }
678
679 ds_destroy (&v->name_and_label);
680 ds_init_empty (&v->name_and_label);
642681
643682 dict_var_changed (v);
644683
127127 DEF_CMD (S_DATA, 0, "PEARSON CORRELATIONS", cmd_correlation)
128128 DEF_CMD (S_DATA, 0, "QUICK CLUSTER", cmd_quick_cluster)
129129 DEF_CMD (S_DATA, 0, "RANK", cmd_rank)
130 DEF_CMD (S_DATA, 0, "REGRESSION", cmd_regression)
130 DEF_CMD (S_DATA, 0, "REGRESSION", cmd_regression)
131131 DEF_CMD (S_DATA, 0, "RELIABILITY", cmd_reliability)
132132 DEF_CMD (S_DATA, 0, "RENAME VARIABLES", cmd_rename_variables)
133133 DEF_CMD (S_DATA, 0, "ROC", cmd_roc)
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2009-2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2009-2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
135135 cmd_end_if (struct lexer *lexer UNUSED, struct dataset *ds)
136136 {
137137 struct do_if_trns *do_if = ctl_stack_top (&do_if_class);
138
139 if (do_if == NULL)
140 return CMD_CASCADING_FAILURE;
141
138142 assert (ds == do_if->ds);
139
140 if (do_if == NULL)
141 return CMD_CASCADING_FAILURE;
142
143143 ctl_stack_pop (do_if);
144144
145145 return CMD_SUCCESS;
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
7777 struct dfm_reader *reader;
7878 struct variable *end = NULL;
7979 struct file_handle *fh = NULL;
80 struct string encoding = DS_EMPTY_INITIALIZER;
80 char *encoding = NULL;
8181
8282 int table;
8383 enum data_parser_type type;
110110 if (!lex_force_string (lexer))
111111 goto error;
112112
113 ds_init_substring (&encoding, lex_tokss (lexer));
113 free (encoding);
114 encoding = ss_xstrdup (lex_tokss (lexer));
114115
115116 lex_get (lexer);
116117 }
240241 }
241242 type = data_parser_get_type (parser);
242243
243 if (! ds_is_empty (&encoding) && NULL == fh)
244 if (encoding && NULL == fh)
244245 msg (MW, _("Encoding should not be specified for inline data. It will be "
245246 "ignored."));
246247
277278 if (table)
278279 data_parser_output_description (parser, fh);
279280
280 reader = dfm_open_reader (fh, lexer);
281 reader = dfm_open_reader (fh, lexer, encoding);
281282 if (reader == NULL)
282283 goto error;
283284
293294 data_parser_make_active_file (parser, ds, reader, dict);
294295
295296 fh_unref (fh);
296 ds_destroy (&encoding);
297 free (encoding);
297298
298299 return CMD_SUCCESS;
299300
302303 if (!in_input_program ())
303304 dict_destroy (dict);
304305 fh_unref (fh);
305 ds_destroy (&encoding);
306 free (encoding);
306307 return CMD_CASCADING_FAILURE;
307308 }
308309
331332 if (!parse_record_placement (lexer, &record, &column)
332333 || !parse_DATA_LIST_vars_pool (lexer, dict, tmp_pool,
333334 &names, &name_cnt, PV_NONE)
334 || !parse_var_placements (lexer, tmp_pool, name_cnt, true,
335 || !parse_var_placements (lexer, tmp_pool, name_cnt, FMT_FOR_INPUT,
335336 &formats, &format_cnt))
336337 return false;
337338
526526 parse_fixed (const struct data_parser *parser, struct dfm_reader *reader,
527527 struct ccase *c)
528528 {
529 const char *input_encoding = dfm_reader_get_legacy_encoding (reader);
529 const char *input_encoding = dfm_reader_get_encoding (reader);
530530 const char *output_encoding = dict_get_encoding (parser->dict);
531531 struct field *f;
532532 int row;
578578 parse_delimited_span (const struct data_parser *parser,
579579 struct dfm_reader *reader, struct ccase *c)
580580 {
581 const char *input_encoding = dfm_reader_get_legacy_encoding (reader);
581 const char *input_encoding = dfm_reader_get_encoding (reader);
582582 const char *output_encoding = dict_get_encoding (parser->dict);
583583 struct string tmp = DS_EMPTY_INITIALIZER;
584584 struct field *f;
622622 parse_delimited_no_span (const struct data_parser *parser,
623623 struct dfm_reader *reader, struct ccase *c)
624624 {
625 const char *input_encoding = dfm_reader_get_legacy_encoding (reader);
625 const char *input_encoding = dfm_reader_get_encoding (reader);
626626 const char *output_encoding = dict_get_encoding (parser->dict);
627627 struct string tmp = DS_EMPTY_INITIALIZER;
628628 struct substring s;
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-2004, 2006, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-2004, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
3333 #include "language/lexer/lexer.h"
3434 #include "libpspp/assertion.h"
3535 #include "libpspp/cast.h"
36 #include "libpspp/encoding-guesser.h"
3637 #include "libpspp/integer-format.h"
38 #include "libpspp/line-reader.h"
3739 #include "libpspp/message.h"
3840 #include "libpspp/str.h"
3941
6870 size_t pos; /* Offset in line of current character. */
6971 unsigned eof_cnt; /* # of attempts to advance past EOF. */
7072 struct lexer *lexer; /* The lexer reading the file */
73 char *encoding; /* Current encoding. */
74
75 /* For FH_MODE_TEXT only. */
76 struct line_reader *line_reader;
7177
7278 /* For FH_MODE_360_VARIABLE and FH_MODE_360_SPANNED files only. */
7379 size_t block_left; /* Bytes left in current block. */
100106 }
101107 }
102108
109 line_reader_free (r->line_reader);
110 free (r->encoding);
103111 fh_unref (r->fh);
104112 ds_destroy (&r->line);
105113 ds_destroy (&r->scratch);
106114 free (r);
107115 }
108116
109 /* Opens the file designated by file handle FH for reading as a
110 data file. Providing fh_inline_file() for FH designates the
111 "inline file", that is, data included inline in the command
112 file between BEGIN FILE and END FILE. Returns a reader if
113 successful, or a null pointer otherwise. */
117 /* Opens the file designated by file handle FH for reading as a data file.
118 Returns a reader if successful, or a null pointer otherwise.
119
120 If FH is fh_inline_file() then the new reader reads data included inline in
121 the command file between BEGIN FILE and END FILE, obtaining data from LEXER.
122 LEXER must remain valid as long as the new reader is in use. ENCODING is
123 ignored.
124
125 If FH is not fh_inline_file(), then the encoding of the file read is by
126 default that of FH itself. If ENCODING is nonnull, then it overrides the
127 default encoding. LEXER is ignored. */
114128 struct dfm_reader *
115 dfm_open_reader (struct file_handle *fh, struct lexer *lexer)
129 dfm_open_reader (struct file_handle *fh, struct lexer *lexer,
130 const char *encoding)
116131 {
117132 struct dfm_reader *r;
118133 struct fh_lock *lock;
146161 {
147162 msg (ME, _("Could not open `%s' for reading as a data file: %s."),
148163 fh_get_file_name (r->fh), strerror (errno));
149 fh_unlock (r->lock);
150 fh_unref (fh);
151 free (r);
152 return NULL;
153164 }
154165 r->file_size = fstat (fileno (r->file), &s) == 0 ? s.st_size : -1;
155166 }
157168 r->file_size = -1;
158169 fh_lock_set_aux (lock, r);
159170
171 if (encoding == NULL)
172 encoding = fh_get_encoding (fh);
173 if (fh_get_referent (fh) == FH_REF_FILE && fh_get_mode (fh) == FH_MODE_TEXT)
174 {
175 r->line_reader = line_reader_for_fd (encoding, fileno (r->file));
176 if (r->line_reader == NULL)
177 {
178 msg (ME, _("Could not read `%s' as a text file with encoding `%s': "
179 "%s."),
180 fh_get_file_name (r->fh), encoding, strerror (errno));
181 goto error;
182 }
183 r->encoding = xstrdup (line_reader_get_encoding (r->line_reader));
184 }
185 else
186 {
187 r->line_reader = NULL;
188 r->encoding = xstrdup (encoding_guess_parse_encoding (encoding));
189 }
190
160191 return r;
192
193 error:
194 fh_unlock (r->lock);
195 fh_unref (fh);
196 free (r);
197 return NULL;
161198 }
162199
163200 /* Returns true if an I/O error occurred on READER, false otherwise. */
164201 bool
165202 dfm_reader_error (const struct dfm_reader *r)
166203 {
167 return fh_get_referent (r->fh) == FH_REF_FILE && ferror (r->file);
204 return (fh_get_referent (r->fh) == FH_REF_FILE
205 && (r->line_reader != NULL
206 ? line_reader_error (r->line_reader) != 0
207 : ferror (r->file)));
168208 }
169209
170210 /* Reads a record from the inline file into R.
210250 return true;
211251 }
212252
213 /* Report a read error or unexpected end-of-file condition on R. */
253 /* Report a read error on R. */
214254 static void
215255 read_error (struct dfm_reader *r)
216256 {
217 if (ferror (r->file))
218 msg (ME, _("Error reading file %s: %s."),
219 fh_get_name (r->fh), strerror (errno));
220 else if (feof (r->file))
221 msg (ME, _("Unexpected end of file reading %s."), fh_get_name (r->fh));
222 else
223 NOT_REACHED ();
257 msg (ME, _("Error reading file %s: %s."),
258 fh_get_name (r->fh), strerror (errno));
224259 }
225260
226261 /* Report a partial read at end of file reading R. */
332367 return 1;
333368 }
334369
370 static bool
371 read_text_record (struct dfm_reader *r)
372 {
373 bool is_auto;
374 bool ok;
375
376 /* Read a line. If the line reader's encoding changes, update r->encoding to
377 match. */
378 is_auto = line_reader_is_auto (r->line_reader);
379 ok = line_reader_read (r->line_reader, &r->line, SIZE_MAX);
380 if (is_auto && !line_reader_is_auto (r->line_reader))
381 {
382 free (r->encoding);
383 r->encoding = xstrdup (line_reader_get_encoding (r->line_reader));
384 }
385
386 /* Detect and report read error. */
387 if (!ok)
388 {
389 int error = line_reader_error (r->line_reader);
390 if (error != 0)
391 msg (ME, _("Error reading file %s: %s."),
392 fh_get_name (r->fh), strerror (error));
393 }
394
395 return ok;
396 }
397
335398 /* Reads a record from a disk file into R.
336399 Returns true if successful, false on error or at end of file. */
337400 static bool
343406 switch (fh_get_mode (r->fh))
344407 {
345408 case FH_MODE_TEXT:
346 if (ds_read_line (&r->line, r->file, SIZE_MAX))
347 {
348 ds_chomp_byte (&r->line, '\n');
349 return true;
350 }
351 else
352 {
353 if (ferror (r->file))
354 read_error (r);
355 return false;
356 }
409 return read_text_record (r);
357410
358411 case FH_MODE_FIXED:
359412 if (ds_read_stream (&r->line, 1, fh_get_record_width (r->fh), r->file))
596649 r->pos = new_pos;
597650 }
598651
599 /* Returns the legacy character encoding of data read from READER. */
652 /* Returns the character encoding of data read from READER. */
600653 const char *
601 dfm_reader_get_legacy_encoding (const struct dfm_reader *reader)
602 {
603 return fh_get_legacy_encoding (reader->fh);
654 dfm_reader_get_encoding (const struct dfm_reader *reader)
655 {
656 return reader->encoding;
604657 }
605658
606659 /* Returns a number between 0 and 100 that approximates the
614667 {
615668 if (reader->file_size >= 0)
616669 {
617 off_t position = ftello (reader->file);
670 off_t position;
671
672 position = (reader->line_reader != NULL
673 ? line_reader_tell (reader->line_reader)
674 : ftello (reader->file));
618675 if (position >= 0)
619676 {
620677 double p = 100.0 * position / reader->file_size;
709766 lex_match (lexer, T_ENDCMD);
710767
711768 /* Open inline file. */
712 r = dfm_open_reader (fh_inline_file (), lexer);
769 r = dfm_open_reader (fh_inline_file (), lexer, NULL);
713770 r->flags |= DFM_SAW_BEGIN_DATA;
714771 r->flags &= ~DFM_CONSUME;
715772
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
3030 struct lexer;
3131
3232 /* Input. */
33 struct dfm_reader *dfm_open_reader (struct file_handle *, struct lexer *);
33 struct dfm_reader *dfm_open_reader (struct file_handle *, struct lexer *,
34 const char *encoding);
3435 void dfm_close_reader (struct dfm_reader *);
3536 bool dfm_reader_error (const struct dfm_reader *);
3637 unsigned dfm_eof (struct dfm_reader *);
3738 struct substring dfm_get_record (struct dfm_reader *);
3839 void dfm_expand_tabs (struct dfm_reader *);
39 const char *dfm_reader_get_legacy_encoding (const struct dfm_reader *);
40 const char *dfm_reader_get_encoding (const struct dfm_reader *);
4041 int dfm_get_percent_read (const struct dfm_reader *);
4142
4243 /* Line control. */
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-2004, 2006, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-2004, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
2727 #include "data/make-file.h"
2828 #include "language/data-io/file-handle.h"
2929 #include "libpspp/assertion.h"
30 #include "libpspp/encoding-guesser.h"
3031 #include "libpspp/integer-format.h"
32 #include "libpspp/i18n.h"
3133 #include "libpspp/message.h"
3234 #include "libpspp/str.h"
3335
4547 struct fh_lock *lock; /* Exclusive access to file. */
4648 FILE *file; /* Associated file. */
4749 struct replace_file *rf; /* Atomic file replacement support. */
50 char *encoding; /* Encoding. */
51
52 int unit; /* Unit width, in bytes. */
53 char lf[MAX_UNIT]; /* \n in encoding, 'unit' bytes long. */
54 char spaces[32]; /* 32 bytes worth of ' ' in encoding. */
4855 };
4956
50 /* Opens a file handle for writing as a data file. */
57 /* Opens a file handle for writing as a data file.
58
59 The encoding of the file written is by default that of FH itself. If
60 ENCODING is nonnull, then it overrides the default encoding.
61
62 *However*: ENCODING directly affects only text strings written by the data
63 writer code itself, that is, new-lines in FH_MODE_TEXT and space padding in
64 FH_MODE_FIXED mode. The client must do its own encoding translation for the
65 data that it writes. (This is unavoidable because sometimes the data
66 written includes binary data that reencoding would mangle.) The client can
67 obtain the encoding to re-encode into with dfm_writer_get_encoding(). */
5168 struct dfm_writer *
52 dfm_open_writer (struct file_handle *fh)
53 {
69 dfm_open_writer (struct file_handle *fh, const char *encoding)
70 {
71 struct encoding_info ei;
5472 struct dfm_writer *w;
5573 struct fh_lock *lock;
74 int ofs;
5675
5776 lock = fh_lock (fh, FH_REF_FILE, N_("data file"), FH_ACC_WRITE, false);
5877 if (lock == NULL)
6180 w = fh_lock_get_aux (lock);
6281 if (w != NULL)
6382 return w;
83
84 encoding = encoding_guess_parse_encoding (encoding != NULL
85 ? encoding
86 : fh_get_encoding (fh));
87 get_encoding_info (&ei, encoding);
6488
6589 w = xmalloc (sizeof *w);
6690 w->fh = fh_ref (fh);
6791 w->lock = lock;
6892 w->rf = replace_file_start (fh_get_file_name (w->fh), "wb", 0666,
6993 &w->file, NULL);
94 w->encoding = xstrdup (encoding);
95 w->unit = ei.unit;
96 memcpy (w->lf, ei.lf, sizeof w->lf);
97 for (ofs = 0; ofs + ei.unit <= sizeof w->spaces; ofs += ei.unit)
98 memcpy (&w->spaces[ofs], ei.space, ei.unit);
99
70100 if (w->rf == NULL)
71101 {
72102 msg (ME, _("An error occurred while opening `%s' for writing "
103133 {
104134 case FH_MODE_TEXT:
105135 fwrite (rec, len, 1, w->file);
106 putc ('\n', w->file);
136 fwrite (w->lf, w->unit, 1, w->file);
107137 break;
108138
109139 case FH_MODE_FIXED:
114144 fwrite (rec, write_bytes, 1, w->file);
115145 while (pad_bytes > 0)
116146 {
117 static const char spaces[32] = " ";
118 size_t chunk = MIN (pad_bytes, sizeof spaces);
119 fwrite (spaces, chunk, 1, w->file);
147 size_t chunk = MIN (pad_bytes, sizeof w->spaces);
148 fwrite (w->spaces, chunk, 1, w->file);
120149 pad_bytes -= chunk;
121150 }
122151 }
192221 ok = false;
193222 }
194223 fh_unref (w->fh);
224 free (w->encoding);
195225 free (w);
196226
197227 return ok;
198228 }
199229
200 /* Returns the legacy character encoding of data written to WRITER. */
230 /* Returns the encoding of data written to WRITER. */
201231 const char *
202 dfm_writer_get_legacy_encoding (const struct dfm_writer *writer)
203 {
204 return fh_get_legacy_encoding (writer->fh);
205 }
232 dfm_writer_get_encoding (const struct dfm_writer *writer)
233 {
234 return writer->encoding;
235 }
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
2222 #include <stddef.h>
2323
2424 struct file_handle;
25 struct dfm_writer *dfm_open_writer (struct file_handle *);
25 struct dfm_writer *dfm_open_writer (struct file_handle *,
26 const char *encoding);
2627 bool dfm_close_writer (struct dfm_writer *);
2728 bool dfm_write_error (const struct dfm_writer *);
2829 bool dfm_put_record (struct dfm_writer *, const char *rec, size_t len);
29 const char *dfm_writer_get_legacy_encoding (const struct dfm_writer *);
30 const char *dfm_writer_get_encoding (const struct dfm_writer *);
3031
3132 #endif /* data-writer.h */
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2006, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
1515
1616 #include <config.h>
1717
18 #include "data/file-handle-def.h"
19
1820 #include <limits.h>
1921 #include <errno.h>
2022 #include <stdlib.h>
2123
2224 #include "data/file-name.h"
2325 #include "data/session.h"
26 #include "data/variable.h"
2427 #include "language/command.h"
2528 #include "language/data-io/file-handle.h"
2629 #include "language/lexer/lexer.h"
2730 #include "libpspp/assertion.h"
31 #include "libpspp/cast.h"
2832 #include "libpspp/message.h"
2933 #include "libpspp/str.h"
30 #include "data/variable.h"
31 #include "data/file-handle-def.h"
3234
3335 #include "gl/xalloc.h"
3436
4446 lrecl=integer;
4547 tabwidth=integer;
4648 mode=mode:!character/binary/image/360;
47 recform=recform:fixed/f/variable/v/spanned/vs.
49 recform=recform:fixed/f/variable/v/spanned/vs;
50 encoding=string.
4851 */
4952 /* (declarations) */
5053 /* (functions) */
108111 properties.mode = FH_MODE_VARIABLE;
109112 break;
110113 case FH_360:
111 properties.encoding = "EBCDIC-US";
114 properties.encoding = CONST_CAST (char *, "EBCDIC-US");
112115 if (cmd.recform == FH_FIXED || cmd.recform == FH_F)
113116 properties.mode = FH_MODE_FIXED;
114117 else if (cmd.recform == FH_VARIABLE || cmd.recform == FH_V)
145148 properties.record_width = cmd.n_lrecl[0];
146149 }
147150
151 if (cmd.s_encoding != NULL)
152 properties.encoding = cmd.s_encoding;
153
148154 fh_create_file (handle_name, cmd.s_name, &properties);
149155
150156 result = CMD_SUCCESS;
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
306306 struct dictionary *dict = dict_create (get_default_encoding ());
307307 struct file_handle *fh = NULL;
308308 struct dfm_reader *reader = NULL;
309 char *encoding = NULL;
309310 char *name = NULL;
310311
311312 int record;
333334 if (!lex_force_match (lexer, T_SLASH))
334335 goto error;
335336
336 if (lex_match_id (lexer, "ARRANGEMENT"))
337 if (lex_match_id (lexer, "ENCODING"))
338 {
339 lex_match (lexer, T_EQUALS);
340 if (!lex_force_string (lexer))
341 goto error;
342
343 free (encoding);
344 encoding = ss_xstrdup (lex_tokss (lexer));
345
346 lex_get (lexer);
347 }
348 else if (lex_match_id (lexer, "ARRANGEMENT"))
337349 {
338350 bool ok;
339351
605617 }
606618 while (lex_token (lexer) != T_ENDCMD);
607619
608 reader = dfm_open_reader (fh, lexer);
620 reader = dfm_open_reader (fh, lexer, encoding);
609621 if (reader == NULL)
610622 goto error;
611623
612624 data_parser_make_active_file (parser, ds, reader, dict);
613625 fh_unref (fh);
626 free (encoding);
614627 return CMD_SUCCESS;
615628
616629 error:
618631 dict_destroy (dict);
619632 fh_unref (fh);
620633 free (name);
634 free (encoding);
621635 return CMD_CASCADING_FAILURE;
622636 }
623637
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
265265 struct file_handle *fh; /* File to be re-read. */
266266 struct expression *e; /* Expression for column to set. */
267267 struct reread_trns *t; /* Created transformation. */
268 char *encoding = NULL;
268269
269270 fh = fh_get_default_handle ();
270271 e = NULL;
277278 if (e)
278279 {
279280 lex_sbc_only_once ("COLUMN");
280 expr_free (e);
281 return CMD_CASCADING_FAILURE;
281 goto error;
282282 }
283283
284284 e = expr_parse (lexer, ds, EXPR_NUMBER);
285285 if (!e)
286 return CMD_CASCADING_FAILURE;
286 goto error;
287287 }
288288 else if (lex_match_id (lexer, "FILE"))
289289 {
291291 fh_unref (fh);
292292 fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE, NULL);
293293 if (fh == NULL)
294 {
295 expr_free (e);
296 return CMD_CASCADING_FAILURE;
297 }
294 goto error;
295 }
296 else if (lex_match_id (lexer, "ENCODING"))
297 {
298 lex_match (lexer, T_EQUALS);
299 if (!lex_force_string (lexer))
300 goto error;
301
302 free (encoding);
303 encoding = ss_xstrdup (lex_tokss (lexer));
304
305 lex_get (lexer);
298306 }
299307 else
300308 {
301309 lex_error (lexer, NULL);
302 expr_free (e);
303 return CMD_CASCADING_FAILURE;
310 goto error;
304311 }
305312 }
306313
307314 t = xmalloc (sizeof *t);
308 t->reader = dfm_open_reader (fh, lexer);
315 t->reader = dfm_open_reader (fh, lexer, encoding);
309316 t->column = e;
310317 add_transformation (ds, reread_trns_proc, reread_trns_free, t);
311318
312319 fh_unref (fh);
320 free (encoding);
313321 return CMD_SUCCESS;
322
323 error:
324 expr_free (e);
325 free (encoding);
326 return CMD_CASCADING_FAILURE;
314327 }
315328
316329 /* Executes a REREAD transformation. */
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2006, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
4141 PRS_TYPE_NEW_REC /* Next record. */
4242 };
4343
44 static bool fixed_parse_columns (struct lexer *, struct pool *, size_t var_cnt, bool for_input,
45 struct fmt_spec **, size_t *);
46 static bool fixed_parse_fortran (struct lexer *l, struct pool *, bool for_input,
44 static bool fixed_parse_columns (struct lexer *, struct pool *, size_t var_cnt,
45 enum fmt_use, struct fmt_spec **, size_t *);
46 static bool fixed_parse_fortran (struct lexer *l, struct pool *, enum fmt_use,
4747 struct fmt_spec **, size_t *);
4848
4949 /* Parses Fortran-like or column-based specifications for placing
6262 Uses POOL for allocation. When the caller is finished
6363 interpreting *FORMATS, POOL may be destroyed. */
6464 bool
65 parse_var_placements (struct lexer *lexer, struct pool *pool, size_t var_cnt, bool for_input,
65 parse_var_placements (struct lexer *lexer, struct pool *pool, size_t var_cnt,
66 enum fmt_use use,
6667 struct fmt_spec **formats, size_t *format_cnt)
6768 {
6869 assert (var_cnt > 0);
6970 if (lex_is_number (lexer))
70 return fixed_parse_columns (lexer, pool, var_cnt, for_input, formats, format_cnt);
71 return fixed_parse_columns (lexer, pool, var_cnt, use,
72 formats, format_cnt);
7173 else if (lex_match (lexer, T_LPAREN))
7274 {
7375 size_t assignment_cnt;
7476 size_t i;
7577
76 if (!fixed_parse_fortran (lexer, pool, for_input, formats, format_cnt))
78 if (!fixed_parse_fortran (lexer, pool, use, formats, format_cnt))
7779 return false;
7880
7981 assignment_cnt = 0;
100102
101103 /* Implements parse_var_placements for column-based formats. */
102104 static bool
103 fixed_parse_columns (struct lexer *lexer, struct pool *pool, size_t var_cnt, bool for_input,
105 fixed_parse_columns (struct lexer *lexer, struct pool *pool, size_t var_cnt,
106 enum fmt_use use,
104107 struct fmt_spec **formats, size_t *format_cnt)
105108 {
106109 struct fmt_spec format;
150153 format.type = FMT_F;
151154 format.d = 0;
152155 }
153 if (!fmt_check (&format, for_input))
156 if (!fmt_check (&format, use))
154157 return false;
155158
156159 *formats = pool_nalloc (pool, var_cnt + 1, sizeof **formats);
164167
165168 /* Implements parse_var_placements for Fortran-like formats. */
166169 static bool
167 fixed_parse_fortran (struct lexer *lexer, struct pool *pool, bool for_input,
170 fixed_parse_fortran (struct lexer *lexer, struct pool *pool, enum fmt_use use,
168171 struct fmt_spec **formats, size_t *format_cnt)
169172 {
170173 size_t formats_allocated = 0;
192195 if (lex_match (lexer, T_LPAREN))
193196 {
194197 /* Call ourselves recursively to handle parentheses. */
195 if (!fixed_parse_fortran (lexer, pool, for_input,
198 if (!fixed_parse_fortran (lexer, pool, use,
196199 &new_formats, &new_format_cnt))
197200 return false;
198201 }
224227 msg (SE, _("Unknown format type `%s'."), type);
225228 return false;
226229 }
227 if (!fmt_check (&f, for_input))
230 if (!fmt_check (&f, use))
228231 return false;
229232 }
230233 }
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2006 Free Software Foundation, Inc.
1 Copyright (C) 2006, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
1818
1919 #include <stdbool.h>
2020 #include <stddef.h>
21 #include "data/format.h"
2122
22 struct fmt_spec;
2323 struct pool;
2424 struct lexer;
2525
2626 bool parse_record_placement (struct lexer *, int *record, int *column);
27 bool parse_var_placements (struct lexer *, struct pool *, size_t var_cnt, bool for_input,
27 bool parse_var_placements (struct lexer *, struct pool *, size_t var_cnt,
28 enum fmt_use,
2829 struct fmt_spec **, size_t *format_cnt);
2930 bool execute_placement_format (const struct fmt_spec *,
3031 int *record, int *column);
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
4747 cmd_print_space (struct lexer *lexer, struct dataset *ds)
4848 {
4949 struct print_space_trns *trns;
50 struct file_handle *handle;
51 struct expression *expr;
50 struct file_handle *handle = NULL;
51 struct expression *expr = NULL;
5252 struct dfm_writer *writer;
53 char *encoding = NULL;
5354
5455 if (lex_match_id (lexer, "OUTFILE"))
5556 {
5859 handle = fh_parse (lexer, FH_REF_FILE, NULL);
5960 if (handle == NULL)
6061 return CMD_FAILURE;
62
63 if (lex_match_id (lexer, "ENCODING"))
64 {
65 lex_match (lexer, T_EQUALS);
66 if (!lex_force_string (lexer))
67 goto error;
68
69 encoding = ss_xstrdup (lex_tokss (lexer));
70
71 lex_get (lexer);
72 }
6173 }
6274 else
6375 handle = NULL;
6779 expr = expr_parse (lexer, ds, EXPR_NUMBER);
6880 if (lex_token (lexer) != T_ENDCMD)
6981 {
70 expr_free (expr);
71 lex_error (lexer, _("expecting end of command"));
72 return CMD_FAILURE;
82 lex_error (lexer, _("expecting end of command"));
83 goto error;
7384 }
7485 }
7586 else
7788
7889 if (handle != NULL)
7990 {
80 writer = dfm_open_writer (handle);
91 writer = dfm_open_writer (handle, encoding);
8192 if (writer == NULL)
82 {
83 fh_unref (handle);
84 expr_free (expr);
85 return CMD_FAILURE;
86 }
93 goto error;
8794 }
8895 else
8996 writer = NULL;
96103 print_space_trns_proc, print_space_trns_free, trns);
97104 fh_unref (handle);
98105 return CMD_SUCCESS;
106
107 error:
108 fh_unref (handle);
109 expr_free (expr);
110 return CMD_FAILURE;
99111 }
100112
101113 /* Executes a PRINT SPACE transformation. */
123135 if (trns->writer == NULL)
124136 text_item_submit (text_item_create (TEXT_ITEM_BLANK_LINE, ""));
125137 else
126 dfm_put_record (trns->writer, " ", 1);
138 dfm_put_record (trns->writer, " ", 1); /* XXX */
127139
128140 if (trns->writer != NULL && dfm_write_error (trns->writer))
129141 return TRNS_ERROR;
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
135135 bool print_table = 0;
136136 struct print_trns *trns;
137137 struct file_handle *fh = NULL;
138 char *encoding = NULL;
138139 struct pool *tmp_pool;
139140
140141 /* Fill in prt to facilitate error-handling. */
158159 fh = fh_parse (lexer, FH_REF_FILE, NULL);
159160 if (fh == NULL)
160161 goto error;
162 }
163 else if (lex_match_id (lexer, "ENCODING"))
164 {
165 lex_match (lexer, T_EQUALS);
166 if (!lex_force_string (lexer))
167 goto error;
168
169 free (encoding);
170 encoding = ss_xstrdup (lex_tokss (lexer));
171
172 lex_get (lexer);
161173 }
162174 else if (lex_match_id (lexer, "RECORDS"))
163175 {
193205
194206 if (fh != NULL)
195207 {
196 trns->writer = dfm_open_writer (fh);
208 trns->writer = dfm_open_writer (fh, encoding);
197209 if (trns->writer == NULL)
198210 goto error;
199 trns->encoding = dfm_writer_get_legacy_encoding (trns->writer);
211 trns->encoding = dfm_writer_get_encoding (trns->writer);
200212 }
201213 else
202214 trns->encoding = UTF8;
324336
325337 if (lex_is_number (lexer) || lex_token (lexer) == T_LPAREN)
326338 {
327 if (!parse_var_placements (lexer, tmp_pool, var_cnt, false,
339 if (!parse_var_placements (lexer, tmp_pool, var_cnt, FMT_FOR_OUTPUT,
328340 &formats, &format_cnt))
329341 return false;
330342 add_space = false;
12081208 do
12091209 {
12101210 size_t head_ofs;
1211 size_t space;
12111212 size_t n;
12121213
12131214 lex_source_expand__ (src);
12141215
12151216 head_ofs = src->head - src->tail;
1217 space = src->allocated - head_ofs;
12161218 n = src->reader->class->read (src->reader, &src->buffer[head_ofs],
1217 src->allocated - head_ofs,
1219 space,
12181220 segmenter_get_prompt (&src->segmenter));
1221 assert (n <= space);
1222
12191223 if (n == 0)
12201224 {
12211225 /* End of input.
00 crosstabs.c
11 frequencies.c
2 regression.c
33
44 src_language_stats_built_sources = \
55 src/language/stats/crosstabs.c \
6 src/language/stats/frequencies.c \
7 src/language/stats/regression.c
6 src/language/stats/frequencies.c
87
98 language_stats_sources = \
109 src/language/stats/aggregate.c \
4948 src/language/stats/reliability.c \
5049 src/language/stats/roc.c \
5150 src/language/stats/roc.h \
51 src/language/stats/regression.c \
5252 src/language/stats/runs.h \
5353 src/language/stats/runs.c \
5454 src/language/stats/sign.c \
206206 nc - 1, nr - 1);
207207
208208 tab_vline (t, TAL_2, heading_columns, 0, nr - 1);
209
209210 tab_vline (t, TAL_1, 1, heading_rows, nr - 1);
210211
211212 for (r = 0 ; r < corr->n_vars1 ; ++r)
231232
232233 for (c = 0 ; c < matrix_cols ; ++c)
233234 {
234 const struct variable *v = corr->n_vars_total > corr->n_vars1 ? corr->vars[corr->n_vars_total - corr->n_vars1 + c] : corr->vars[c];
235 const struct variable *v = corr->n_vars_total > corr->n_vars1 ?
236 corr->vars[corr->n_vars_total - corr->n_vars1 - 1 + c] : corr->vars[c];
235237 tab_text (t, heading_columns + c, 0, TAB_LEFT | TAT_TITLE, var_to_string (v));
236238 }
237239
241243 for (c = 0 ; c < matrix_cols ; ++c)
242244 {
243245 unsigned char flags = 0;
244 const int col_index = corr->n_vars_total - corr->n_vars1 + c;
246 const int col_index = corr->n_vars_total > corr->n_vars1 ?
247 corr->n_vars_total - corr->n_vars1 - 1 + c :
248 c;
245249 double pearson = gsl_matrix_get (cm, r, col_index);
246250 double w = gsl_matrix_get (samples, r, col_index);
247251 double sig = opts->tails * significance_of_correlation (pearson, w);
308312 if ( opts->statistics & STATS_DESCRIPTIVES)
309313 output_descriptives (corr, mean_matrix, var_matrix, samples_matrix);
310314
311 output_correlation (corr, opts,
312 corr_matrix,
313 samples_matrix,
314 cov_matrix);
315 output_correlation (corr, opts, corr_matrix,
316 samples_matrix, cov_matrix);
315317
316318 covariance_destroy (cov);
317319 gsl_matrix_free (corr_matrix);
3939 #include "math/interaction.h"
4040 #include "math/box-whisker.h"
4141 #include "math/categoricals.h"
42 #include "math/chart-geometry.h"
4243 #include "math/histogram.h"
4344 #include "math/moments.h"
4445 #include "math/np.h"
5051
5152 #include "output/charts/boxplot.h"
5253 #include "output/charts/np-plot.h"
54 #include "output/charts/spreadlevel-plot.h"
5355 #include "output/charts/plot-hist.h"
5456
5557 #include "language/command.h"
6264 #include "gettext.h"
6365 #define _(msgid) gettext (msgid)
6466 #define N_(msgid) msgid
67
68 static void
69 append_value_name (const struct variable *var, const union value *val, struct string *str)
70 {
71 var_append_value_name (var, val, str);
72 if ( var_is_value_missing (var, val, MV_ANY))
73 ds_put_cstr (str, _(" (missing)"));
74 }
6575
6676 enum bp_mode
6777 {
93103 size_t n_iacts;
94104 struct interaction **iacts;
95105
96 enum mv_class exclude;
106 enum mv_class dep_excl;
107 enum mv_class fctr_excl;
97108
98109 const struct dictionary *dict;
99110
108119
109120 bool missing_pw;
110121
111 /* Test options require that casenumbers are known */
112 bool casenumbers;
113
114122 /* The case index of the ID value (or -1) if not applicable */
115123 size_t id_idx;
124 int id_width;
116125
117126 enum pc_alg pc_alg;
118127 double *ptiles;
121130 bool npplot;
122131 bool histogram;
123132 bool boxplot;
133 bool spreadlevel;
134 int sl_power;
124135
125136 enum bp_mode boxplot_mode;
126137
136147
137148 /* Either the casenumber or the value of the variable specified
138149 by the /ID subcommand which corresponds to this extremity */
139 double identity;
150 union value identity;
140151 };
141152
142153 struct exploratory_stats
297308
298309 ds_put_cstr (&label, var_to_string (ivar));
299310 ds_put_cstr (&label, " = ");
300 var_append_value_name (ivar, val, &label);
311 append_value_name (ivar, val, &label);
301312 ds_put_cstr (&label, "; ");
302313 }
303314
356367
357368 ds_put_cstr (&label, var_to_string (ivar));
358369 ds_put_cstr (&label, " = ");
359 var_append_value_name (ivar, val, &label);
370 append_value_name (ivar, val, &label);
360371 ds_put_cstr (&label, "; ");
361372 }
362373
423434
424435 ds_put_cstr (&label, var_to_string (ivar));
425436 ds_put_cstr (&label, " = ");
426 var_append_value_name (ivar, val, &label);
437 append_value_name (ivar, val, &label);
427438 ds_put_cstr (&label, "; ");
428439
429440 }
455466 }
456467 }
457468
469 static void
470 show_spreadlevel (const struct examine *cmd, int iact_idx)
471 {
472 const struct interaction *iact = cmd->iacts[iact_idx];
473 const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx);
474
475 int v;
476
477 /* Spreadlevel when there are no levels is not useful */
478 if (iact->n_vars == 0)
479 return;
480
481 for (v = 0; v < cmd->n_dep_vars; ++v)
482 {
483 int grp;
484 struct chart_item *sl;
485
486 struct string label;
487 ds_init_cstr (&label,
488 var_to_string (cmd->dep_vars[v]));
489
490 if (iact->n_vars > 0)
491 {
492 ds_put_cstr (&label, " (");
493 interaction_to_string (iact, &label);
494 ds_put_cstr (&label, ")");
495 }
496
497 sl = spreadlevel_plot_create (ds_cstr (&label), cmd->sl_power);
498
499 for (grp = 0; grp < n_cats; ++grp)
500 {
501 const struct exploratory_stats *es =
502 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
503
504 double median = percentile_calculate (es[v].quartiles[1], cmd->pc_alg);
505
506 double iqr = percentile_calculate (es[v].quartiles[2], cmd->pc_alg) -
507 percentile_calculate (es[v].quartiles[0], cmd->pc_alg);
508
509 spreadlevel_plot_add (sl, iqr, median);
510 }
511
512 if (sl == NULL)
513 msg (MW, _("Not creating spreadlevel chart for %s"), ds_cstr (&label));
514 else
515 chart_item_submit (sl);
516
517 ds_destroy (&label);
518 }
519 }
520
458521
459522 static void
460523 show_histogram (const struct examine *cmd, int iact_idx)
479542 categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp);
480543
481544 struct string label;
545
546 if (es[v].histogram == NULL)
547 continue;
548
482549 ds_init_cstr (&label,
483550 var_to_string (cmd->dep_vars[v]));
484551
492559
493560 ds_put_cstr (&label, var_to_string (ivar));
494561 ds_put_cstr (&label, " = ");
495 var_append_value_name (ivar, val, &label);
562 append_value_name (ivar, val, &label);
496563 ds_put_cstr (&label, "; ");
497564
498565 }
617684 {
618685 struct string str;
619686 ds_init_empty (&str);
620 var_append_value_name (ivar, val, &str);
687 append_value_name (ivar, val, &str);
621688
622689 tab_text (t,
623690 1 + ivar_idx,
785852 {
786853 struct string str;
787854 ds_init_empty (&str);
788 var_append_value_name (ivar, val, &str);
855 append_value_name (ivar, val, &str);
789856
790857 tab_text (t,
791858 1 + ivar_idx,
11011168 {
11021169 struct string str;
11031170 ds_init_empty (&str);
1104 var_append_value_name (ivar, val, &str);
1171 append_value_name (ivar, val, &str);
11051172
11061173 tab_text (t,
11071174 1 + ivar_idx,
11481215 &F_8_0);
11491216
11501217 /* The casenumber */
1218 if (cmd->id_var)
1219 tab_value (t,
1220 heading_columns,
1221 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1222 TAB_RIGHT,
1223 &es->maxima[e].identity,
1224 cmd->id_var,
1225 NULL);
1226 else
1227 tab_double (t,
1228 heading_columns,
1229 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1230 TAB_RIGHT,
1231 es->maxima[e].identity.f,
1232 &F_8_0);
1233
11511234 tab_double (t,
1152 heading_columns,
1153 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1154 0,
1155 es->maxima[e].identity,
1156 &F_8_0);
1157
1158
1159 tab_double (t,
1160 heading_columns + 1,
1161 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1162 0,
1163 es->maxima[e].val,
1164 0);
1165
1166
1235 heading_columns + 1,
1236 heading_rows + v * rows_per_var + i * rows_per_cat + e,
1237 0,
1238 es->maxima[e].val,
1239 var_get_print_format (cmd->dep_vars[v]));
1240
11671241
11681242 tab_double (t,
11691243 heading_columns - 1,
11731247 &F_8_0);
11741248
11751249 /* The casenumber */
1176 tab_double (t,
1177 heading_columns,
1178 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1179 0,
1180 es->minima[e].identity,
1181 &F_8_0);
1250 if (cmd->id_var)
1251 tab_value (t,
1252 heading_columns,
1253 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1254 TAB_RIGHT,
1255 &es->minima[e].identity,
1256 cmd->id_var,
1257 NULL);
1258 else
1259 tab_double (t,
1260 heading_columns,
1261 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
1262 TAB_RIGHT,
1263 es->minima[e].identity.f,
1264 &F_8_0);
11821265
11831266 tab_double (t,
11841267 heading_columns + 1,
11851268 heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e,
11861269 0,
11871270 es->minima[e].val,
1188 0);
1271 var_get_print_format (cmd->dep_vars[v]));
11891272 }
11901273 }
11911274 free (prev_val);
13031386 {
13041387 struct string str;
13051388 ds_init_empty (&str);
1306 var_append_value_name (ivar, val, &str);
1389 append_value_name (ivar, val, &str);
13071390
13081391 tab_text (t,
13091392 1 + ivar_idx, heading_rows + n_cats * v + i,
14631546 const struct variable *var = examine->dep_vars[v];
14641547 const double x = case_data (c, var)->f;
14651548
1466 if (var_is_value_missing (var, case_data (c, var), examine->exclude))
1549 if (var_is_value_missing (var, case_data (c, var), examine->dep_excl))
14671550 {
14681551 es[v].missing += weight;
14691552 continue;
14811564
14821565 moments_pass_one (es[v].mom, x, weight);
14831566
1484 /* Save the value and the casenumber to the writer */
1567 /* Save the value and the ID to the writer */
1568 assert (examine->id_idx != -1);
14851569 case_data_rw_idx (outcase, EX_VAL)->f = x;
1486 if ( examine->id_idx != -1)
1487 case_data_rw_idx (outcase, EX_ID)->f = case_data_idx (c, examine->id_idx)->f;
1570 value_copy (case_data_rw_idx (outcase, EX_ID),
1571 case_data_idx (c, examine->id_idx), examine->id_width);
14881572
14891573 case_data_rw_idx (outcase, EX_WT)->f = weight;
14901574
15151599
15161600 if (examine->histogram)
15171601 {
1602 /* Sturges Rule */
1603 double bin_width = fabs (es[v].minimum - es[v].maximum)
1604 / (1 + log2 (es[v].cc))
1605 ;
1606
15181607 es[v].histogram =
1519 histogram_create (10, es[v].minimum, es[v].maximum);
1608 histogram_create (bin_width, es[v].minimum, es[v].maximum);
15201609 }
15211610
15221611 es[v].sorted_reader = casewriter_make_reader (es[v].sorted_writer);
15251614
15261615 es[v].maxima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].maxima));
15271616 es[v].minima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].minima));
1617 for (i = 0; i < examine->calc_extremes; ++i)
1618 {
1619 value_init_pool (examine->pool, &es[v].maxima[i].identity, examine->id_width) ;
1620 value_init_pool (examine->pool, &es[v].minima[i].identity, examine->id_width) ;
1621 }
15281622
15291623 for (reader = casereader_clone (es[v].sorted_reader);
15301624 (c = casereader_read (reader)) != NULL; case_unref (c))
15441638 {
15451639 struct extremity *min = &es[v].minima[x];
15461640 min->val = val;
1547 min->identity = case_data_idx (c, EX_ID)->f;
1641 value_copy (&min->identity, case_data_idx (c, EX_ID), examine->id_width);
15481642 }
15491643 imin += wt;
15501644 }
15631657
15641658 max = &es[v].maxima[x];
15651659 max->val = val;
1566 max->identity = case_data_idx (c, EX_ID)->f;
1660 value_copy (&max->identity, case_data_idx (c, EX_ID), examine->id_width);
15671661 }
15681662 }
15691663 }
16141708 struct order_stats *os;
16151709
16161710 es[v].box_whisker = box_whisker_create (es[v].hinges,
1617 EX_ID);
1711 EX_ID, examine->id_var);
16181712
16191713 os = &es[v].box_whisker->parent;
16201714 order_stats_accumulate_idx (&os, 1,
17121806
17131807 cmd->wv = dict_get_weight (cmd->dict);
17141808
1715 cmd->id_idx = -1;
17161809 cmd->cats
17171810 = categoricals_create (cmd->iacts, cmd->n_iacts,
1718 cmd->wv, cmd->exclude);
1811 cmd->wv, cmd->dep_excl, cmd->fctr_excl);
17191812
17201813 categoricals_set_payload (cmd->cats, &payload, cmd, NULL);
17211814
1722 if (cmd->casenumbers)
1815 if (cmd->id_idx == -1)
17231816 {
17241817 struct ccase *c = casereader_peek (input, 0);
17251818
1726 if (cmd->id_var)
1727 cmd->id_idx = var_get_case_index (cmd->id_var);
1728 else
1729 {
1730 cmd->id_idx = case_get_value_cnt (c);
1731 input = casereader_create_arithmetic_sequence (input, 1.0, 1.0);
1732 }
1819 assert (cmd->id_var == NULL);
1820
1821 cmd->id_idx = case_get_value_cnt (c);
1822 input = casereader_create_arithmetic_sequence (input, 1.0, 1.0);
17331823
17341824 case_unref (c);
17351825 }
1736
1737 /* FIXME: Filter out missing factor variables */
17381826
17391827 /* Remove cases on a listwise basis if requested */
17401828 if ( cmd->missing_pw == false)
17411829 input = casereader_create_filter_missing (input,
17421830 cmd->dep_vars,
17431831 cmd->n_dep_vars,
1744 cmd->exclude,
1832 cmd->dep_excl,
17451833 NULL,
17461834 NULL);
17471835
17851873 if (cmd->npplot)
17861874 show_npplot (cmd, i);
17871875
1876 if (cmd->spreadlevel)
1877 show_spreadlevel (cmd, i);
1878
17881879 if (cmd->descriptives)
17891880 descriptives_report (cmd, i);
17901881 }
18051896 struct examine examine;
18061897 bool percentiles_seen = false;
18071898
1808 examine.casenumbers = false;
18091899 examine.missing_pw = false;
18101900 examine.disp_extremes = 0;
18111901 examine.calc_extremes = 0;
18141904 examine.pc_alg = PC_HAVERAGE;
18151905 examine.ptiles = NULL;
18161906 examine.n_percentiles = 0;
1817 examine.id_var = 0;
1907 examine.id_idx = -1;
1908 examine.id_width = 0;
1909 examine.id_var = NULL;
18181910 examine.boxplot_mode = BP_GROUPS;
18191911
18201912 examine.ex_proto = caseproto_create ();
1821 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */
1822 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* id */
1823 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */
18241913
18251914 examine.pool = pool_create ();
18261915
18331922 examine.iacts = iacts_mem = pool_zalloc (examine.pool, sizeof (struct interaction *));
18341923 examine.iacts[0] = interaction_create (NULL);
18351924
1836 examine.exclude = MV_ANY;
1925 examine.dep_excl = MV_ANY;
1926 examine.fctr_excl = MV_ANY;
18371927 examine.histogram = false;
18381928 examine.npplot = false;
18391929 examine.boxplot = false;
1930 examine.spreadlevel = false;
1931 examine.sl_power = 0;
18401932
18411933 examine.dict = dataset_dict (ds);
18421934
20152107 }
20162108 else if (lex_match_id (lexer, "EXCLUDE"))
20172109 {
2018 examine.exclude = MV_ANY;
2110 examine.dep_excl = MV_ANY;
20192111 }
20202112 else if (lex_match_id (lexer, "INCLUDE"))
20212113 {
2022 examine.exclude = MV_SYSTEM;
2114 examine.dep_excl = MV_SYSTEM;
2115 }
2116 else if (lex_match_id (lexer, "REPORT"))
2117 {
2118 examine.fctr_excl = MV_NEVER;
2119 }
2120 else if (lex_match_id (lexer, "NOREPORT"))
2121 {
2122 examine.fctr_excl = MV_ANY;
20232123 }
20242124 else
20252125 {
20642164 {
20652165 examine.histogram = true;
20662166 }
2167 else if (lex_match_id (lexer, "SPREADLEVEL"))
2168 {
2169 examine.spreadlevel = true;
2170 examine.sl_power = 0;
2171 if (lex_match (lexer, T_LPAREN))
2172 {
2173 examine.sl_power = lex_integer (lexer);
2174
2175 lex_get (lexer);
2176 if (! lex_force_match (lexer, T_RPAREN))
2177 goto error;
2178 }
2179 }
20672180 else if (lex_match_id (lexer, "NONE"))
20682181 {
20692182 examine.histogram = false;
21052218 }
21062219 }
21072220
2221
21082222 if ( totals_seen && nototals_seen)
21092223 {
21102224 msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
21242238 }
21252239
21262240
2241 if ( examine.id_var )
2242 {
2243 examine.id_idx = var_get_case_index (examine.id_var);
2244 examine.id_width = var_get_width (examine.id_var);
2245 }
2246
2247 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */
2248 examine.ex_proto = caseproto_add_width (examine.ex_proto, examine.id_width); /* id */
2249 examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */
2250
2251
21272252 if (examine.disp_extremes > 0)
21282253 {
21292254 examine.calc_extremes = examine.disp_extremes;
2130 examine.casenumbers = true;
2131 }
2132
2133 if (examine.boxplot)
2134 {
2135 examine.casenumbers = true;
2136 }
2137
2255 }
21382256
21392257 if (examine.descriptives && examine.calc_extremes == 0)
21402258 {
21832301
21842302 error:
21852303 caseproto_unref (examine.ex_proto);
2304 examine.iacts = iacts_mem;
21862305 for (i = 0; i < examine.n_iacts; ++i)
21872306 interaction_destroy (examine.iacts[i]);
21882307 free (examine.dep_vars);
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
15351535 const double e_lambda = gsl_vector_get (extracted_eigenvalues, i);
15361536 double e_percent = 100.0 * e_lambda / e_total ;
15371537
1538 const double r_lambda = gsl_vector_get (rotated_loadings, i);
1539 double r_percent = 100.0 * r_lambda / e_total ;
1540
15411538 c = 0;
15421539
15431540 tab_text_format (t, c++, i + heading_rows, TAB_LEFT | TAT_TITLE, _("%zu"), i + 1);
15441541
15451542 i_cum += i_percent;
15461543 e_cum += e_percent;
1547 r_cum += r_percent;
15481544
15491545 /* Initial Eigenvalues */
15501546 if (factor->print & PRINT_INITIAL)
15661562 }
15671563 }
15681564
1569 if (factor->print & PRINT_ROTATION)
1570 {
1571 if (i < idata->n_extractions)
1572 {
1573 tab_double (t, c++, i + heading_rows, 0, r_lambda, NULL);
1574 tab_double (t, c++, i + heading_rows, 0, r_percent, NULL);
1575 tab_double (t, c++, i + heading_rows, 0, r_cum, NULL);
1576 }
1577 }
1578
1565 if (rotated_loadings != NULL)
1566 {
1567 const double r_lambda = gsl_vector_get (rotated_loadings, i);
1568 double r_percent = 100.0 * r_lambda / e_total ;
1569
1570 if (factor->print & PRINT_ROTATION)
1571 {
1572 if (i < idata->n_extractions)
1573 {
1574 r_cum += r_percent;
1575 tab_double (t, c++, i + heading_rows, 0, r_lambda, NULL);
1576 tab_double (t, c++, i + heading_rows, 0, r_percent, NULL);
1577 tab_double (t, c++, i + heading_rows, 0, r_cum, NULL);
1578 }
1579 }
1580 }
15791581 }
15801582
15811583 tab_submit (t);
4242 #include "libpspp/str.h"
4343 #include "math/histogram.h"
4444 #include "math/moments.h"
45 #include "math/chart-geometry.h"
46
4547 #include "output/chart-item.h"
4648 #include "output/charts/piechart.h"
4749 #include "output/charts/plot-hist.h"
496498
497499 histogram = freq_tab_to_hist (frq, &vf->tab, vf->var);
498500
499 chart_item_submit (histogram_chart_create (
501 if ( histogram)
502 {
503 chart_item_submit (histogram_chart_create (
500504 histogram->gsl_hist, var_to_string(vf->var),
501505 vf->tab.valid_cases,
502506 d[FRQ_MEAN],
503507 d[FRQ_STDDEV],
504508 frq->hist->draw_normal));
505509
506 statistic_destroy (&histogram->parent);
510 statistic_destroy (&histogram->parent);
511 }
507512 }
508513
509514 if (frq->pie)
11131118 {
11141119 double x_min, x_max, valid_freq;
11151120 int i;
1116
1121 double bin_width;
11171122 struct histogram *histogram;
11181123 double iqr;
1119 int bins;
11201124
11211125 /* Find out the extremes of the x value, within the range to be included in
11221126 the histogram, and sum the total frequency of those values. */
11361140
11371141 /* Freedman-Diaconis' choice of bin width. */
11381142 iqr = calculate_iqr (frq);
1139 if (iqr != SYSMIS)
1140 {
1141 double bin_width = 2 * iqr / pow (valid_freq, 1.0 / 3.0);
1142 bins = (x_max - x_min) / bin_width;
1143 if (bins < 5)
1144 bins = 5;
1145 else if (bins > 400)
1146 bins = 400;
1147 }
1148 else
1149 bins = 5;
1150
1151 histogram = histogram_create (bins, x_min, x_max);
1143 bin_width = 2 * iqr / pow (valid_freq, 1.0 / 3.0);
1144
1145 histogram = histogram_create (bin_width, x_min, x_max);
1146
1147 if ( histogram == NULL)
1148 return NULL;
1149
11521150 for (i = 0; i < ft->n_valid; i++)
11531151 {
11541152 const struct freq *f = &ft->valid[i];
589589 struct covariance *cov;
590590
591591 ws.cats = categoricals_create (cmd->interactions, cmd->n_interactions,
592 cmd->wv, cmd->exclude);
592 cmd->wv, cmd->exclude, MV_ANY);
593593
594594 cov = covariance_2pass_create (cmd->n_dep_vars, cmd->dep_vars,
595595 ws.cats, cmd->wv, cmd->exclude);
944944 struct mtable *table = &cmd->table[t];
945945 table->cats
946946 = categoricals_create (table->interactions,
947 table->n_layers, wv, cmd->exclude);
947 table->n_layers, wv, cmd->dep_exclude, cmd->exclude);
948948
949949 categoricals_set_payload (table->cats, &payload, cmd, table);
950950 }
11611161 tab_text (t, 0,
11621162 heading_rows + dv * n_cats,
11631163 TAB_RIGHT | TAT_TITLE,
1164 var_get_name (table->dep_vars[dv])
1164 var_to_string (table->dep_vars[dv])
11651165 );
11661166
11671167 if ( dv > 0)
666666 payload.destroy = NULL;
667667
668668 ws.vws[v].cat = categoricals_create (&inter, 1, cmd->wv,
669 cmd->exclude);
669 cmd->exclude, cmd->exclude);
670670
671671 categoricals_set_payload (ws.vws[v].cat, &payload,
672672 CONST_CAST (struct variable *, cmd->vars[v]),
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2005, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include <stdbool.h>
19
20 #include <gsl/gsl_cdf.h>
21 #include <gsl/gsl_matrix.h>
22
23 #include <data/dataset.h>
24
25 #include "language/command.h"
26 #include "language/lexer/lexer.h"
27 #include "language/lexer/value-parser.h"
28 #include "language/lexer/variable-parser.h"
29
30
31 #include "data/casegrouper.h"
32 #include "data/casereader.h"
33 #include "data/dictionary.h"
34
35 #include "math/covariance.h"
36 #include "math/linreg.h"
37 #include "math/moments.h"
38
39 #include "libpspp/message.h"
40 #include "libpspp/taint.h"
41
42 #include "output/tab.h"
43
44 #include "gettext.h"
45 #define _(msgid) gettext (msgid)
46 #define N_(msgid) msgid
47
48
49 #include <gl/intprops.h>
50
51 #define REG_LARGE_DATA 1000
52
53 struct regression
54 {
55 struct dataset *ds;
56
57 const struct variable **vars;
58 size_t n_vars;
59
60 const struct variable **dep_vars;
61 size_t n_dep_vars;
62
63 bool r;
64 bool coeff;
65 bool anova;
66 bool bcov;
67
68
69 bool resid;
70 bool pred;
71
72 linreg **models;
73 };
74
75
76 static void run_regression (const struct regression *cmd, struct casereader *input);
77
78
79
80 /*
81 Transformations for saving predicted values
82 and residuals, etc.
83 */
84 struct reg_trns
85 {
86 int n_trns; /* Number of transformations. */
87 int trns_id; /* Which trns is this one? */
88 linreg *c; /* Linear model for this trns. */
89 };
90
91 /*
92 Gets the predicted values.
93 */
94 static int
95 regression_trns_pred_proc (void *t_, struct ccase **c,
96 casenumber case_idx UNUSED)
97 {
98 size_t i;
99 size_t n_vals;
100 struct reg_trns *trns = t_;
101 linreg *model;
102 union value *output = NULL;
103 const union value *tmp;
104 double *vals;
105 const struct variable **vars = NULL;
106
107 assert (trns != NULL);
108 model = trns->c;
109 assert (model != NULL);
110 assert (model->depvar != NULL);
111 assert (model->pred != NULL);
112
113 vars = linreg_get_vars (model);
114 n_vals = linreg_n_coeffs (model);
115 vals = xnmalloc (n_vals, sizeof (*vals));
116 *c = case_unshare (*c);
117
118 output = case_data_rw (*c, model->pred);
119
120 for (i = 0; i < n_vals; i++)
121 {
122 tmp = case_data (*c, vars[i]);
123 vals[i] = tmp->f;
124 }
125 output->f = linreg_predict (model, vals, n_vals);
126 free (vals);
127 return TRNS_CONTINUE;
128 }
129
130 /*
131 Gets the residuals.
132 */
133 static int
134 regression_trns_resid_proc (void *t_, struct ccase **c,
135 casenumber case_idx UNUSED)
136 {
137 size_t i;
138 size_t n_vals;
139 struct reg_trns *trns = t_;
140 linreg *model;
141 union value *output = NULL;
142 const union value *tmp;
143 double *vals = NULL;
144 double obs;
145 const struct variable **vars = NULL;
146
147 assert (trns != NULL);
148 model = trns->c;
149 assert (model != NULL);
150 assert (model->depvar != NULL);
151 assert (model->resid != NULL);
152
153 vars = linreg_get_vars (model);
154 n_vals = linreg_n_coeffs (model);
155
156 vals = xnmalloc (n_vals, sizeof (*vals));
157 *c = case_unshare (*c);
158 output = case_data_rw (*c, model->resid);
159 assert (output != NULL);
160
161 for (i = 0; i < n_vals; i++)
162 {
163 tmp = case_data (*c, vars[i]);
164 vals[i] = tmp->f;
165 }
166 tmp = case_data (*c, model->depvar);
167 obs = tmp->f;
168 output->f = linreg_residual (model, obs, vals, n_vals);
169 free (vals);
170
171 return TRNS_CONTINUE;
172 }
173
174
175 static char *
176 reg_get_name (const struct dictionary *dict, const char *prefix)
177 {
178 char *name;
179 int i;
180
181 /* XXX handle too-long prefixes */
182 name = xmalloc (strlen (prefix) + INT_BUFSIZE_BOUND (i) + 1);
183 for (i = 1; ; i++)
184 {
185 sprintf (name, "%s%d", prefix, i);
186 if (dict_lookup_var (dict, name) == NULL)
187 return name;
188 }
189 }
190
191 /*
192 Free the transformation. Free its linear model if this
193 transformation is the last one.
194 */
195 static bool
196 regression_trns_free (void *t_)
197 {
198 bool result = true;
199 struct reg_trns *t = t_;
200
201 if (t->trns_id == t->n_trns)
202 {
203 result = linreg_free (t->c);
204 }
205 free (t);
206
207 return result;
208 }
209
210 static void
211 reg_save_var (struct dataset *ds, const char *prefix, trns_proc_func * f,
212 linreg * c, struct variable **v, int n_trns)
213 {
214 struct dictionary *dict = dataset_dict (ds);
215 static int trns_index = 1;
216 char *name;
217 struct variable *new_var;
218 struct reg_trns *t = NULL;
219
220 t = xmalloc (sizeof (*t));
221 t->trns_id = trns_index;
222 t->n_trns = n_trns;
223 t->c = c;
224
225 name = reg_get_name (dict, prefix);
226 new_var = dict_create_var_assert (dict, name, 0);
227 free (name);
228
229 *v = new_var;
230 add_transformation (ds, f, regression_trns_free, t);
231 trns_index++;
232 }
233
234 static void
235 subcommand_save (const struct regression *cmd)
236 {
237 linreg **lc;
238 int n_trns = 0;
239
240 if ( cmd->resid ) n_trns++;
241 if ( cmd->pred ) n_trns++;
242
243 n_trns *= cmd->n_dep_vars;
244
245 for (lc = cmd->models; lc < cmd->models + cmd->n_dep_vars; lc++)
246 {
247 if (*lc != NULL)
248 {
249 if ((*lc)->depvar != NULL)
250 {
251 if (cmd->resid)
252 {
253 reg_save_var (cmd->ds, "RES", regression_trns_resid_proc, *lc,
254 &(*lc)->resid, n_trns);
255 }
256 if (cmd->pred)
257 {
258 reg_save_var (cmd->ds, "PRED", regression_trns_pred_proc, *lc,
259 &(*lc)->pred, n_trns);
260 }
261 }
262 }
263 }
264 }
265
266 int
267 cmd_regression (struct lexer *lexer, struct dataset *ds)
268 {
269 struct regression regression;
270 const struct dictionary *dict = dataset_dict (ds);
271
272 memset (&regression, 0, sizeof (struct regression));
273
274 regression.anova = true;
275 regression.coeff = true;
276 regression.r = true;
277
278 regression.pred = false;
279 regression.resid = false;
280
281 regression.ds = ds;
282
283 /* Accept an optional, completely pointless "/VARIABLES=" */
284 lex_match (lexer, T_SLASH);
285 if (lex_match_id (lexer, "VARIABLES"))
286 {
287 if (! lex_force_match (lexer, T_EQUALS) )
288 goto error;
289 }
290
291 if (!parse_variables_const (lexer, dict,
292 &regression.vars, &regression.n_vars,
293 PV_NO_DUPLICATE | PV_NUMERIC))
294 goto error;
295
296
297 while (lex_token (lexer) != T_ENDCMD)
298 {
299 lex_match (lexer, T_SLASH);
300
301 if (lex_match_id (lexer, "DEPENDENT"))
302 {
303 if (! lex_force_match (lexer, T_EQUALS) )
304 goto error;
305
306 if (!parse_variables_const (lexer, dict,
307 &regression.dep_vars, &regression.n_dep_vars,
308 PV_NO_DUPLICATE | PV_NUMERIC))
309 goto error;
310 }
311 else if (lex_match_id (lexer, "METHOD"))
312 {
313 lex_match (lexer, T_EQUALS);
314
315 if (!lex_force_match_id (lexer, "ENTER"))
316 {
317 goto error;
318 }
319 }
320 else if (lex_match_id (lexer, "STATISTICS"))
321 {
322 lex_match (lexer, T_EQUALS);
323
324 while (lex_token (lexer) != T_ENDCMD
325 && lex_token (lexer) != T_SLASH)
326 {
327 if (lex_match (lexer, T_ALL))
328 {
329 }
330 else if (lex_match_id (lexer, "DEFAULTS"))
331 {
332 }
333 else if (lex_match_id (lexer, "R"))
334 {
335 }
336 else if (lex_match_id (lexer, "COEFF"))
337 {
338 }
339 else if (lex_match_id (lexer, "ANOVA"))
340 {
341 }
342 else if (lex_match_id (lexer, "BCOV"))
343 {
344 }
345 else
346 {
347 lex_error (lexer, NULL);
348 goto error;
349 }
350 }
351 }
352 else if (lex_match_id (lexer, "SAVE"))
353 {
354 lex_match (lexer, T_EQUALS);
355
356 while (lex_token (lexer) != T_ENDCMD
357 && lex_token (lexer) != T_SLASH)
358 {
359 if (lex_match_id (lexer, "PRED"))
360 {
361 regression.pred = true;
362 }
363 else if (lex_match_id (lexer, "RESID"))
364 {
365 regression.resid = true;
366 }
367 else
368 {
369 lex_error (lexer, NULL);
370 goto error;
371 }
372 }
373 }
374 else
375 {
376 lex_error (lexer, NULL);
377 goto error;
378 }
379 }
380
381 if (!regression.vars)
382 {
383 dict_get_vars (dict, &regression.vars, &regression.n_vars, 0);
384 }
385
386
387 regression.models = xcalloc (regression.n_dep_vars, sizeof *regression.models);
388
389 {
390 struct casegrouper *grouper;
391 struct casereader *group;
392 bool ok;
393
394 grouper = casegrouper_create_splits (proc_open (ds), dict);
395 while (casegrouper_get_next_group (grouper, &group))
396 run_regression (&regression, group);
397 ok = casegrouper_destroy (grouper);
398 ok = proc_commit (ds) && ok;
399 }
400
401 if (regression.pred || regression.resid )
402 subcommand_save (&regression);
403
404
405 return CMD_SUCCESS;
406
407 error:
408 return CMD_FAILURE;
409 }
410
411
412 static size_t
413 get_n_all_vars (const struct regression *cmd)
414 {
415 size_t result = cmd->n_vars;
416 size_t i;
417 size_t j;
418
419 result += cmd->n_dep_vars;
420 for (i = 0; i < cmd->n_dep_vars; i++)
421 {
422 for (j = 0; j < cmd->n_vars; j++)
423 {
424 if (cmd->vars[j] == cmd->dep_vars[i])
425 {
426 result--;
427 }
428 }
429 }
430 return result;
431 }
432
433 static void
434 fill_all_vars (const struct variable **vars, const struct regression *cmd)
435 {
436 size_t i;
437 size_t j;
438 bool absent;
439
440 for (i = 0; i < cmd->n_vars; i++)
441 {
442 vars[i] = cmd->vars[i];
443 }
444 for (i = 0; i < cmd->n_dep_vars; i++)
445 {
446 absent = true;
447 for (j = 0; j < cmd->n_vars; j++)
448 {
449 if (cmd->dep_vars[i] == cmd->vars[j])
450 {
451 absent = false;
452 break;
453 }
454 }
455 if (absent)
456 {
457 vars[i + cmd->n_vars] = cmd->dep_vars[i];
458 }
459 }
460 }
461
462 /*
463 Is variable k the dependent variable?
464 */
465 static bool
466 is_depvar (const struct regression *cmd, size_t k, const struct variable *v)
467 {
468 return v == cmd->vars[k];
469 }
470
471
472 /* Identify the explanatory variables in v_variables. Returns
473 the number of independent variables. */
474 static int
475 identify_indep_vars (const struct regression *cmd,
476 const struct variable **indep_vars,
477 const struct variable *depvar)
478 {
479 int n_indep_vars = 0;
480 int i;
481
482 for (i = 0; i < cmd->n_vars; i++)
483 if (!is_depvar (cmd, i, depvar))
484 indep_vars[n_indep_vars++] = cmd->vars[i];
485 if ((n_indep_vars < 1) && is_depvar (cmd, 0, depvar))
486 {
487 /*
488 There is only one independent variable, and it is the same
489 as the dependent variable. Print a warning and continue.
490 */
491 msg (SE,
492 gettext ("The dependent variable is equal to the independent variable."
493 "The least squares line is therefore Y=X."
494 "Standard errors and related statistics may be meaningless."));
495 n_indep_vars = 1;
496 indep_vars[0] = cmd->vars[0];
497 }
498 return n_indep_vars;
499 }
500
501
502 static double
503 fill_covariance (gsl_matrix *cov, struct covariance *all_cov,
504 const struct variable **vars,
505 size_t n_vars, const struct variable *dep_var,
506 const struct variable **all_vars, size_t n_all_vars,
507 double *means)
508 {
509 size_t i;
510 size_t j;
511 size_t dep_subscript;
512 size_t *rows;
513 const gsl_matrix *ssizes;
514 const gsl_matrix *mean_matrix;
515 const gsl_matrix *ssize_matrix;
516 double result = 0.0;
517
518 gsl_matrix *cm = covariance_calculate_unnormalized (all_cov);
519
520 if ( cm == NULL)
521 return 0;
522
523 rows = xnmalloc (cov->size1 - 1, sizeof (*rows));
524
525 for (i = 0; i < n_all_vars; i++)
526 {
527 for (j = 0; j < n_vars; j++)
528 {
529 if (vars[j] == all_vars[i])
530 {
531 rows[j] = i;
532 }
533 }
534 if (all_vars[i] == dep_var)
535 {
536 dep_subscript = i;
537 }
538 }
539 mean_matrix = covariance_moments (all_cov, MOMENT_MEAN);
540 ssize_matrix = covariance_moments (all_cov, MOMENT_NONE);
541 for (i = 0; i < cov->size1 - 1; i++)
542 {
543 means[i] = gsl_matrix_get (mean_matrix, rows[i], 0)
544 / gsl_matrix_get (ssize_matrix, rows[i], 0);
545 for (j = 0; j < cov->size2 - 1; j++)
546 {
547 gsl_matrix_set (cov, i, j, gsl_matrix_get (cm, rows[i], rows[j]));
548 gsl_matrix_set (cov, j, i, gsl_matrix_get (cm, rows[j], rows[i]));
549 }
550 }
551 means[cov->size1 - 1] = gsl_matrix_get (mean_matrix, dep_subscript, 0)
552 / gsl_matrix_get (ssize_matrix, dep_subscript, 0);
553 ssizes = covariance_moments (all_cov, MOMENT_NONE);
554 result = gsl_matrix_get (ssizes, dep_subscript, rows[0]);
555 for (i = 0; i < cov->size1 - 1; i++)
556 {
557 gsl_matrix_set (cov, i, cov->size1 - 1,
558 gsl_matrix_get (cm, rows[i], dep_subscript));
559 gsl_matrix_set (cov, cov->size1 - 1, i,
560 gsl_matrix_get (cm, rows[i], dep_subscript));
561 if (result > gsl_matrix_get (ssizes, rows[i], dep_subscript))
562 {
563 result = gsl_matrix_get (ssizes, rows[i], dep_subscript);
564 }
565 }
566 gsl_matrix_set (cov, cov->size1 - 1, cov->size1 - 1,
567 gsl_matrix_get (cm, dep_subscript, dep_subscript));
568 free (rows);
569 gsl_matrix_free (cm);
570 return result;
571 }
572
573
574 /*
575 STATISTICS subcommand output functions.
576 */
577 static void reg_stats_r (linreg *, void *);
578 static void reg_stats_coeff (linreg *, void *);
579 static void reg_stats_anova (linreg *, void *);
580 static void reg_stats_bcov (linreg *, void *);
581
582 static void statistics_keyword_output (void (*)(linreg *, void *),
583 bool, linreg *, void *);
584
585
586
587 static void
588 subcommand_statistics (const struct regression *cmd , linreg * c, void *aux)
589 {
590 statistics_keyword_output (reg_stats_r, cmd->r, c, aux);
591 statistics_keyword_output (reg_stats_anova, cmd->anova, c, aux);
592 statistics_keyword_output (reg_stats_coeff, cmd->coeff, c, aux);
593 statistics_keyword_output (reg_stats_bcov, cmd->bcov, c, aux);
594 }
595
596
597 static void
598 run_regression (const struct regression *cmd, struct casereader *input)
599 {
600 size_t i;
601 int n_indep = 0;
602 int k;
603 double *means;
604 struct ccase *c;
605 struct covariance *cov;
606 const struct variable **vars;
607 const struct variable **all_vars;
608 const struct variable *dep_var;
609 struct casereader *reader;
610 size_t n_all_vars;
611
612 linreg **models = cmd->models;
613
614 n_all_vars = get_n_all_vars (cmd);
615 all_vars = xnmalloc (n_all_vars, sizeof (*all_vars));
616 fill_all_vars (all_vars, cmd);
617 vars = xnmalloc (cmd->n_vars, sizeof (*vars));
618 means = xnmalloc (n_all_vars, sizeof (*means));
619 cov = covariance_1pass_create (n_all_vars, all_vars,
620 dict_get_weight (dataset_dict (cmd->ds)), MV_ANY);
621
622 reader = casereader_clone (input);
623 reader = casereader_create_filter_missing (reader, all_vars, n_all_vars,
624 MV_ANY, NULL, NULL);
625
626
627 for (; (c = casereader_read (reader)) != NULL; case_unref (c))
628 {
629 covariance_accumulate (cov, c);
630 }
631
632 for (k = 0; k < cmd->n_dep_vars; k++)
633 {
634 double n_data;
635
636 gsl_matrix *this_cm;
637 dep_var = cmd->dep_vars[k];
638 n_indep = identify_indep_vars (cmd, vars, dep_var);
639
640 this_cm = gsl_matrix_alloc (n_indep + 1, n_indep + 1);
641 n_data = fill_covariance (this_cm, cov, vars, n_indep,
642 dep_var, all_vars, n_all_vars, means);
643 models[k] = linreg_alloc (dep_var, (const struct variable **) vars,
644 n_data, n_indep);
645 models[k]->depvar = dep_var;
646 for (i = 0; i < n_indep; i++)
647 {
648 linreg_set_indep_variable_mean (models[k], i, means[i]);
649 }
650 linreg_set_depvar_mean (models[k], means[i]);
651 /*
652 For large data sets, use QR decomposition.
653 */
654 if (n_data > sqrt (n_indep) && n_data > REG_LARGE_DATA)
655 {
656 models[k]->method = LINREG_QR;
657 }
658
659 if (n_data > 0)
660 {
661 /*
662 Find the least-squares estimates and other statistics.
663 */
664 linreg_fit (this_cm, models[k]);
665
666 if (!taint_has_tainted_successor (casereader_get_taint (input)))
667 {
668 subcommand_statistics (cmd, models[k], this_cm);
669 }
670 }
671 else
672 {
673 msg (SE,
674 _("No valid data found. This command was skipped."));
675 linreg_free (models[k]);
676 models[k] = NULL;
677 }
678 gsl_matrix_free (this_cm);
679 }
680
681 casereader_destroy (reader);
682 free (vars);
683 free (all_vars);
684 free (means);
685 casereader_destroy (input);
686 covariance_destroy (cov);
687 }
688
689
690
691
692
693 static void
694 reg_stats_r (linreg *c, void *aux UNUSED)
695 {
696 struct tab_table *t;
697 int n_rows = 2;
698 int n_cols = 5;
699 double rsq;
700 double adjrsq;
701 double std_error;
702
703 assert (c != NULL);
704 rsq = linreg_ssreg (c) / linreg_sst (c);
705 adjrsq = 1.0 - (1.0 - rsq) * (linreg_n_obs (c) - 1.0) / (linreg_n_obs (c) - linreg_n_coeffs (c));
706 std_error = sqrt (linreg_mse (c));
707 t = tab_create (n_cols, n_rows);
708 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
709 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
710 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
711 tab_vline (t, TAL_0, 1, 0, 0);
712
713 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("R"));
714 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("R Square"));
715 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Adjusted R Square"));
716 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error of the Estimate"));
717 tab_double (t, 1, 1, TAB_RIGHT, sqrt (rsq), NULL);
718 tab_double (t, 2, 1, TAB_RIGHT, rsq, NULL);
719 tab_double (t, 3, 1, TAB_RIGHT, adjrsq, NULL);
720 tab_double (t, 4, 1, TAB_RIGHT, std_error, NULL);
721 tab_title (t, _("Model Summary"));
722 tab_submit (t);
723 }
724
725 /*
726 Table showing estimated regression coefficients.
727 */
728 static void
729 reg_stats_coeff (linreg * c, void *aux_)
730 {
731 size_t j;
732 int n_cols = 7;
733 int n_rows;
734 int this_row;
735 double t_stat;
736 double pval;
737 double std_err;
738 double beta;
739 const char *label;
740
741 const struct variable *v;
742 struct tab_table *t;
743 gsl_matrix *cov = aux_;
744
745 assert (c != NULL);
746 n_rows = linreg_n_coeffs (c) + 3;
747
748 t = tab_create (n_cols, n_rows);
749 tab_headers (t, 2, 0, 1, 0);
750 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
751 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
752 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
753 tab_vline (t, TAL_0, 1, 0, 0);
754
755 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("B"));
756 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
757 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Beta"));
758 tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("t"));
759 tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
760 tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("(Constant)"));
761 tab_double (t, 2, 1, 0, linreg_intercept (c), NULL);
762 std_err = sqrt (gsl_matrix_get (linreg_cov (c), 0, 0));
763 tab_double (t, 3, 1, 0, std_err, NULL);
764 tab_double (t, 4, 1, 0, 0.0, NULL);
765 t_stat = linreg_intercept (c) / std_err;
766 tab_double (t, 5, 1, 0, t_stat, NULL);
767 pval = 2 * gsl_cdf_tdist_Q (fabs (t_stat), (double) (linreg_n_obs (c) - linreg_n_coeffs (c)));
768 tab_double (t, 6, 1, 0, pval, NULL);
769 for (j = 0; j < linreg_n_coeffs (c); j++)
770 {
771 struct string tstr;
772 ds_init_empty (&tstr);
773 this_row = j + 2;
774
775 v = linreg_indep_var (c, j);
776 label = var_to_string (v);
777 /* Do not overwrite the variable's name. */
778 ds_put_cstr (&tstr, label);
779 tab_text (t, 1, this_row, TAB_CENTER, ds_cstr (&tstr));
780 /*
781 Regression coefficients.
782 */
783 tab_double (t, 2, this_row, 0, linreg_coeff (c, j), NULL);
784 /*
785 Standard error of the coefficients.
786 */
787 std_err = sqrt (gsl_matrix_get (linreg_cov (c), j + 1, j + 1));
788 tab_double (t, 3, this_row, 0, std_err, NULL);
789 /*
790 Standardized coefficient, i.e., regression coefficient
791 if all variables had unit variance.
792 */
793 beta = sqrt (gsl_matrix_get (cov, j, j));
794 beta *= linreg_coeff (c, j) /
795 sqrt (gsl_matrix_get (cov, cov->size1 - 1, cov->size2 - 1));
796 tab_double (t, 4, this_row, 0, beta, NULL);
797
798 /*
799 Test statistic for H0: coefficient is 0.
800 */
801 t_stat = linreg_coeff (c, j) / std_err;
802 tab_double (t, 5, this_row, 0, t_stat, NULL);
803 /*
804 P values for the test statistic above.
805 */
806 pval =
807 2 * gsl_cdf_tdist_Q (fabs (t_stat),
808 (double) (linreg_n_obs (c) - linreg_n_coeffs (c)));
809 tab_double (t, 6, this_row, 0, pval, NULL);
810 ds_destroy (&tstr);
811 }
812 tab_title (t, _("Coefficients"));
813 tab_submit (t);
814 }
815
816 /*
817 Display the ANOVA table.
818 */
819 static void
820 reg_stats_anova (linreg * c, void *aux UNUSED)
821 {
822 int n_cols = 7;
823 int n_rows = 4;
824 const double msm = linreg_ssreg (c) / linreg_dfmodel (c);
825 const double mse = linreg_mse (c);
826 const double F = msm / mse;
827 const double pval = gsl_cdf_fdist_Q (F, c->dfm, c->dfe);
828
829 struct tab_table *t;
830
831 assert (c != NULL);
832 t = tab_create (n_cols, n_rows);
833 tab_headers (t, 2, 0, 1, 0);
834
835 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
836
837 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
838 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
839 tab_vline (t, TAL_0, 1, 0, 0);
840
841 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares"));
842 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
843 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
844 tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
845 tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
846
847 tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("Regression"));
848 tab_text (t, 1, 2, TAB_LEFT | TAT_TITLE, _("Residual"));
849 tab_text (t, 1, 3, TAB_LEFT | TAT_TITLE, _("Total"));
850
851 /* Sums of Squares */
852 tab_double (t, 2, 1, 0, linreg_ssreg (c), NULL);
853 tab_double (t, 2, 3, 0, linreg_sst (c), NULL);
854 tab_double (t, 2, 2, 0, linreg_sse (c), NULL);
855
856
857 /* Degrees of freedom */
858 tab_text_format (t, 3, 1, TAB_RIGHT, "%g", c->dfm);
859 tab_text_format (t, 3, 2, TAB_RIGHT, "%g", c->dfe);
860 tab_text_format (t, 3, 3, TAB_RIGHT, "%g", c->dft);
861
862 /* Mean Squares */
863 tab_double (t, 4, 1, TAB_RIGHT, msm, NULL);
864 tab_double (t, 4, 2, TAB_RIGHT, mse, NULL);
865
866 tab_double (t, 5, 1, 0, F, NULL);
867
868 tab_double (t, 6, 1, 0, pval, NULL);
869
870 tab_title (t, _("ANOVA"));
871 tab_submit (t);
872 }
873
874
875 static void
876 reg_stats_bcov (linreg * c, void *aux UNUSED)
877 {
878 int n_cols;
879 int n_rows;
880 int i;
881 int k;
882 int row;
883 int col;
884 const char *label;
885 struct tab_table *t;
886
887 assert (c != NULL);
888 n_cols = c->n_indeps + 1 + 2;
889 n_rows = 2 * (c->n_indeps + 1);
890 t = tab_create (n_cols, n_rows);
891 tab_headers (t, 2, 0, 1, 0);
892 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
893 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
894 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
895 tab_vline (t, TAL_0, 1, 0, 0);
896 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Model"));
897 tab_text (t, 1, 1, TAB_CENTER | TAT_TITLE, _("Covariances"));
898 for (i = 0; i < linreg_n_coeffs (c); i++)
899 {
900 const struct variable *v = linreg_indep_var (c, i);
901 label = var_to_string (v);
902 tab_text (t, 2, i, TAB_CENTER, label);
903 tab_text (t, i + 2, 0, TAB_CENTER, label);
904 for (k = 1; k < linreg_n_coeffs (c); k++)
905 {
906 col = (i <= k) ? k : i;
907 row = (i <= k) ? i : k;
908 tab_double (t, k + 2, i, TAB_CENTER,
909 gsl_matrix_get (c->cov, row, col), NULL);
910 }
911 }
912 tab_title (t, _("Coefficient Correlations"));
913 tab_submit (t);
914 }
915
916 static void
917 statistics_keyword_output (void (*function) (linreg *, void *),
918 bool keyword, linreg * c, void *aux)
919 {
920 if (keyword)
921 {
922 (*function) (c, aux);
923 }
924 }
+0
-1036
src/language/stats/regression.q less more
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2005, 2009, 2010, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include <gsl/gsl_cdf.h>
19 #include <gsl/gsl_matrix.h>
20 #include <gsl/gsl_vector.h>
21 #include <math.h>
22 #include <stdlib.h>
23
24 #include "data/case.h"
25 #include "data/casegrouper.h"
26 #include "data/casereader.h"
27 #include "data/dataset.h"
28 #include "data/dictionary.h"
29 #include "data/missing-values.h"
30 #include "data/transformations.h"
31 #include "data/value-labels.h"
32 #include "data/variable.h"
33 #include "language/command.h"
34 #include "language/data-io/file-handle.h"
35 #include "language/dictionary/split-file.h"
36 #include "language/lexer/lexer.h"
37 #include "libpspp/compiler.h"
38 #include "libpspp/message.h"
39 #include "libpspp/taint.h"
40 #include "math/covariance.h"
41 #include "math/linreg.h"
42 #include "math/moments.h"
43 #include "output/tab.h"
44
45 #include "gl/intprops.h"
46 #include "gl/xalloc.h"
47
48 #include "gettext.h"
49 #define _(msgid) gettext (msgid)
50
51 #define REG_LARGE_DATA 1000
52
53 /* (headers) */
54
55 /* (specification)
56 "REGRESSION" (regression_):
57 *variables=custom;
58 +statistics[st_]=r,
59 coeff,
60 anova,
61 outs,
62 zpp,
63 label,
64 sha,
65 ci,
66 bcov,
67 ses,
68 xtx,
69 collin,
70 tol,
71 selection,
72 f,
73 defaults,
74 all;
75 ^dependent=varlist;
76 +save[sv_]=resid,pred;
77 +method=enter.
78 */
79 /* (declarations) */
80 /* (functions) */
81 static struct cmd_regression cmd;
82
83 /*
84 Moments for each of the variables used.
85 */
86 struct moments_var
87 {
88 struct moments1 *m;
89 const struct variable *v;
90 };
91
92 /*
93 Transformations for saving predicted values
94 and residuals, etc.
95 */
96 struct reg_trns
97 {
98 int n_trns; /* Number of transformations. */
99 int trns_id; /* Which trns is this one? */
100 linreg *c; /* Linear model for this trns. */
101 };
102 /*
103 Variables used (both explanatory and response).
104 */
105 static const struct variable **v_variables;
106
107 /*
108 Number of variables.
109 */
110 static size_t n_variables;
111
112 static bool run_regression (struct casereader *, struct cmd_regression *,
113 struct dataset *, linreg **);
114
115 /*
116 STATISTICS subcommand output functions.
117 */
118 static void reg_stats_r (linreg *, void *);
119 static void reg_stats_coeff (linreg *, void *);
120 static void reg_stats_anova (linreg *, void *);
121 static void reg_stats_outs (linreg *, void *);
122 static void reg_stats_zpp (linreg *, void *);
123 static void reg_stats_label (linreg *, void *);
124 static void reg_stats_sha (linreg *, void *);
125 static void reg_stats_ci (linreg *, void *);
126 static void reg_stats_f (linreg *, void *);
127 static void reg_stats_bcov (linreg *, void *);
128 static void reg_stats_ses (linreg *, void *);
129 static void reg_stats_xtx (linreg *, void *);
130 static void reg_stats_collin (linreg *, void *);
131 static void reg_stats_tol (linreg *, void *);
132 static void reg_stats_selection (linreg *, void *);
133 static void statistics_keyword_output (void (*)(linreg *, void *),
134 int, linreg *, void *);
135
136 static void
137 reg_stats_r (linreg *c, void *aux UNUSED)
138 {
139 struct tab_table *t;
140 int n_rows = 2;
141 int n_cols = 5;
142 double rsq;
143 double adjrsq;
144 double std_error;
145
146 assert (c != NULL);
147 rsq = linreg_ssreg (c) / linreg_sst (c);
148 adjrsq = 1.0 - (1.0 - rsq) * (linreg_n_obs (c) - 1.0) / (linreg_n_obs (c) - linreg_n_coeffs (c));
149 std_error = sqrt (linreg_mse (c));
150 t = tab_create (n_cols, n_rows);
151 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
152 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
153 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
154 tab_vline (t, TAL_0, 1, 0, 0);
155
156 tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("R"));
157 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("R Square"));
158 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Adjusted R Square"));
159 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error of the Estimate"));
160 tab_double (t, 1, 1, TAB_RIGHT, sqrt (rsq), NULL);
161 tab_double (t, 2, 1, TAB_RIGHT, rsq, NULL);
162 tab_double (t, 3, 1, TAB_RIGHT, adjrsq, NULL);
163 tab_double (t, 4, 1, TAB_RIGHT, std_error, NULL);
164 tab_title (t, _("Model Summary"));
165 tab_submit (t);
166 }
167
168 /*
169 Table showing estimated regression coefficients.
170 */
171 static void
172 reg_stats_coeff (linreg * c, void *aux_)
173 {
174 size_t j;
175 int n_cols = 7;
176 int n_rows;
177 int this_row;
178 double t_stat;
179 double pval;
180 double std_err;
181 double beta;
182 const char *label;
183
184 const struct variable *v;
185 struct tab_table *t;
186 gsl_matrix *cov = aux_;
187
188 assert (c != NULL);
189 n_rows = linreg_n_coeffs (c) + 3;
190
191 t = tab_create (n_cols, n_rows);
192 tab_headers (t, 2, 0, 1, 0);
193 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
194 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
195 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
196 tab_vline (t, TAL_0, 1, 0, 0);
197
198 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("B"));
199 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
200 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Beta"));
201 tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("t"));
202 tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
203 tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("(Constant)"));
204 tab_double (t, 2, 1, 0, linreg_intercept (c), NULL);
205 std_err = sqrt (gsl_matrix_get (linreg_cov (c), 0, 0));
206 tab_double (t, 3, 1, 0, std_err, NULL);
207 tab_double (t, 4, 1, 0, 0.0, NULL);
208 t_stat = linreg_intercept (c) / std_err;
209 tab_double (t, 5, 1, 0, t_stat, NULL);
210 pval = 2 * gsl_cdf_tdist_Q (fabs (t_stat), (double) (linreg_n_obs (c) - linreg_n_coeffs (c)));
211 tab_double (t, 6, 1, 0, pval, NULL);
212 for (j = 0; j < linreg_n_coeffs (c); j++)
213 {
214 struct string tstr;
215 ds_init_empty (&tstr);
216 this_row = j + 2;
217
218 v = linreg_indep_var (c, j);
219 label = var_to_string (v);
220 /* Do not overwrite the variable's name. */
221 ds_put_cstr (&tstr, label);
222 tab_text (t, 1, this_row, TAB_CENTER, ds_cstr (&tstr));
223 /*
224 Regression coefficients.
225 */
226 tab_double (t, 2, this_row, 0, linreg_coeff (c, j), NULL);
227 /*
228 Standard error of the coefficients.
229 */
230 std_err = sqrt (gsl_matrix_get (linreg_cov (c), j + 1, j + 1));
231 tab_double (t, 3, this_row, 0, std_err, NULL);
232 /*
233 Standardized coefficient, i.e., regression coefficient
234 if all variables had unit variance.
235 */
236 beta = sqrt (gsl_matrix_get (cov, j, j));
237 beta *= linreg_coeff (c, j) /
238 sqrt (gsl_matrix_get (cov, cov->size1 - 1, cov->size2 - 1));
239 tab_double (t, 4, this_row, 0, beta, NULL);
240
241 /*
242 Test statistic for H0: coefficient is 0.
243 */
244 t_stat = linreg_coeff (c, j) / std_err;
245 tab_double (t, 5, this_row, 0, t_stat, NULL);
246 /*
247 P values for the test statistic above.
248 */
249 pval =
250 2 * gsl_cdf_tdist_Q (fabs (t_stat),
251 (double) (linreg_n_obs (c) - linreg_n_coeffs (c)));
252 tab_double (t, 6, this_row, 0, pval, NULL);
253 ds_destroy (&tstr);
254 }
255 tab_title (t, _("Coefficients"));
256 tab_submit (t);
257 }
258
259 /*
260 Display the ANOVA table.
261 */
262 static void
263 reg_stats_anova (linreg * c, void *aux UNUSED)
264 {
265 int n_cols = 7;
266 int n_rows = 4;
267 const double msm = linreg_ssreg (c) / linreg_dfmodel (c);
268 const double mse = linreg_mse (c);
269 const double F = msm / mse;
270 const double pval = gsl_cdf_fdist_Q (F, c->dfm, c->dfe);
271
272 struct tab_table *t;
273
274 assert (c != NULL);
275 t = tab_create (n_cols, n_rows);
276 tab_headers (t, 2, 0, 1, 0);
277
278 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
279
280 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
281 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
282 tab_vline (t, TAL_0, 1, 0, 0);
283
284 tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares"));
285 tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
286 tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
287 tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
288 tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
289
290 tab_text (t, 1, 1, TAB_LEFT | TAT_TITLE, _("Regression"));
291 tab_text (t, 1, 2, TAB_LEFT | TAT_TITLE, _("Residual"));
292 tab_text (t, 1, 3, TAB_LEFT | TAT_TITLE, _("Total"));
293
294 /* Sums of Squares */
295 tab_double (t, 2, 1, 0, linreg_ssreg (c), NULL);
296 tab_double (t, 2, 3, 0, linreg_sst (c), NULL);
297 tab_double (t, 2, 2, 0, linreg_sse (c), NULL);
298
299
300 /* Degrees of freedom */
301 tab_text_format (t, 3, 1, TAB_RIGHT, "%g", c->dfm);
302 tab_text_format (t, 3, 2, TAB_RIGHT, "%g", c->dfe);
303 tab_text_format (t, 3, 3, TAB_RIGHT, "%g", c->dft);
304
305 /* Mean Squares */
306 tab_double (t, 4, 1, TAB_RIGHT, msm, NULL);
307 tab_double (t, 4, 2, TAB_RIGHT, mse, NULL);
308
309 tab_double (t, 5, 1, 0, F, NULL);
310
311 tab_double (t, 6, 1, 0, pval, NULL);
312
313 tab_title (t, _("ANOVA"));
314 tab_submit (t);
315 }
316
317 static void
318 reg_stats_outs (linreg * c, void *aux UNUSED)
319 {
320 assert (c != NULL);
321 }
322
323 static void
324 reg_stats_zpp (linreg * c, void *aux UNUSED)
325 {
326 assert (c != NULL);
327 }
328
329 static void
330 reg_stats_label (linreg * c, void *aux UNUSED)
331 {
332 assert (c != NULL);
333 }
334
335 static void
336 reg_stats_sha (linreg * c, void *aux UNUSED)
337 {
338 assert (c != NULL);
339 }
340 static void
341 reg_stats_ci (linreg * c, void *aux UNUSED)
342 {
343 assert (c != NULL);
344 }
345 static void
346 reg_stats_f (linreg * c, void *aux UNUSED)
347 {
348 assert (c != NULL);
349 }
350 static void
351 reg_stats_bcov (linreg * c, void *aux UNUSED)
352 {
353 int n_cols;
354 int n_rows;
355 int i;
356 int k;
357 int row;
358 int col;
359 const char *label;
360 struct tab_table *t;
361
362 assert (c != NULL);
363 n_cols = c->n_indeps + 1 + 2;
364 n_rows = 2 * (c->n_indeps + 1);
365 t = tab_create (n_cols, n_rows);
366 tab_headers (t, 2, 0, 1, 0);
367 tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1);
368 tab_hline (t, TAL_2, 0, n_cols - 1, 1);
369 tab_vline (t, TAL_2, 2, 0, n_rows - 1);
370 tab_vline (t, TAL_0, 1, 0, 0);
371 tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Model"));
372 tab_text (t, 1, 1, TAB_CENTER | TAT_TITLE, _("Covariances"));
373 for (i = 0; i < linreg_n_coeffs (c); i++)
374 {
375 const struct variable *v = linreg_indep_var (c, i);
376 label = var_to_string (v);
377 tab_text (t, 2, i, TAB_CENTER, label);
378 tab_text (t, i + 2, 0, TAB_CENTER, label);
379 for (k = 1; k < linreg_n_coeffs (c); k++)
380 {
381 col = (i <= k) ? k : i;
382 row = (i <= k) ? i : k;
383 tab_double (t, k + 2, i, TAB_CENTER,
384 gsl_matrix_get (c->cov, row, col), NULL);
385 }
386 }
387 tab_title (t, _("Coefficient Correlations"));
388 tab_submit (t);
389 }
390 static void
391 reg_stats_ses (linreg * c, void *aux UNUSED)
392 {
393 assert (c != NULL);
394 }
395 static void
396 reg_stats_xtx (linreg * c, void *aux UNUSED)
397 {
398 assert (c != NULL);
399 }
400 static void
401 reg_stats_collin (linreg * c, void *aux UNUSED)
402 {
403 assert (c != NULL);
404 }
405 static void
406 reg_stats_tol (linreg * c, void *aux UNUSED)
407 {
408 assert (c != NULL);
409 }
410 static void
411 reg_stats_selection (linreg * c, void *aux UNUSED)
412 {
413 assert (c != NULL);
414 }
415
416 static void
417 statistics_keyword_output (void (*function) (linreg *, void *),
418 int keyword, linreg * c, void *aux)
419 {
420 if (keyword)
421 {
422 (*function) (c, aux);
423 }
424 }
425
426 static void
427 subcommand_statistics (int *keywords, linreg * c, void *aux)
428 {
429 /*
430 The order here must match the order in which the STATISTICS
431 keywords appear in the specification section above.
432 */
433 enum
434 { r,
435 coeff,
436 anova,
437 outs,
438 zpp,
439 label,
440 sha,
441 ci,
442 bcov,
443 ses,
444 xtx,
445 collin,
446 tol,
447 selection,
448 f,
449 defaults,
450 all
451 };
452 int i;
453 int d = 1;
454
455 if (keywords[all])
456 {
457 /*
458 Set everything but F.
459 */
460 for (i = 0; i < f; i++)
461 {
462 keywords[i] = 1;
463 }
464 }
465 else
466 {
467 for (i = 0; i < all; i++)
468 {
469 if (keywords[i])
470 {
471 d = 0;
472 }
473 }
474 /*
475 Default output: ANOVA table, parameter estimates,
476 and statistics for variables not entered into model,
477 if appropriate.
478 */
479 if (keywords[defaults] | d)
480 {
481 keywords[anova] = 1;
482 keywords[outs] = 1;
483 keywords[coeff] = 1;
484 keywords[r] = 1;
485 }
486 }
487 statistics_keyword_output (reg_stats_r, keywords[r], c, aux);
488 statistics_keyword_output (reg_stats_anova, keywords[anova], c, aux);
489 statistics_keyword_output (reg_stats_coeff, keywords[coeff], c, aux);
490 statistics_keyword_output (reg_stats_outs, keywords[outs], c, aux);
491 statistics_keyword_output (reg_stats_zpp, keywords[zpp], c, aux);
492 statistics_keyword_output (reg_stats_label, keywords[label], c, aux);
493 statistics_keyword_output (reg_stats_sha, keywords[sha], c, aux);
494 statistics_keyword_output (reg_stats_ci, keywords[ci], c, aux);
495 statistics_keyword_output (reg_stats_f, keywords[f], c, aux);
496 statistics_keyword_output (reg_stats_bcov, keywords[bcov], c, aux);
497 statistics_keyword_output (reg_stats_ses, keywords[ses], c, aux);
498 statistics_keyword_output (reg_stats_xtx, keywords[xtx], c, aux);
499 statistics_keyword_output (reg_stats_collin, keywords[collin], c, aux);
500 statistics_keyword_output (reg_stats_tol, keywords[tol], c, aux);
501 statistics_keyword_output (reg_stats_selection, keywords[selection], c, aux);
502 }
503
504 /*
505 Free the transformation. Free its linear model if this
506 transformation is the last one.
507 */
508 static bool
509 regression_trns_free (void *t_)
510 {
511 bool result = true;
512 struct reg_trns *t = t_;
513
514 if (t->trns_id == t->n_trns)
515 {
516 result = linreg_free (t->c);
517 }
518 free (t);
519
520 return result;
521 }
522
523 /*
524 Gets the predicted values.
525 */
526 static int
527 regression_trns_pred_proc (void *t_, struct ccase **c,
528 casenumber case_idx UNUSED)
529 {
530 size_t i;
531 size_t n_vals;
532 struct reg_trns *trns = t_;
533 linreg *model;
534 union value *output = NULL;
535 const union value *tmp;
536 double *vals;
537 const struct variable **vars = NULL;
538
539 assert (trns != NULL);
540 model = trns->c;
541 assert (model != NULL);
542 assert (model->depvar != NULL);
543 assert (model->pred != NULL);
544
545 vars = linreg_get_vars (model);
546 n_vals = linreg_n_coeffs (model);
547 vals = xnmalloc (n_vals, sizeof (*vals));
548 *c = case_unshare (*c);
549
550 output = case_data_rw (*c, model->pred);
551
552 for (i = 0; i < n_vals; i++)
553 {
554 tmp = case_data (*c, vars[i]);
555 vals[i] = tmp->f;
556 }
557 output->f = linreg_predict (model, vals, n_vals);
558 free (vals);
559 return TRNS_CONTINUE;
560 }
561
562 /*
563 Gets the residuals.
564 */
565 static int
566 regression_trns_resid_proc (void *t_, struct ccase **c,
567 casenumber case_idx UNUSED)
568 {
569 size_t i;
570 size_t n_vals;
571 struct reg_trns *trns = t_;
572 linreg *model;
573 union value *output = NULL;
574 const union value *tmp;
575 double *vals = NULL;
576 double obs;
577 const struct variable **vars = NULL;
578
579 assert (trns != NULL);
580 model = trns->c;
581 assert (model != NULL);
582 assert (model->depvar != NULL);
583 assert (model->resid != NULL);
584
585 vars = linreg_get_vars (model);
586 n_vals = linreg_n_coeffs (model);
587
588 vals = xnmalloc (n_vals, sizeof (*vals));
589 *c = case_unshare (*c);
590 output = case_data_rw (*c, model->resid);
591 assert (output != NULL);
592
593 for (i = 0; i < n_vals; i++)
594 {
595 tmp = case_data (*c, vars[i]);
596 vals[i] = tmp->f;
597 }
598 tmp = case_data (*c, model->depvar);
599 obs = tmp->f;
600 output->f = linreg_residual (model, obs, vals, n_vals);
601 free (vals);
602
603 return TRNS_CONTINUE;
604 }
605
606 static char *
607 reg_get_name (const struct dictionary *dict, const char *prefix)
608 {
609 char *name;
610 int i;
611
612 /* XXX handle too-long prefixes */
613 name = xmalloc (strlen (prefix) + INT_BUFSIZE_BOUND (i) + 1);
614 for (i = 1; ; i++)
615 {
616 sprintf (name, "%s%d", prefix, i);
617 if (dict_lookup_var (dict, name) == NULL)
618 return name;
619 }
620 }
621
622 static void
623 reg_save_var (struct dataset *ds, const char *prefix, trns_proc_func * f,
624 linreg * c, struct variable **v, int n_trns)
625 {
626 struct dictionary *dict = dataset_dict (ds);
627 static int trns_index = 1;
628 char *name;
629 struct variable *new_var;
630 struct reg_trns *t = NULL;
631
632 t = xmalloc (sizeof (*t));
633 t->trns_id = trns_index;
634 t->n_trns = n_trns;
635 t->c = c;
636
637 name = reg_get_name (dict, prefix);
638 new_var = dict_create_var_assert (dict, name, 0);
639 free (name);
640
641 *v = new_var;
642 add_transformation (ds, f, regression_trns_free, t);
643 trns_index++;
644 }
645 static void
646 subcommand_save (struct dataset *ds, int save, linreg ** models)
647 {
648 linreg **lc;
649 int n_trns = 0;
650 int i;
651
652 if (save)
653 {
654 /* Count the number of transformations we will need. */
655 for (i = 0; i < REGRESSION_SV_count; i++)
656 {
657 if (cmd.a_save[i])
658 {
659 n_trns++;
660 }
661 }
662 n_trns *= cmd.n_dependent;
663
664 for (lc = models; lc < models + cmd.n_dependent; lc++)
665 {
666 if (*lc != NULL)
667 {
668 if ((*lc)->depvar != NULL)
669 {
670 if (cmd.a_save[REGRESSION_SV_RESID])
671 {
672 reg_save_var (ds, "RES", regression_trns_resid_proc, *lc,
673 &(*lc)->resid, n_trns);
674 }
675 if (cmd.a_save[REGRESSION_SV_PRED])
676 {
677 reg_save_var (ds, "PRED", regression_trns_pred_proc, *lc,
678 &(*lc)->pred, n_trns);
679 }
680 }
681 }
682 }
683 }
684 else
685 {
686 for (lc = models; lc < models + cmd.n_dependent; lc++)
687 {
688 if (*lc != NULL)
689 {
690 linreg_free (*lc);
691 }
692 }
693 }
694 }
695
696 int
697 cmd_regression (struct lexer *lexer, struct dataset *ds)
698 {
699 struct casegrouper *grouper;
700 struct casereader *group;
701 linreg **models;
702 bool ok;
703 size_t i;
704
705 if (!parse_regression (lexer, ds, &cmd, NULL))
706 {
707 return CMD_FAILURE;
708 }
709
710 models = xnmalloc (cmd.n_dependent, sizeof *models);
711 for (i = 0; i < cmd.n_dependent; i++)
712 {
713 models[i] = NULL;
714 }
715
716 /* Data pass. */
717 grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
718 while (casegrouper_get_next_group (grouper, &group))
719 run_regression (group, &cmd, ds, models);
720 ok = casegrouper_destroy (grouper);
721 ok = proc_commit (ds) && ok;
722
723 subcommand_save (ds, cmd.sbc_save, models);
724 free (v_variables);
725 free (models);
726 free_regression (&cmd);
727
728 return ok ? CMD_SUCCESS : CMD_FAILURE;
729 }
730
731 /*
732 Is variable k the dependent variable?
733 */
734 static bool
735 is_depvar (size_t k, const struct variable *v)
736 {
737 return v == v_variables[k];
738 }
739
740 /* Parser for the variables sub command */
741 static int
742 regression_custom_variables (struct lexer *lexer, struct dataset *ds,
743 struct cmd_regression *cmd UNUSED,
744 void *aux UNUSED)
745 {
746 const struct dictionary *dict = dataset_dict (ds);
747
748 lex_match (lexer, T_EQUALS);
749
750 if ((lex_token (lexer) != T_ID
751 || dict_lookup_var (dict, lex_tokcstr (lexer)) == NULL)
752 && lex_token (lexer) != T_ALL)
753 return 2;
754
755
756 if (!parse_variables_const
757 (lexer, dict, &v_variables, &n_variables, PV_NONE))
758 {
759 free (v_variables);
760 return 0;
761 }
762 assert (n_variables);
763
764 return 1;
765 }
766
767 /* Identify the explanatory variables in v_variables. Returns
768 the number of independent variables. */
769 static int
770 identify_indep_vars (const struct variable **indep_vars,
771 const struct variable *depvar)
772 {
773 int n_indep_vars = 0;
774 int i;
775
776 for (i = 0; i < n_variables; i++)
777 if (!is_depvar (i, depvar))
778 indep_vars[n_indep_vars++] = v_variables[i];
779 if ((n_indep_vars < 1) && is_depvar (0, depvar))
780 {
781 /*
782 There is only one independent variable, and it is the same
783 as the dependent variable. Print a warning and continue.
784 */
785 msg (SE,
786 gettext ("The dependent variable is equal to the independent variable."
787 "The least squares line is therefore Y=X."
788 "Standard errors and related statistics may be meaningless."));
789 n_indep_vars = 1;
790 indep_vars[0] = v_variables[0];
791 }
792 return n_indep_vars;
793 }
794
795 static double
796 fill_covariance (gsl_matrix *cov, struct covariance *all_cov,
797 const struct variable **vars,
798 size_t n_vars, const struct variable *dep_var,
799 const struct variable **all_vars, size_t n_all_vars,
800 double *means)
801 {
802 size_t i;
803 size_t j;
804 size_t dep_subscript;
805 size_t *rows;
806 const gsl_matrix *ssizes;
807 const gsl_matrix *mean_matrix;
808 const gsl_matrix *ssize_matrix;
809 double result = 0.0;
810
811 gsl_matrix *cm = covariance_calculate_unnormalized (all_cov);
812
813 if ( cm == NULL)
814 return 0;
815
816 rows = xnmalloc (cov->size1 - 1, sizeof (*rows));
817
818 for (i = 0; i < n_all_vars; i++)
819 {
820 for (j = 0; j < n_vars; j++)
821 {
822 if (vars[j] == all_vars[i])
823 {
824 rows[j] = i;
825 }
826 }
827 if (all_vars[i] == dep_var)
828 {
829 dep_subscript = i;
830 }
831 }
832 mean_matrix = covariance_moments (all_cov, MOMENT_MEAN);
833 ssize_matrix = covariance_moments (all_cov, MOMENT_NONE);
834 for (i = 0; i < cov->size1 - 1; i++)
835 {
836 means[i] = gsl_matrix_get (mean_matrix, rows[i], 0)
837 / gsl_matrix_get (ssize_matrix, rows[i], 0);
838 for (j = 0; j < cov->size2 - 1; j++)
839 {
840 gsl_matrix_set (cov, i, j, gsl_matrix_get (cm, rows[i], rows[j]));
841 gsl_matrix_set (cov, j, i, gsl_matrix_get (cm, rows[j], rows[i]));
842 }
843 }
844 means[cov->size1 - 1] = gsl_matrix_get (mean_matrix, dep_subscript, 0)
845 / gsl_matrix_get (ssize_matrix, dep_subscript, 0);
846 ssizes = covariance_moments (all_cov, MOMENT_NONE);
847 result = gsl_matrix_get (ssizes, dep_subscript, rows[0]);
848 for (i = 0; i < cov->size1 - 1; i++)
849 {
850 gsl_matrix_set (cov, i, cov->size1 - 1,
851 gsl_matrix_get (cm, rows[i], dep_subscript));
852 gsl_matrix_set (cov, cov->size1 - 1, i,
853 gsl_matrix_get (cm, rows[i], dep_subscript));
854 if (result > gsl_matrix_get (ssizes, rows[i], dep_subscript))
855 {
856 result = gsl_matrix_get (ssizes, rows[i], dep_subscript);
857 }
858 }
859 gsl_matrix_set (cov, cov->size1 - 1, cov->size1 - 1,
860 gsl_matrix_get (cm, dep_subscript, dep_subscript));
861 free (rows);
862 gsl_matrix_free (cm);
863 return result;
864 }
865 static size_t
866 get_n_all_vars (struct cmd_regression *cmd)
867 {
868 size_t result = n_variables;
869 size_t i;
870 size_t j;
871
872 result += cmd->n_dependent;
873 for (i = 0; i < cmd->n_dependent; i++)
874 {
875 for (j = 0; j < n_variables; j++)
876 {
877 if (v_variables[j] == cmd->v_dependent[i])
878 {
879 result--;
880 }
881 }
882 }
883 return result;
884 }
885 static void
886 fill_all_vars (const struct variable **vars, struct cmd_regression *cmd)
887 {
888 size_t i;
889 size_t j;
890 bool absent;
891
892 for (i = 0; i < n_variables; i++)
893 {
894 vars[i] = v_variables[i];
895 }
896 for (i = 0; i < cmd->n_dependent; i++)
897 {
898 absent = true;
899 for (j = 0; j < n_variables; j++)
900 {
901 if (cmd->v_dependent[i] == v_variables[j])
902 {
903 absent = false;
904 break;
905 }
906 }
907 if (absent)
908 {
909 vars[i + n_variables] = cmd->v_dependent[i];
910 }
911 }
912 }
913 static bool
914 run_regression (struct casereader *input, struct cmd_regression *cmd,
915 struct dataset *ds, linreg **models)
916 {
917 size_t i;
918 int n_indep = 0;
919 int k;
920 double n_data;
921 double *means;
922 struct ccase *c;
923 struct covariance *cov;
924 const struct variable **vars;
925 const struct variable **all_vars;
926 const struct variable *dep_var;
927 struct casereader *reader;
928 const struct dictionary *dict;
929 size_t n_all_vars;
930
931 assert (models != NULL);
932
933 for (i = 0; i < n_variables; i++)
934 {
935 if (!var_is_numeric (v_variables[i]))
936 {
937 msg (SE, _("REGRESSION requires numeric variables."));
938 return false;
939 }
940 }
941
942 c = casereader_peek (input, 0);
943 if (c == NULL)
944 {
945 casereader_destroy (input);
946 return true;
947 }
948 output_split_file_values (ds, c);
949 case_unref (c);
950
951 dict = dataset_dict (ds);
952 if (!v_variables)
953 {
954 dict_get_vars (dict, &v_variables, &n_variables, 0);
955 }
956 n_all_vars = get_n_all_vars (cmd);
957 all_vars = xnmalloc (n_all_vars, sizeof (*all_vars));
958 fill_all_vars (all_vars, cmd);
959 vars = xnmalloc (n_variables, sizeof (*vars));
960 means = xnmalloc (n_all_vars, sizeof (*means));
961 cov = covariance_1pass_create (n_all_vars, all_vars,
962 dict_get_weight (dict), MV_ANY);
963
964 reader = casereader_clone (input);
965 reader = casereader_create_filter_missing (reader, all_vars, n_all_vars,
966 MV_ANY, NULL, NULL);
967
968
969 for (; (c = casereader_read (reader)) != NULL; case_unref (c))
970 {
971 covariance_accumulate (cov, c);
972 }
973
974 for (k = 0; k < cmd->n_dependent; k++)
975 {
976 gsl_matrix *this_cm;
977 dep_var = cmd->v_dependent[k];
978 n_indep = identify_indep_vars (vars, dep_var);
979
980 this_cm = gsl_matrix_alloc (n_indep + 1, n_indep + 1);
981 n_data = fill_covariance (this_cm, cov, vars, n_indep,
982 dep_var, all_vars, n_all_vars, means);
983 models[k] = linreg_alloc (dep_var, (const struct variable **) vars,
984 n_data, n_indep);
985 models[k]->depvar = dep_var;
986 for (i = 0; i < n_indep; i++)
987 {
988 linreg_set_indep_variable_mean (models[k], i, means[i]);
989 }
990 linreg_set_depvar_mean (models[k], means[i]);
991 /*
992 For large data sets, use QR decomposition.
993 */
994 if (n_data > sqrt (n_indep) && n_data > REG_LARGE_DATA)
995 {
996 models[k]->method = LINREG_QR;
997 }
998
999 if (n_data > 0)
1000 {
1001 /*
1002 Find the least-squares estimates and other statistics.
1003 */
1004 linreg_fit (this_cm, models[k]);
1005
1006 if (!taint_has_tainted_successor (casereader_get_taint (input)))
1007 {
1008 subcommand_statistics (cmd->a_statistics, models[k], this_cm);
1009 }
1010 }
1011 else
1012 {
1013 msg (SE,
1014 gettext ("No valid data found. This command was skipped."));
1015 linreg_free (models[k]);
1016 models[k] = NULL;
1017 }
1018 gsl_matrix_free (this_cm);
1019 }
1020
1021 casereader_destroy (reader);
1022 free (vars);
1023 free (all_vars);
1024 free (means);
1025 casereader_destroy (input);
1026 covariance_destroy (cov);
1027
1028 return true;
1029 }
1030
1031 /*
1032 Local Variables:
1033 mode: c
1034 End:
1035 */
2121 #include <time.h>
2222 #include <unistd.h>
2323
24 #include "gl/vasnprintf.h"
25
26 #include "data/casereader.h"
2427 #include "data/data-in.h"
2528 #include "data/data-out.h"
2629 #include "data/dataset.h"
104107 scripttab=string;
105108 seed=custom;
106109 tnumbers=custom;
110 tvars=custom;
107111 tb1=string;
108112 tbfonts=string;
109113 undefined=undef:warn/nowarn;
353357 }
354358
355359
360 static int
361 stc_custom_tvars (struct lexer *lexer,
362 struct dataset *ds UNUSED,
363 struct cmd_set *cmd UNUSED, void *aux UNUSED)
364 {
365 lex_match (lexer, T_EQUALS);
366
367 if (lex_match_id (lexer, "NAMES"))
368 {
369 settings_set_var_style (SETTINGS_VAR_STYLE_NAMES);
370 }
371 else if (lex_match_id (lexer, "LABELS"))
372 {
373 settings_set_var_style (SETTINGS_VAR_STYLE_LABELS);
374 }
375 else if (lex_match_id (lexer, "BOTH"))
376 {
377 settings_set_var_style (SETTINGS_VAR_STYLE_BOTH);
378 }
379 else
380 {
381 lex_error_expecting (lexer, "NAMES", "LABELS", "BOTH", NULL_SENTINEL);
382 return 0;
383 }
384
385 return 1;
386 }
387
388
356389 /* Parses the EPOCH subcommand, which controls the epoch used for
357390 parsing 2-digit years. */
358391 static int
864897 {
865898 return strdup (host_system);
866899 }
900
901 static char *
902 show_n (const struct dataset *ds)
903 {
904 casenumber n;
905 size_t l;
906
907 const struct casereader *reader = dataset_source (ds);
908
909 if (reader == NULL)
910 return strdup (_("Unknown"));
911
912 n = casereader_count_cases (reader);
913
914 return asnprintf (NULL, &l, "%ld", n);
915 }
916
867917
868918 struct show_sbc
869919 {
890940 {"MXERRS", show_mxerrs},
891941 {"MXLOOPS", show_mxloops},
892942 {"MXWARNS", show_mxwarns},
943 {"N", show_n},
893944 {"PRINTBACk", show_printback},
894945 {"RESULTS", show_results},
895946 {"RIB", show_rib},
350350 abt_reaugmented (const struct abt *abt, struct abt_node *p)
351351 {
352352 for (; p != NULL; p = p->up)
353 abt->reaugment (p, p->down[0], p->down[1], abt->aux);
353 abt->reaugment (p, abt->aux);
354354 }
355355
356356 /* Moves P around in ABT to compensate for its key having
451451 b->up = a->up;
452452 a->up = b;
453453
454 abt->reaugment (a, a->down[0], a->down[1], abt->aux);
455 abt->reaugment (b, b->down[0], b->down[1], abt->aux);
454 abt->reaugment (a, abt->aux);
455 abt->reaugment (b, abt->aux);
456456
457457 return b;
458458 }
482482
483483 b->level++;
484484
485 abt->reaugment (a, a->down[0], a->down[1], abt->aux);
486 abt->reaugment (b, b->down[0], b->down[1], abt->aux);
485 abt->reaugment (a, abt->aux);
486 abt->reaugment (b, abt->aux);
487487
488488 return b;
489489 }
3333
3434 The ABT data structure partially abstracts augmentation. The
3535 client passes in a "reaugmentation" function that accepts a
36 node and its left and right children. This function must
37 recalculate the node's augmentation data based on its own
38 contents and the contents of its children, and store the new
39 augmentation data in the node.
36 node. This function must recalculate the node's augmentation
37 data based on its own contents and the contents of its
38 children, and store the new augmentation data in the node.
4039
4140 The ABT automatically calls the reaugmentation function
4241 whenever it can tell that a node's augmentation data might
103102 }
104103
105104 // Recalculates the count for NODE's subtree by adding up the
106 // counts for its LEFT and RIGHT child subtrees.
105 // counts for its left and right child subtrees.
107106 static void
108 reaugment_elements (struct abt_node *node_,
109 const struct abt_node *left,
110 const struct abt_node *right,
111 const void *aux)
107 reaugment_elements (struct abt_node *node_, const void *aux)
112108 {
113109 struct element *node = node_to_element (node_);
114110 node->count = 1;
115 if (left != NULL)
116 node->count += node_to_element (left)->count;
117 if (right != NULL)
118 node->count += node_to_element (right)->count;
111 if (node->node.down[0] != NULL)
112 node->count += node_to_element (node->node.down[0])->count;
113 if (node->node.down[1] != NULL)
114 node->count += node_to_element (node->node.down[1])->count;
119115 }
120116
121117 // Finds and returns the element in ABT that is in the given
148144 code and links to other resources, such as the original AA
149145 tree paper. */
150146
147 #include <stdbool.h>
151148 #include <stddef.h>
152149 #include "libpspp/cast.h"
153150
172169 const struct abt_node *b,
173170 const void *aux);
174171
175 /* Recalculates NODE's augmentation based on NODE's data and that
176 of its LEFT and RIGHT children, with the tree's AUX. */
177 typedef void abt_reaugment_func (struct abt_node *node,
178 const struct abt_node *left,
179 const struct abt_node *right,
180 const void *aux);
172 /* Recalculates NODE's augmentation based on NODE's data and that of its left
173 and right children NODE->down[0] and NODE[1], respectively, with the tree's
174 AUX. */
175 typedef void abt_reaugment_func (struct abt_node *node, const void *aux);
181176
182177 /* An augmented binary tree. */
183178 struct abt
191186 void abt_init (struct abt *, abt_compare_func *, abt_reaugment_func *,
192187 const void *aux);
193188
189 static inline bool abt_is_empty (const struct abt *);
190
194191 struct abt_node *abt_insert (struct abt *, struct abt_node *);
195192 void abt_insert_after (struct abt *,
196193 const struct abt_node *, struct abt_node *);
208205 struct abt_node *abt_changed (struct abt *, struct abt_node *);
209206 void abt_moved (struct abt *, struct abt_node *);
210207
208 /* Returns true if ABT contains no nodes, false if ABT contains at least one
209 node. */
210 static inline bool
211 abt_is_empty (const struct abt *abt)
212 {
213 return abt->root == NULL;
214 }
215
211216 #endif /* libpspp/abt.h */
4343 src/libpspp/integer-format.h \
4444 src/libpspp/intern.c \
4545 src/libpspp/intern.h \
46 src/libpspp/line-reader.c \
47 src/libpspp/line-reader.h \
4648 src/libpspp/ll.c \
4749 src/libpspp/ll.h \
4850 src/libpspp/llx.c \
6163 src/libpspp/range-map.h \
6264 src/libpspp/range-set.c \
6365 src/libpspp/range-set.h \
66 src/libpspp/range-tower.c \
67 src/libpspp/range-tower.h \
6468 src/libpspp/sparse-array.c \
6569 src/libpspp/sparse-array.h \
6670 src/libpspp/sparse-xarray.c \
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
3535 #include "gettext.h"
3636 #define _(msgid) gettext (msgid)
3737
38 enum op
39 {
40 OP_WRITE, /* writing */
41 OP_READ /* reading */
42 };
43
3844 struct ext_array
3945 {
4046 FILE *file; /* Underlying file. */
4450 the stream buffer, making the common case of sequential
4551 access to cases unreasonably slow. */
4652 off_t position;
53
54 /* The most recent operation performed */
55 enum op op;
4756 };
4857
4958 /* Creates and returns a new external array. */
5564 if (ea->file == NULL)
5665 error (0, errno, _("failed to create temporary file"));
5766 ea->position = 0;
67 ea->op = OP_WRITE;
5868 return ea;
5969 }
6070
7989 Returns true if the seek is successful and EA is not
8090 otherwise tainted, false otherwise. */
8191 static bool
82 do_seek (const struct ext_array *ea_, off_t offset)
92 do_seek (const struct ext_array *ea_, off_t offset, enum op op)
8393 {
8494 struct ext_array *ea = CONST_CAST (struct ext_array *, ea_);
85
8695 if (!ext_array_error (ea))
8796 {
88 if (ea->position == offset)
97 if (ea->position == offset && ea->op == op)
8998 return true;
9099 else if (fseeko (ea->file, offset, SEEK_SET) == 0)
91100 {
120129 return false;
121130 }
122131 ea->position += bytes;
132 ea->op = OP_READ;
123133 return true;
124134 }
125135
137147 return false;
138148 }
139149 ea->position += bytes;
150 ea->op = OP_WRITE;
140151 return true;
141152 }
142153
145156 bool
146157 ext_array_read (const struct ext_array *ea, off_t offset, size_t n, void *data)
147158 {
148 return do_seek (ea, offset) && do_read (ea, data, n);
159 return do_seek (ea, offset, OP_READ) && do_read (ea, data, n);
149160 }
161
150162
151163 /* Writes the N bytes in DATA to EA at byte offset OFFSET.
152164 Returns true if successful, false on failure. */
154166 ext_array_write (struct ext_array *ea, off_t offset, size_t n,
155167 const void *data)
156168 {
157 return do_seek (ea, offset) && do_write (ea, data, n);
169 return do_seek (ea, offset, OP_WRITE) && do_write (ea, data, n);
158170 }
159171
160172 /* Returns true if an error has occurred in I/O on EA,
2929 #include <unigbrk.h>
3030
3131 #include "libpspp/assertion.h"
32 #include "libpspp/compiler.h"
3233 #include "libpspp/hmapx.h"
3334 #include "libpspp/hash-functions.h"
3435 #include "libpspp/pool.h"
4041 #include "gl/xalloc.h"
4142 #include "gl/relocatable.h"
4243 #include "gl/xstrndup.h"
44
45 #include "gettext.h"
46 #define _(msgid) gettext (msgid)
4347
4448 struct converter
4549 {
541545 i18n_init (void)
542546 {
543547 setlocale (LC_CTYPE, "");
548 setlocale (LC_COLLATE, "");
544549 setlocale (LC_MESSAGES, "");
545550 #if HAVE_LC_PAPER
546551 setlocale (LC_PAPER, "");
782787 && ((e[3] == '8' && e[4] == '\0')
783788 || (e[3] == '-' && e[4] == '8' && e[5] == '\0')));
784789 }
790
791 static struct encoding_category *categories;
792 static int n_categories;
793
794 static void SENTINEL (0)
795 add_category (size_t *allocated_categories, const char *category, ...)
796 {
797 struct encoding_category *c;
798 const char *encodings[16];
799 va_list args;
800 int i, n;
801
802 /* Count encoding arguments. */
803 va_start (args, category);
804 n = 0;
805 while ((encodings[n] = va_arg (args, const char *)) != NULL)
806 {
807 const char *encoding = encodings[n];
808 if (!strcmp (encoding, "Auto") || is_encoding_supported (encoding))
809 n++;
810 }
811 assert (n < sizeof encodings / sizeof *encodings);
812 va_end (args);
813
814 if (n == 0)
815 return;
816
817 if (n_categories >= *allocated_categories)
818 categories = x2nrealloc (categories,
819 allocated_categories, sizeof *categories);
820
821 c = &categories[n_categories++];
822 c->category = category;
823 c->encodings = xmalloc (n * sizeof *c->encodings);
824 for (i = 0; i < n; i++)
825 c->encodings[i] = encodings[i];
826 c->n_encodings = n;
827 }
828
829 static void
830 init_encoding_categories (void)
831 {
832 static bool inited;
833 size_t alloc;
834
835 if (inited)
836 return;
837 inited = true;
838
839 alloc = 0;
840 add_category (&alloc, "Unicode", "UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE",
841 "UTF-32", "UTF-32BE", "UTF-32LE", NULL_SENTINEL);
842 add_category (&alloc, _("Arabic"), "IBM864", "ISO-8859-6", "Windows-1256",
843 NULL_SENTINEL);
844 add_category (&alloc, _("Armenian"), "ARMSCII-8", NULL_SENTINEL);
845 add_category (&alloc, _("Baltic"), "ISO-8859-13", "ISO-8859-4",
846 "Windows-1257", NULL_SENTINEL);
847 add_category (&alloc, _("Celtic"), "ISO-8859-14", NULL_SENTINEL);
848 add_category (&alloc, _("Central European"), "IBM852", "ISO-8859-2",
849 "Mac-CentralEurope", "Windows-1250", NULL_SENTINEL);
850 add_category (&alloc, _("Chinese Simplified"), "GB18030", "GB2312", "GBK",
851 "HZ-GB-2312", "ISO-2022-CN", NULL_SENTINEL);
852 add_category (&alloc, _("Chinese Traditional"), "Big5", "Big5-HKSCS",
853 "EUC-TW", NULL_SENTINEL);
854 add_category (&alloc, _("Croatian"), "MacCroatian", NULL_SENTINEL);
855 add_category (&alloc, _("Cyrillic"), "IBM855", "ISO-8859-5", "ISO-IR-111",
856 "KOI8-R", "MacCyrillic", NULL_SENTINEL);
857 add_category (&alloc, _("Cyrillic/Russian"), "IBM866", NULL_SENTINEL);
858 add_category (&alloc, _("Cyrillic/Ukrainian"), "KOI8-U", "MacUkrainian",
859 NULL_SENTINEL);
860 add_category (&alloc, _("Georgian"), "GEOSTD8", NULL_SENTINEL);
861 add_category (&alloc, _("Greek"), "ISO-8859-7", "MacGreek", NULL_SENTINEL);
862 add_category (&alloc, _("Gujarati"), "MacGujarati", NULL_SENTINEL);
863 add_category (&alloc, _("Gurmukhi"), "MacGurmukhi", NULL_SENTINEL);
864 add_category (&alloc, _("Hebrew"), "IBM862", "ISO-8859-8-I", "Windows-1255",
865 NULL_SENTINEL);
866 add_category (&alloc, _("Hebrew Visual"), "ISO-8859-8", NULL_SENTINEL);
867 add_category (&alloc, _("Hindi"), "MacDevangari", NULL_SENTINEL);
868 add_category (&alloc, _("Icelandic"), "MacIcelandic", NULL_SENTINEL);
869 add_category (&alloc, _("Japanese"), "EUC-JP", "ISO-2022-JP", "Shift_JIS",
870 NULL_SENTINEL);
871 add_category (&alloc, _("Korean"), "EUC-KR", "ISO-2022-KR", "JOHAB", "UHC",
872 NULL_SENTINEL);
873 add_category (&alloc, _("Nordic"), "ISO-8859-10", NULL_SENTINEL);
874 add_category (&alloc, _("Romanian"), "ISO-8859-16", "MacRomanian",
875 NULL_SENTINEL);
876 add_category (&alloc, _("South European"), "ISO-8859-3", NULL_SENTINEL);
877 add_category (&alloc, _("Thai"), "ISO-8859-11", "TIS-620", "Windows-874",
878 NULL_SENTINEL);
879 add_category (&alloc, _("Turkish"), "IBM857", "ISO-8859-9", "Windows-1254",
880 NULL_SENTINEL);
881 add_category (&alloc, _("Vietnamese"), "TVCN", "VISCII", "VPS",
882 "Windows-1258", NULL_SENTINEL);
883 add_category (&alloc, _("Western European"), "ISO-8859-1", "ISO-8859-15",
884 "Windows-1252", "IBM850", "MacRoman", NULL_SENTINEL);
885 }
886
887 /* Returns an array of "struct encoding_category" that contains only the
888 categories and encodings that the system supports. */
889 struct encoding_category *
890 get_encoding_categories (void)
891 {
892 init_encoding_categories ();
893 return categories;
894 }
895
896 /* Returns the number of elements in the array returned by
897 get_encoding_categories(). */
898 size_t
899 get_n_encoding_categories (void)
900 {
901 init_encoding_categories ();
902 return n_categories;
903 }
142142 bool is_encoding_supported (const char *encoding);
143143
144144 bool is_encoding_utf8 (const char *encoding);
145
146 /* Database of encodings, by language or region. */
147
148 struct encoding_category
149 {
150 const char *category; /* e.g. "Arabic" or "Western European". */
151 const char **encodings; /* Encodings within the category. */
152 size_t n_encodings; /* Number of encodings in category. */
153 };
154
155 struct encoding_category *get_encoding_categories (void);
156 size_t get_n_encoding_categories (void);
145157
146158 #endif /* i18n.h */
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2010, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "line-reader.h"
19
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "libpspp/assertion.h"
28 #include "libpspp/encoding-guesser.h"
29 #include "libpspp/i18n.h"
30 #include "libpspp/str.h"
31
32 #include "gl/minmax.h"
33 #include "gl/xalloc.h"
34
35 enum line_reader_state
36 {
37 S_UNIBYTE, /* Known stream encoding, 1-byte unit. */
38 S_MULTIBYTE, /* Known stream encoding, multibyte unit. */
39 S_AUTO /* Encoding autodetection in progress. */
40 };
41
42 struct line_reader
43 {
44 int fd;
45 enum line_reader_state state;
46 struct encoding_info encoding_info;
47
48 char *encoding; /* Current encoding. */
49 char *auto_encoding; /* In S_AUTO mode, user-specified encoding. */
50
51 char *buffer;
52 char *head;
53 size_t length;
54
55 int error;
56 bool eof;
57 };
58
59 static ssize_t fill_buffer (struct line_reader *);
60
61 /* Opens FILENAME, which is encoded in ENCODING, for reading line by line,
62 passing FLAGS to the open() function. Returns a new line_reader if
63 successful, otherwise returns NULL and sets errno to an appropriate value.
64
65 The accepted forms for ENCODING are listed at the top of
66 encoding-guesser.h. */
67 struct line_reader *
68 line_reader_for_file (const char *encoding, const char *filename, int flags)
69 {
70 struct line_reader *r;
71 int fd;
72
73 assert (!(flags & O_CREAT));
74
75 fd = open (filename, flags);
76 if (fd < 0)
77 return NULL;
78
79 r = line_reader_for_fd (encoding, fd);
80 if (r == NULL)
81 {
82 int save_errno = errno;
83 close (fd);
84 errno = save_errno;
85 }
86
87 return r;
88 }
89
90 /* Creates and returns a new line_reader that reads its input from FD. Returns
91 a new line_reader if successful, otherwise returns NULL and sets errno to an
92 appropriate value.
93
94 The accepted forms for ENCODING are listed at the top of
95 encoding-guesser.h. */
96 struct line_reader *
97 line_reader_for_fd (const char *encoding, int fd)
98 {
99 struct line_reader *r;
100
101 r = calloc (1, sizeof *r);
102 if (r == NULL)
103 return NULL;
104
105 r->fd = fd;
106 r->buffer = malloc (LINE_READER_BUFFER_SIZE);
107 if (r->buffer == NULL)
108 goto error;
109 r->head = r->buffer;
110 r->length = 0;
111
112 if (fill_buffer (r) < 0)
113 goto error;
114
115 r->encoding = xstrdup (encoding_guess_head_encoding (
116 encoding, r->buffer, r->length));
117 if (!get_encoding_info (&r->encoding_info, r->encoding))
118 {
119 errno = EINVAL;
120 goto error;
121 }
122
123 if (encoding_guess_encoding_is_auto (encoding)
124 && !strcmp (r->encoding, "ASCII"))
125 {
126 r->state = S_AUTO;
127 r->auto_encoding = xstrdup (encoding);
128 }
129 else
130 r->state = r->encoding_info.unit == 1 ? S_UNIBYTE : S_MULTIBYTE;
131
132 return r;
133
134 error:
135 line_reader_free (r);
136 return NULL;
137 }
138
139 /* Closes R and its underlying file descriptor and frees all associated
140 resources. Returns the return value from close(). */
141 int
142 line_reader_close (struct line_reader *r)
143 {
144 if (r != NULL)
145 {
146 int fd = r->fd;
147 line_reader_free (r);
148 return close (fd);
149 }
150 return 0;
151 }
152
153 /* Frees R and associated resources, but does not close the underlying file
154 descriptor. (Thus, the client must close the file descriptor when it is no
155 longer needed.) */
156 void
157 line_reader_free (struct line_reader *r)
158 {
159 if (r != NULL)
160 {
161 free (r->buffer);
162 free (r->encoding);
163 free (r->auto_encoding);
164 free (r);
165 }
166 }
167
168 static ssize_t
169 fill_buffer (struct line_reader *r)
170 {
171 ssize_t n;
172
173 /* Move any unused bytes to the beginning of the input buffer. */
174 if (r->length > 0 && r->buffer != r->head)
175 memmove (r->buffer, r->head, r->length);
176 r->head = r->buffer;
177
178 /* Read more input. */
179 do
180 {
181 n = read (r->fd, r->buffer + r->length,
182 LINE_READER_BUFFER_SIZE - r->length);
183 }
184 while (n < 0 && errno == EINTR);
185 if (n > 0)
186 r->length += n;
187 else if (n < 0)
188 r->error = errno;
189 else
190 r->eof = true;
191 return n;
192 }
193
194 static void
195 output_bytes (struct line_reader *r, struct string *s, size_t n)
196 {
197 ds_put_substring (s, ss_buffer (r->head, n));
198 r->head += n;
199 r->length -= n;
200 }
201
202 static void
203 output_line (struct line_reader *r, struct string *s, size_t n)
204 {
205 int unit = r->encoding_info.unit;
206
207 output_bytes (r, s, n);
208
209 r->head += unit;
210 r->length -= unit;
211
212 ds_chomp (s, ss_buffer (r->encoding_info.cr, unit));
213 }
214
215 /* Reads a line of text, but no more than MAX_LENGTH bytes, from R and appends
216 it to S, omitting the final new-line and the carriage return that
217 immediately precedes it, if one is present. The line is left in its
218 original encoding.
219
220 Returns true if anything was successfully read from the file. (If an empty
221 line was read, then nothing is appended to S.) Returns false if end of file
222 was reached or a read error occurred before any text could be read. */
223 bool
224 line_reader_read (struct line_reader *r, struct string *s, size_t max_length)
225 {
226 size_t original_length = ds_length (s);
227 int unit = r->encoding_info.unit;
228
229 do
230 {
231 size_t max_out = max_length - (ds_length (s) - original_length);
232 size_t max_in = r->length;
233 size_t max = MIN (max_in, max_out);
234 size_t n;
235 char *p;
236
237 if (max_out < unit)
238 break;
239
240 switch (r->state)
241 {
242 case S_UNIBYTE:
243 p = memchr (r->head, r->encoding_info.lf[0], max);
244 if (p != NULL)
245 {
246 output_line (r, s, p - r->head);
247 return true;
248 }
249 n = max;
250 break;
251
252 case S_MULTIBYTE:
253 for (n = 0; n + unit <= max; n += unit)
254 if (!memcmp (r->head + n, r->encoding_info.lf, unit))
255 {
256 output_line (r, s, n);
257 return true;
258 }
259 break;
260
261 case S_AUTO:
262 for (n = 0; n < max; n++)
263 if (!encoding_guess_is_ascii_text (r->head[n]))
264 {
265 char *encoding;
266
267 output_bytes (r, s, n);
268 fill_buffer (r);
269 r->state = S_UNIBYTE;
270
271 encoding = xstrdup (encoding_guess_tail_encoding (
272 r->auto_encoding, r->head, r->length));
273 free (r->encoding);
274 r->encoding = encoding;
275
276 free (r->auto_encoding);
277 r->auto_encoding = NULL;
278
279 n = 0;
280 break;
281 }
282 else if (r->head[n] == '\n')
283 {
284 output_line (r, s, n);
285 return true;
286 }
287 break;
288
289 default:
290 NOT_REACHED ();
291 }
292
293 output_bytes (r, s, n);
294 }
295 while (r->length >= unit || fill_buffer (r) > 0);
296
297 return ds_length (s) > original_length;
298 }
299
300 /* Returns the file descriptor underlying R. */
301 int
302 line_reader_fileno (const struct line_reader *r)
303 {
304 return r->fd;
305 }
306
307 /* Returns the offset in the file of the next byte to be read from R, or -1 on
308 error (e.g. if the file is not seekable). */
309 off_t
310 line_reader_tell (const struct line_reader *r)
311 {
312 off_t pos = lseek (r->fd, 0, SEEK_CUR);
313 if (pos >= 0)
314 pos = MAX (0, pos - r->length);
315 return pos;
316 }
317
318 /* Returns true if end of file has been encountered reading R. */
319 bool
320 line_reader_eof (const struct line_reader *r)
321 {
322 return r->eof && !r->length;
323 }
324
325 /* Returns an nonzero errno value if an error has been encountered reading
326 R, zero otherwise. */
327 int
328 line_reader_error (const struct line_reader *r)
329 {
330 return !r->length ? r->error : 0;
331 }
332
333 /* Returns the encoding of R. If line_reader_is_auto(R) returns true, the
334 encoding might change as more lines are read. */
335 const char *
336 line_reader_get_encoding (const struct line_reader *r)
337 {
338 return r->encoding;
339 }
340
341 /* Returns true if the encoding of the file being read by R is not yet
342 completely known. If this function returns true, then the encoding returned
343 by line_reader_get_encoding() might change as more lines are read (and after
344 the change, this function will return false). */
345 bool
346 line_reader_is_auto (const struct line_reader *r)
347 {
348 return r->state == S_AUTO;
349 }
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2010, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef LIBPSPP_LINE_READER_H
17 #define LIBPSPP_LINE_READER_H 1
18
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <sys/types.h>
22
23 /* line_reader.
24
25 Reads a text file in an arbitrary encoding one line at a time, with
26 optional automatic encoding detection.
27 */
28
29 #define LINE_READER_BUFFER_SIZE 4096
30
31 struct string;
32
33 struct line_reader *line_reader_for_fd (const char *encoding, int fd);
34 struct line_reader *line_reader_for_file (const char *encoding,
35 const char *filename, int flags);
36
37 int line_reader_close (struct line_reader *);
38 void line_reader_free (struct line_reader *);
39
40 bool line_reader_read (struct line_reader *, struct string *,
41 size_t max_length);
42
43 int line_reader_fileno (const struct line_reader *);
44 off_t line_reader_tell (const struct line_reader *);
45
46 bool line_reader_eof (const struct line_reader *);
47 int line_reader_error (const struct line_reader *);
48
49 const char *line_reader_get_encoding (const struct line_reader *);
50
51 bool line_reader_is_auto (const struct line_reader *);
52
53 #endif /* libpspp/line-reader.h */
105105 /* Inserts the region starting at START and extending for WIDTH
106106 into RS. */
107107 void
108 range_set_insert (struct range_set *rs,
109 unsigned long int start, unsigned long int width)
108 range_set_set1 (struct range_set *rs,
109 unsigned long int start, unsigned long int width)
110110 {
111111 unsigned long int end = start + width;
112112 struct range_set_node *node;
154154 /* Deletes the region starting at START and extending for WIDTH
155155 from RS. */
156156 void
157 range_set_delete (struct range_set *rs,
158 unsigned long int start, unsigned long int width)
157 range_set_set0 (struct range_set *rs,
158 unsigned long int start, unsigned long int width)
159159 {
160160 unsigned long int end = start + width;
161161 struct range_set_node *node;
5252 struct range_set *range_set_clone (const struct range_set *, struct pool *);
5353 void range_set_destroy (struct range_set *);
5454
55 void range_set_insert (struct range_set *,
56 unsigned long int start, unsigned long int width);
57 void range_set_delete (struct range_set *,
58 unsigned long int start, unsigned long int width);
55 void range_set_set1 (struct range_set *,
56 unsigned long int start, unsigned long int width);
57 void range_set_set0 (struct range_set *,
58 unsigned long int start, unsigned long int width);
5959 bool range_set_allocate (struct range_set *, unsigned long int request,
6060 unsigned long int *start, unsigned long int *width);
6161 bool range_set_allocate_fully (struct range_set *, unsigned long int request,
6565 unsigned long int start);
6666
6767 static inline bool range_set_is_empty (const struct range_set *);
68
69 #define RANGE_SET_FOR_EACH(NODE, RANGE_SET) \
70 for ((NODE) = range_set_first (RANGE_SET); \
71 (NODE) != NULL; \
72 (NODE) = range_set_next (RANGE_SET, NODE))
6873
6974 static inline const struct range_set_node *range_set_first (
7075 const struct range_set *);
103108
104109 /* Returns the node representing the first contiguous region of
105110 1-bits in RS, or a null pointer if RS is empty.
106 Any call to range_set_insert, range_set_delete, or
111 Any call to range_set_set1, range_set_set0, or
107112 range_set_allocate invalidates the returned node. */
108113 static inline const struct range_set_node *
109114 range_set_first (const struct range_set *rs)
116121 pointer if NODE is the last region in RS.
117122 If NODE is null, returns the first region in RS, as for
118123 range_set_first.
119 Any call to range_set_insert, range_set_delete, or
124 Any call to range_set_set1, range_set_set0, or
120125 range_set_allocate invalidates the returned node. */
121126 static inline const struct range_set_node *
122127 range_set_next (const struct range_set *rs, const struct range_set_node *node)
128133
129134 /* Returns the node representing the last contiguous region of
130135 1-bits in RS, or a null pointer if RS is empty.
131 Any call to range_set_insert, range_set_delete, or
136 Any call to range_set_set1, range_set_set0, or
132137 range_set_allocate invalidates the returned node. */
133138 static inline const struct range_set_node *
134139 range_set_last (const struct range_set *rs)
141146 pointer if NODE is the first region in RS.
142147 If NODE is null, returns the last region in RS, as for
143148 range_set_last.
144 Any call to range_set_insert, range_set_delete, or
149 Any call to range_set_set1, range_set_set0, or
145150 range_set_allocate invalidates the returned node. */
146151 static inline const struct range_set_node *
147152 range_set_prev (const struct range_set *rs, const struct range_set_node *node)
0 /* pspp - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* Bitmap, implemented as a balanced binary tree. */
17
18 /* If you add routines in this file, please add a corresponding
19 test to range-tower-test.c. This test program should achieve
20 100% coverage of lines and branches in this code, as reported
21 by "gcov -b". */
22
23 #include <config.h>
24
25 #include "libpspp/range-tower.h"
26
27 #include <limits.h>
28 #include <stdlib.h>
29
30 #include "libpspp/assertion.h"
31 #include "libpspp/compiler.h"
32 #include "libpspp/pool.h"
33
34 #include "gl/minmax.h"
35 #include "gl/xalloc.h"
36
37 static void reaugment_range_tower_node (struct abt_node *, const void *aux);
38 static void delete_node (struct range_tower *, struct range_tower_node *);
39
40 static void destroy_pool (void *);
41
42 static void
43 print_structure (const struct abt_node *node_)
44 {
45 struct range_tower_node *node;
46
47 if (node_ == NULL)
48 return;
49 node = abt_data (node_, struct range_tower_node, abt_node);
50 printf ("%lu+%lu/%d", node->n_zeros, node->n_ones, node->abt_node.level);
51 if (node->abt_node.down[0] || node->abt_node.down[1])
52 {
53 printf ("(");
54 print_structure (node->abt_node.down[0]);
55 printf (",");
56 print_structure (node->abt_node.down[1]);
57 printf (")");
58 }
59 }
60
61 /* Prints the regions in RT to stdout. */
62 static void UNUSED
63 print_regions (const char *title, const struct range_tower *rt)
64 {
65 const struct range_tower_node *node;
66
67 printf ("%s:", title);
68 for (node = range_tower_first__ (rt); node != NULL;
69 node = range_tower_next__ (rt, node))
70 printf (" (%lu,%lu)", node->n_zeros, node->n_ones);
71 printf ("\n");
72 printf ("structure:");
73 print_structure (rt->abt.root);
74 printf ("\n");
75 }
76
77 static struct range_tower_node *
78 range_tower_node_from_abt_node (const struct abt_node *abt_node)
79 {
80 return abt_data (abt_node, struct range_tower_node, abt_node);
81 }
82
83 /* Returns the total width (zeros and ones) of the nodes in the subtree rooted
84 at P, or 0 if P is null. */
85 static unsigned long int
86 subtree_width (const struct abt_node *p)
87 {
88 return p != NULL ? range_tower_node_from_abt_node (p)->subtree_width : 0;
89 }
90
91 /* Returns the position of the first 1-bit in NODE.
92
93 The performance of this function is O(lg n) in the number of nodes in the
94 range tower. It is often possible to avoid calling this function, either by
95 taking advantage of the NODE_START parameter to tower_lookup or by
96 incrementally keeping track of height while iterating through a tower. In
97 the former case the asymptotic performance is no different, since
98 tower_lookup is also O(lg n), but in the latter case performance improves
99 from O(lg n) to O(1). */
100 unsigned long int
101 range_tower_node_get_start (const struct range_tower_node *node)
102 {
103 const struct abt_node *p = &node->abt_node;
104 unsigned long start = subtree_width (p->down[0]) + range_tower_node_from_abt_node (p)->n_zeros;
105 while (p->up != NULL)
106 {
107 if (p == p->up->down[1])
108 {
109 const struct range_tower_node *up
110 = range_tower_node_from_abt_node (p->up);
111 start += subtree_width (p->up->down[0]) + up->n_zeros + up->n_ones;
112 }
113 p = p->up;
114 }
115 return start;
116 }
117
118 /* Returns one past the position of the last 1-bit in NODE.
119
120 Like range_tower_node_get_start(), the performance of this function is O(lg
121 n) in the number of nodes in the range tower. */
122 unsigned long int
123 range_tower_node_get_end (const struct range_tower_node *node)
124 {
125 return range_tower_node_get_start (node) + node->n_ones;
126 }
127
128 /* Creates and returns a new, empty range tower. */
129 struct range_tower *
130 range_tower_create (void)
131 {
132 return range_tower_create_pool (NULL);
133 }
134
135 static struct range_tower *
136 range_tower_create_pool__ (struct pool *pool)
137 {
138 struct range_tower *rt = xmalloc (sizeof *rt);
139
140 rt->pool = pool;
141 if (pool != NULL)
142 pool_register (pool, destroy_pool, rt);
143
144 abt_init (&rt->abt, NULL, reaugment_range_tower_node, NULL);
145 rt->cache_end = 0;
146
147 return rt;
148 }
149
150 /* Creates and returns a new, empty range tower in the given POOL. */
151 struct range_tower *
152 range_tower_create_pool (struct pool *pool)
153 {
154 struct range_tower_node *node;
155 struct range_tower *rt;
156
157 rt = range_tower_create_pool__ (pool);
158
159 node = xmalloc (sizeof *node);
160 node->n_zeros = ULONG_MAX;
161 node->n_ones = 0;
162 abt_insert_after (&rt->abt, NULL, &node->abt_node);
163
164 return rt;
165 }
166
167 /* Creates and returns a clone of OLD range tower in the given POOL
168 (which may be null). */
169 struct range_tower *
170 range_tower_clone (const struct range_tower *old, struct pool *pool)
171 {
172 const struct range_tower_node *old_node;
173 struct abt_node *prev_node;
174 struct range_tower *new;
175
176 new = range_tower_create_pool__ (pool);
177 prev_node = NULL;
178 for (old_node = range_tower_first__ (old); old_node != NULL;
179 old_node = range_tower_next__ (old, old_node))
180 {
181 struct range_tower_node *new_node;
182
183 new_node = xmalloc (sizeof *new_node);
184 new_node->n_zeros = old_node->n_zeros;
185 new_node->n_ones = old_node->n_ones;
186
187 abt_insert_after (&new->abt, prev_node, &new_node->abt_node);
188 prev_node = &new_node->abt_node;
189 }
190 return new;
191 }
192
193 /* Destroys range tower RT. */
194 void
195 range_tower_destroy (struct range_tower *rt)
196 {
197 if (rt != NULL)
198 {
199 if (rt->pool != NULL)
200 pool_unregister (rt->pool, rt);
201 while (!abt_is_empty (&rt->abt))
202 delete_node (rt, range_tower_first__ (rt));
203 free (rt);
204 }
205 }
206
207 /* Sets the WIDTH bits starting at START in RT to 1-bits. */
208 void
209 range_tower_set1 (struct range_tower *rt,
210 unsigned long int start, unsigned long int width)
211 {
212 struct range_tower_node *node;
213 unsigned long int node_start;
214
215 assert (width == 0 || start + width - 1 >= start);
216
217 node = range_tower_lookup (rt, start, &node_start);
218 while (width > 0)
219 {
220 unsigned long int node_ofs = start - node_start;
221
222 if (node_ofs >= node->n_zeros)
223 {
224 /* There are already some 1-bits here, so skip them. */
225 unsigned long ones_left = (node->n_zeros + node->n_ones) - node_ofs;
226 if (width <= ones_left)
227 return;
228
229 start += ones_left;
230 width -= ones_left;
231 node_start += node->n_zeros + node->n_ones;
232 node_ofs = 0;
233 node = range_tower_next__ (rt, node);
234 }
235
236 /* Invalidate cache. */
237 rt->cache_end = 0;
238
239 if (node_ofs == 0)
240 {
241 if (node_start > 0)
242 {
243 struct range_tower_node *prev = range_tower_prev__ (rt, node);
244 if (width >= node->n_zeros)
245 {
246 /* All zeros in NODE are replaced by ones. Change NODE's
247 entire width into PREV's trailing ones, e.g. 00001111
248 00001111 becomes 0000111111111111. */
249 int node_width = node->n_zeros + node->n_ones;
250 abt_delete (&rt->abt, &node->abt_node);
251 prev->n_ones += node_width;
252 abt_reaugmented (&rt->abt, &prev->abt_node);
253 if (width <= node_width)
254 return;
255
256 /* Go around again with NODE replaced by PREV's new
257 successor. */
258 width -= node_width;
259 start += node_width;
260 node = range_tower_next__ (rt, prev);
261 node_start += node_width;
262 }
263 else
264 {
265 /* Leading zeros in NODE change into trailing ones in PREV,
266 but trailing zeros in NODE remain, e.g. 00001111 00001111
267 becomes 0000111111 001111. */
268 node->n_zeros -= width;
269 abt_reaugmented (&rt->abt, &node->abt_node);
270
271 prev->n_ones += width;
272 abt_reaugmented (&rt->abt, &prev->abt_node);
273 return;
274 }
275 }
276 else
277 {
278 if (width >= node->n_zeros)
279 {
280 /* All zeros in NODE are replaced by ones, e.g. 00001111
281 becomes 11111111. */
282 node->n_ones += node->n_zeros;
283 node->n_zeros = 0;
284 if (width <= node->n_ones)
285 return;
286
287 start += node->n_ones;
288 node_start += node->n_ones;
289 width -= node->n_ones;
290 node = range_tower_next__ (rt, node);
291 }
292 else
293 {
294 /* Leading zeros in NODE (which starts at offset 0) are
295 replaced by ones, but some zeros remain. This requires a
296 node split, e.g. 00001111 becomes 11 001111. */
297 struct range_tower_node *new_node;
298
299 node->n_zeros -= width;
300 abt_reaugmented (&rt->abt, &node->abt_node);
301
302 new_node = xmalloc (sizeof *new_node);
303 new_node->n_zeros = 0;
304 new_node->n_ones = width;
305 abt_insert_before (&rt->abt, &node->abt_node,
306 &new_node->abt_node);
307 return;
308 }
309 }
310 }
311 else
312 {
313 unsigned long int zeros_left = node->n_zeros - node_ofs;
314 if (width >= zeros_left)
315 {
316 /* Trailing zeros in NODE are replaced by ones, but leading
317 zeros remain, e.g. 00001111 becomes 00111111. */
318 node->n_zeros -= zeros_left;
319 node->n_ones += zeros_left;
320 if (width <= node->n_ones)
321 return;
322 start += node->n_ones;
323 width -= node->n_ones;
324 node_start += node->n_zeros + node->n_ones;
325 node = range_tower_next__ (rt, node);
326 }
327 else
328 {
329 /* Zeros that are neither leading or trailing turn into ones.
330 Split the node into two nodes, e.g. 00001111 becomes 011
331 01111. */
332 struct range_tower_node *new_node;
333
334 new_node = xmalloc (sizeof *new_node);
335 new_node->n_ones = node->n_ones;
336 new_node->n_zeros = zeros_left - width;
337
338 node->n_zeros = node_ofs;
339 node->n_ones = width;
340 abt_reaugmented (&rt->abt, &node->abt_node);
341
342 abt_insert_after (&rt->abt, &node->abt_node,
343 &new_node->abt_node);
344 return;
345 }
346 }
347 }
348 }
349
350 /* Sets the WIDTH bits starting at START in RT to 0-bits. */
351 void
352 range_tower_set0 (struct range_tower *rt,
353 unsigned long int start, unsigned long int width)
354 {
355 struct range_tower_node *node;
356 unsigned long int node_start;
357
358 assert (width == 0 || start + width - 1 >= start);
359
360 node = range_tower_lookup (rt, start, &node_start);
361 while (width > 0)
362 {
363 unsigned long int node_ofs = start - node_start;
364
365 if (node_ofs < node->n_zeros)
366 {
367 /* Deleting zeros is a no-op, so skip them. */
368 unsigned long zeros_left = node->n_zeros - node_ofs;
369 if (zeros_left >= width)
370 {
371 /* We are deleting only existing zeros. Nothing to do. */
372 return;
373 }
374
375 width -= zeros_left;
376 start += zeros_left;
377 node_ofs = node->n_zeros;
378 }
379
380 rt->cache_end = 0;
381
382 if (node_ofs == node->n_zeros)
383 {
384 if (node->n_ones > width)
385 {
386 /* DELTA leading ones within NODE turn into zeros, but some ones
387 remain, e.g. 00001111 becomes 00111111. No reaugmentation
388 because n_zeros + n_ones doesn't change. */
389 node->n_zeros += width;
390 node->n_ones -= width;
391 return;
392 }
393 else
394 {
395 /* All ones in NODE turn into zeros, so merge NODE with the
396 following node, e.g. 00001111 00001111 becomes
397 0000000000001111, and then do it again with the merged
398 node. */
399 unsigned long int next_zeros, next_ones;
400 struct range_tower_node *next;
401
402 next = range_tower_next__ (rt, node);
403 if (next == NULL)
404 {
405 node->n_zeros += node->n_ones;
406 node->n_ones = 0;
407 return;
408 }
409
410 next_zeros = next->n_zeros;
411 next_ones = next->n_ones;
412 abt_delete (&rt->abt, &next->abt_node);
413
414 node->n_zeros += node->n_ones + next_zeros;
415 node->n_ones = next_ones;
416 abt_reaugmented (&rt->abt, &node->abt_node);
417 }
418 }
419 else if (node_ofs + width >= node->n_zeros + node->n_ones)
420 {
421 /* Trailing ones in NODE turn into zeros, but leading ones remain,
422 e.g. 000011{11} 00001111 becomes 000011 {00}00001111. Give the
423 trailing ones to the next node as zeros and go around again with
424 the next node. */
425 struct range_tower_node *next;
426 unsigned long int delta;
427
428 delta = node->n_ones - (node_ofs - node->n_zeros);
429 node->n_ones -= delta;
430 abt_reaugmented (&rt->abt, &node->abt_node);
431
432 next = range_tower_next__ (rt, node);
433 if (next == NULL)
434 {
435 struct range_tower_node *new_node;
436
437 new_node = xmalloc (sizeof *new_node);
438 new_node->n_zeros = delta;
439 new_node->n_ones = 0;
440
441 abt_insert_before (&rt->abt, NULL, &new_node->abt_node);
442 return;
443 }
444
445 next->n_zeros += delta;
446 abt_reaugmented (&rt->abt, &next->abt_node);
447
448 node_start += node->n_zeros + node->n_ones;
449 start = node_start;
450 node = next;
451 }
452 else
453 {
454 /* Ones that are neither leading or trailing turn into zeros,
455 e.g. 00001111 becomes 00001 001. Split the node into two nodes
456 and we're done. */
457 unsigned long int end = start + width;
458 struct range_tower_node *new_node;
459
460 new_node = xmalloc (sizeof *new_node);
461 new_node->n_zeros = width;
462 new_node->n_ones = (node_start + node->n_zeros + node->n_ones) - end;
463
464 node->n_ones = node_ofs - node->n_zeros;
465 abt_reaugmented (&rt->abt, &node->abt_node);
466
467 abt_insert_after (&rt->abt, &node->abt_node, &new_node->abt_node);
468 return;
469 }
470 }
471 }
472
473 static void
474 range_tower_delete__ (struct range_tower *rt,
475 unsigned long int start, unsigned long int width)
476 {
477 struct range_tower_node *node;
478 unsigned long int node_start;
479
480 rt->cache_end = 0;
481 node = range_tower_lookup (rt, start, &node_start);
482 for (;;)
483 {
484 unsigned long int node_ofs = start - node_start;
485
486 if (node_ofs < node->n_zeros)
487 {
488 if (node_ofs + width < node->n_zeros)
489 {
490 node->n_zeros -= width;
491 abt_reaugmented (&rt->abt, &node->abt_node);
492 break;
493 }
494 else if (node_ofs > 0)
495 {
496 width -= node->n_zeros - node_ofs;
497 node->n_zeros = node_ofs;
498 abt_reaugmented (&rt->abt, &node->abt_node);
499 if (width == 0)
500 break;
501 /* Continue with 1-bits. */
502 }
503 else if (width < node->n_zeros + node->n_ones)
504 {
505 struct range_tower_node *prev = range_tower_prev__ (rt, node);
506 unsigned long int ones_left;
507
508 ones_left = (node->n_zeros + node->n_ones) - width;
509 if (prev != NULL)
510 {
511 abt_delete (&rt->abt, &node->abt_node);
512 prev->n_ones += ones_left;
513 abt_reaugmented (&rt->abt, &prev->abt_node);
514 }
515 else
516 {
517 node->n_zeros = 0;
518 node->n_ones = ones_left;
519 abt_reaugmented (&rt->abt, &node->abt_node);
520 }
521 break;
522 }
523 else
524 {
525 /* Delete entire node. */
526 struct range_tower_node *next = range_tower_next__ (rt, node);
527
528 width -= node->n_zeros + node->n_ones;
529 abt_delete (&rt->abt, &node->abt_node);
530 if (next == NULL)
531 break;
532
533 node = next;
534 continue;
535 }
536 }
537
538 if (node_ofs + width < node->n_zeros + node->n_ones)
539 {
540 node->n_ones -= width;
541 abt_reaugmented (&rt->abt, &node->abt_node);
542 break;
543 }
544 else if (node_ofs > node->n_zeros)
545 {
546 unsigned long int ones_ofs = node_ofs - node->n_zeros;
547 width -= node->n_ones - ones_ofs;
548 node->n_ones = ones_ofs;
549 abt_reaugmented (&rt->abt, &node->abt_node);
550 if (width == 0)
551 break;
552 /* continue with next node */
553 node_start += node->n_zeros + node->n_ones;
554 node = range_tower_next__ (rt, node);
555 }
556 else
557 {
558 /* Merge with next node */
559 struct range_tower_node *next = range_tower_next__ (rt, node);
560 if (next != NULL)
561 {
562 unsigned long int next_zeros = next->n_zeros;
563 unsigned long int next_ones = next->n_ones;
564
565 abt_delete (&rt->abt, &next->abt_node);
566
567 width -= node->n_ones;
568
569 node->n_zeros += next_zeros;
570 node->n_ones = next_ones;
571 abt_reaugmented (&rt->abt, &node->abt_node);
572
573 if (width == 0)
574 break;
575 }
576 else
577 {
578 node->n_ones = 0;
579 abt_reaugmented (&rt->abt, &node->abt_node);
580 break;
581 }
582 }
583 }
584 }
585
586 void
587 range_tower_delete (struct range_tower *rt,
588 unsigned long int start, unsigned long int width)
589 {
590 struct range_tower_node *node;
591
592 if (width == 0)
593 return;
594
595 assert (start + width - 1 >= start);
596
597 range_tower_delete__ (rt, start, width);
598
599 node = range_tower_last__ (rt);
600 if (node != NULL && node->n_ones == 0)
601 {
602 node->n_zeros += width;
603 abt_reaugmented (&rt->abt, &node->abt_node);
604 }
605 else
606 {
607 struct range_tower_node *new_node;
608
609 new_node = xmalloc (sizeof *new_node);
610 new_node->n_zeros = width;
611 new_node->n_ones = 0;
612
613 abt_insert_before (&rt->abt, NULL, &new_node->abt_node);
614 }
615 }
616
617 static struct range_tower_node *
618 range_tower_insert0__ (struct range_tower *rt, struct range_tower_node *node,
619 unsigned long int *node_startp,
620 unsigned long int start, unsigned long int width)
621 {
622 unsigned long int node_ofs = start - *node_startp;
623
624 if (node_ofs <= node->n_zeros)
625 {
626 /* 00+00+001111 => 0000001111. */
627 node->n_zeros += width;
628 abt_reaugmented (&rt->abt, &node->abt_node);
629
630 return node;
631 }
632 else
633 {
634 /* 000011+00+11 => 000011 0011. */
635 struct range_tower_node *new_node;
636
637 new_node = xmalloc (sizeof *new_node);
638 new_node->n_zeros = width;
639 new_node->n_ones = node->n_zeros + node->n_ones - node_ofs;
640
641 node->n_ones -= new_node->n_ones;
642 abt_reaugmented (&rt->abt, &node->abt_node);
643 abt_insert_after (&rt->abt, &node->abt_node, &new_node->abt_node);
644
645 *node_startp += node->n_zeros + node->n_ones;
646 return new_node;
647 }
648 }
649
650 void
651 range_tower_insert0 (struct range_tower *rt,
652 unsigned long int start, unsigned long int width)
653 {
654 if (width == 0)
655 return;
656
657 assert (width == 0 || start + width - 1 >= start);
658
659 if (start + width == ULONG_MAX)
660 range_tower_set0 (rt, start, width);
661 else
662 {
663 struct range_tower_node *node;
664 unsigned long int node_start;
665
666 range_tower_delete__ (rt, ULONG_MAX - width, width);
667
668 node = range_tower_lookup (rt, start, &node_start);
669 range_tower_insert0__ (rt, node, &node_start, start, width);
670 }
671 }
672
673 static struct range_tower_node *
674 range_tower_insert1__ (struct range_tower *rt, struct range_tower_node *node,
675 unsigned long int *node_startp,
676 unsigned long int start, unsigned long int width)
677 {
678
679 unsigned long int node_start = *node_startp;
680 unsigned long int node_ofs = start - node_start;
681
682 if (node_ofs >= node->n_zeros)
683 {
684 node->n_ones += width;
685 abt_reaugmented (&rt->abt, &node->abt_node);
686 return node;
687 }
688 else if (node_ofs == 0 && node_start > 0)
689 {
690 struct range_tower_node *prev = range_tower_prev__ (rt, node);
691
692 prev->n_ones += width;
693 abt_reaugmented (&rt->abt, &prev->abt_node);
694
695 *node_startp += width;
696 return node;
697 }
698 else
699 {
700 /* 00001111 => 0+11+0001111 => 011 0001111 */
701 struct range_tower_node *new_node;
702
703 new_node = xmalloc (sizeof *new_node);
704 new_node->n_zeros = node->n_zeros - node_ofs;
705 new_node->n_ones = node->n_ones;
706
707 node->n_zeros = node_ofs;
708 node->n_ones = width;
709 abt_reaugmented (&rt->abt, &node->abt_node);
710
711 abt_insert_after (&rt->abt, &node->abt_node, &new_node->abt_node);
712
713 *node_startp += node->n_zeros + node->n_ones;
714 return new_node;
715 }
716 }
717
718 void
719 range_tower_insert1 (struct range_tower *rt,
720 unsigned long int start, unsigned long int width)
721 {
722 struct range_tower_node *node;
723 unsigned long int node_start;
724
725 if (width == 0)
726 return;
727
728 range_tower_delete__ (rt, ULONG_MAX - width, width);
729
730 assert (width == 0 || start + width - 1 >= start);
731
732 node = range_tower_lookup (rt, start, &node_start);
733 range_tower_insert1__ (rt, node, &node_start, start, width);
734 }
735
736 void
737 range_tower_move (struct range_tower *rt,
738 unsigned long int old_start,
739 unsigned long int new_start,
740 unsigned long int width)
741 {
742 unsigned long int node_start;
743 int i;
744
745 if (width == 0 || old_start == new_start)
746 return;
747
748 assert (old_start + width - 1 >= old_start);
749 assert (new_start + width - 1 >= new_start);
750
751 i = 0;
752 do
753 {
754 struct range_tower_node *node;
755 unsigned long int node_ofs;
756 unsigned long int zeros, ones;
757
758 node = range_tower_lookup (rt, old_start, &node_start);
759 node_ofs = old_start - node_start;
760
761 if (node_ofs >= node->n_zeros)
762 {
763 unsigned long int max_ones;
764
765 zeros = 0;
766 max_ones = (node->n_zeros + node->n_ones) - node_ofs;
767 ones = MIN (width, max_ones);
768 }
769 else
770 {
771 unsigned long int max_zeros;
772
773 max_zeros = node->n_zeros - node_ofs;
774 zeros = MIN (width, max_zeros);
775 if (zeros < width)
776 ones = MIN (width - zeros, node->n_ones);
777 else
778 ones = 0;
779 }
780
781 node->n_zeros -= zeros;
782 node->n_ones -= ones;
783 abt_reaugmented (&rt->abt, &node->abt_node);
784
785 if (node->n_zeros == 0)
786 {
787 if (node->n_ones == 0)
788 abt_delete (&rt->abt, &node->abt_node);
789 else if (node_start > 0)
790 {
791 /* Merge with previous. */
792 unsigned long int n_ones = node->n_ones;
793 struct range_tower_node *prev = range_tower_prev__ (rt, node);
794
795 abt_delete (&rt->abt, &node->abt_node);
796 prev->n_ones += n_ones;
797 abt_reaugmented (&rt->abt, &prev->abt_node);
798 }
799 }
800 else if (node->n_ones == 0)
801 {
802 struct range_tower_node *next = range_tower_next__ (rt, node);
803 if (next != NULL)
804 {
805 /* Merge with next. */
806 unsigned long int n_zeros = node->n_zeros;
807
808 abt_delete (&rt->abt, &node->abt_node);
809 next->n_zeros += n_zeros;
810 abt_reaugmented (&rt->abt, &next->abt_node);
811 }
812 }
813
814 if (new_start < old_start)
815 {
816 node = range_tower_lookup (rt, new_start, &node_start);
817 if (zeros)
818 {
819 node = range_tower_insert0__ (rt, node, &node_start,
820 new_start, zeros);
821 old_start += zeros;
822 new_start += zeros;
823 }
824
825 if (ones)
826 {
827 node = range_tower_insert1__ (rt, node, &node_start,
828 new_start, ones);
829 old_start += ones;
830 new_start += ones;
831 }
832 }
833 else
834 {
835 unsigned long int remaining = width - (zeros + ones);
836
837 if (new_start + remaining < ULONG_MAX - (zeros + ones))
838 {
839 node = range_tower_lookup (rt, new_start + remaining,
840 &node_start);
841 if (zeros)
842 {
843 node = range_tower_insert0__ (rt, node, &node_start,
844 new_start + remaining, zeros);
845 new_start += zeros;
846 }
847
848 if (ones)
849 {
850 node = range_tower_insert1__ (rt, node, &node_start,
851 new_start + remaining, ones);
852 new_start += ones;
853 }
854 }
855 else
856 {
857 node = range_tower_last__ (rt);
858 if (zeros)
859 {
860 if (node->n_ones)
861 {
862 struct range_tower_node *new_node;
863
864 new_node = xmalloc (sizeof *new_node);
865 new_node->n_zeros = zeros;
866 new_node->n_ones = 0;
867
868 abt_insert_after (&rt->abt, &node->abt_node,
869 &new_node->abt_node);
870
871 node_start += node->n_zeros + node->n_ones;
872 node = new_node;
873 }
874 else
875 {
876 node->n_zeros += zeros;
877 abt_reaugmented (&rt->abt, &node->abt_node);
878 }
879 }
880 if (ones)
881 {
882 node->n_ones += ones;
883 abt_reaugmented (&rt->abt, &node->abt_node);
884 }
885
886 new_start += zeros + ones;
887 }
888 }
889 width -= zeros + ones;
890 }
891 while (width > 0);
892 }
893
894 /* Returns true if there is a 1-bit at the given POSITION in RT,
895 false otherwise. */
896 bool
897 range_tower_contains (const struct range_tower *rt_, unsigned long int position)
898 {
899 struct range_tower *rt = CONST_CAST (struct range_tower *, rt_);
900 if (position >= rt->cache_end || position < rt->cache_start)
901 {
902 struct range_tower_node *node;
903 unsigned long int node_start;
904
905 node = range_tower_lookup (rt, position, &node_start);
906 if (position < node_start + node->n_zeros)
907 {
908 rt->cache_start = node_start;
909 rt->cache_end = node_start + node->n_zeros;
910 rt->cache_value = false;
911 }
912 else
913 {
914 rt->cache_start = node_start + node->n_zeros;
915 rt->cache_end = rt->cache_start + node->n_ones;
916 rt->cache_value = true;
917 }
918 }
919 return rt->cache_value;
920 }
921
922 /* Returns the smallest position of a 1-bit greater than or
923 equal to START. Returns ULONG_MAX if there is no 1-bit with
924 position greater than or equal to START. */
925 unsigned long int
926 range_tower_scan (const struct range_tower *rt_, unsigned long int start)
927 {
928 struct range_tower *rt = CONST_CAST (struct range_tower *, rt_);
929
930 if (start < rt->cache_end && start >= rt->cache_start && rt->cache_value)
931 return start;
932
933 if (start != ULONG_MAX)
934 {
935 struct range_tower_node *node;
936 unsigned long int node_start;
937
938 node = range_tower_lookup (rt, start, &node_start);
939 if (node->n_ones)
940 {
941 rt->cache_start = node_start + node->n_zeros;
942 rt->cache_end = rt->cache_start + node->n_ones;
943 rt->cache_value = true;
944 return MAX (start, rt->cache_start);
945 }
946 else
947 {
948 rt->cache_start = node_start;
949 rt->cache_end = ULONG_MAX;
950 rt->cache_value = false;
951 }
952 }
953 return ULONG_MAX;
954 }
955
956 /* Recalculates the subtree_width of NODE based on its LEFT and
957 RIGHT children's "subtree_width"s. */
958 static void
959 reaugment_range_tower_node (struct abt_node *node_, const void *aux UNUSED)
960 {
961 struct range_tower_node *node = range_tower_node_from_abt_node (node_);
962
963 node->subtree_width = node->n_zeros + node->n_ones;
964 if (node->abt_node.down[0] != NULL)
965 {
966 struct range_tower_node *left;
967
968 left = range_tower_node_from_abt_node (node->abt_node.down[0]);
969 node->subtree_width += left->subtree_width;
970 }
971 if (node->abt_node.down[1] != NULL)
972 {
973 struct range_tower_node *right;
974
975 right = range_tower_node_from_abt_node (node->abt_node.down[1]);
976 node->subtree_width += right->subtree_width;
977 }
978 }
979
980 /* Deletes NODE from RT and frees it. */
981 static void
982 delete_node (struct range_tower *rt, struct range_tower_node *node)
983 {
984 abt_delete (&rt->abt, &node->abt_node);
985 free (node);
986 }
987
988 struct range_tower_node *
989 range_tower_lookup (const struct range_tower *rt, unsigned long int position,
990 unsigned long int *node_start)
991 {
992 const struct range_tower_node *node;
993 const struct abt_node *abt_node;
994
995 abt_node = rt->abt.root;
996 node = range_tower_node_from_abt_node (abt_node);
997 *node_start = subtree_width (abt_node->down[0]);
998 for (;;)
999 {
1000 unsigned long int left_width = subtree_width (abt_node->down[0]);
1001
1002 if (position < left_width)
1003 {
1004 abt_node = abt_node->down[0];
1005 *node_start -= left_width - subtree_width (abt_node->down[0]);
1006 }
1007 else
1008 {
1009 unsigned long int node_width = node->n_zeros + node->n_ones;
1010
1011 position -= left_width;
1012 if (position < node_width)
1013 return CONST_CAST (struct range_tower_node *, node);
1014
1015 position -= node_width;
1016 abt_node = abt_node->down[1];
1017 left_width = subtree_width (abt_node->down[0]);
1018 *node_start += node_width + left_width;
1019 }
1020 node = range_tower_node_from_abt_node (abt_node);
1021 }
1022 }
1023
1024 /* Destroys range tower RT.
1025 Helper function for range_tower_create_pool. */
1026 static void
1027 destroy_pool (void *rt_)
1028 {
1029 struct range_tower *rt = rt_;
1030 rt->pool = NULL;
1031 range_tower_destroy (rt);
1032 }
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* Bitmap, implemented as an augmented binary tree.
17
18 Beyond the usual features of a bitmap, a range tower can efficiently
19 implement a "splice" operation that shifts ranges of bits left or right.
20 This feature does cost memory and time, so use a range tower only if this
21 feature is actually needed. Otherwise, use a range set (see range-set.h),
22 which can do everything that a range tower can do except the "splice"
23 operation.
24
25 Each operation has O(lg N) cost, where N is the number of contiguous regions
26 of 1-bits in the bitmap. Also, a cache reduces the second and subsequent
27 containment tests within a single contiguous region to O(1). */
28
29 #ifndef LIBPSPP_RANGE_TOWER_H
30 #define LIBPSPP_RANGE_TOWER_H
31
32 #include <limits.h>
33 #include <stdbool.h>
34 #include "libpspp/abt.h"
35 #include "libpspp/cast.h"
36
37 /* A tower of ranges. */
38 struct range_tower
39 {
40 struct pool *pool; /* Pool for freeing range_tower. */
41 struct abt abt; /* Tree of range_tower_nodes. */
42
43 /* Cache. */
44 unsigned long int cache_start; /* Start of region. */
45 unsigned long int cache_end; /* One past end of region. */
46 bool cache_value; /* Is the region in the tower? */
47 };
48
49 /* A node in the range tower. */
50 struct range_tower_node
51 {
52 struct abt_node abt_node; /* Augmented binary tree node. */
53 unsigned long int n_zeros; /* Number of leading zeros. */
54 unsigned long int n_ones; /* Number of ones following the zeros. */
55 unsigned long int subtree_width; /* n_zeros + n_ones + sum of descendants. */
56 };
57
58 struct range_tower *range_tower_create (void);
59 struct range_tower *range_tower_create_pool (struct pool *);
60 struct range_tower *range_tower_clone (const struct range_tower *,
61 struct pool *);
62 void range_tower_destroy (struct range_tower *);
63
64 void range_tower_splice (struct range_tower *,
65 unsigned long int start,
66 unsigned long int old_width,
67 unsigned long int new_width);
68
69 void range_tower_set1 (struct range_tower *,
70 unsigned long int start, unsigned long int width);
71 void range_tower_set0 (struct range_tower *,
72 unsigned long int start, unsigned long int width);
73
74 void range_tower_insert1 (struct range_tower *,
75 unsigned long int start, unsigned long int width);
76 void range_tower_insert0 (struct range_tower *,
77 unsigned long int start, unsigned long int width);
78
79 void range_tower_delete (struct range_tower *,
80 unsigned long int start, unsigned long int width);
81
82 void range_tower_move (struct range_tower *,
83 unsigned long int old_start,
84 unsigned long int new_start,
85 unsigned long int width);
86
87 bool range_tower_contains (const struct range_tower *,
88 unsigned long int position);
89 unsigned long int range_tower_scan (const struct range_tower *,
90 unsigned long int start);
91
92 static inline bool range_tower_is_empty (const struct range_tower *);
93
94 #define RANGE_TOWER_FOR_EACH(NODE, START, RANGE_TOWER) \
95 for ((NODE) = range_tower_first (RANGE_TOWER), (START) = 0; \
96 (NODE) && ((START) += (NODE)->n_zeros, true); \
97 (START) += (NODE)->n_ones, \
98 (NODE) = range_tower_next (RANGE_TOWER, NODE))
99
100 static inline const struct range_tower_node *range_tower_first (
101 const struct range_tower *);
102 static inline const struct range_tower_node *range_tower_next (
103 const struct range_tower *, const struct range_tower_node *);
104 static inline const struct range_tower_node *range_tower_last (
105 const struct range_tower *);
106 static inline const struct range_tower_node *range_tower_prev (
107 const struct range_tower *, const struct range_tower_node *);
108 unsigned long int range_tower_node_get_start (const struct range_tower_node *);
109 unsigned long int range_tower_node_get_end (const struct range_tower_node *);
110 static inline unsigned long int range_tower_node_get_width (
111 const struct range_tower_node *);
112
113 /* Inline functions. */
114
115 static inline struct range_tower_node *range_tower_node_from_abt__ (
116 const struct abt_node *);
117 static inline struct range_tower_node *range_tower_next__ (
118 const struct range_tower *, const struct range_tower_node *);
119 static inline struct range_tower_node *range_tower_first__ (
120 const struct range_tower *);
121 static inline struct range_tower_node *range_tower_prev__ (
122 const struct range_tower *, const struct range_tower_node *);
123 static inline struct range_tower_node *range_tower_last__ (
124 const struct range_tower *);
125
126 /* Returns true if RS contains no 1-bits, false otherwise. */
127 static inline bool
128 range_tower_is_empty (const struct range_tower *rs)
129 {
130 const struct range_tower_node *node =
131 abt_data (rs->abt.root, struct range_tower_node, abt_node);
132
133 return node->n_zeros == ULONG_MAX;
134 }
135
136 /* Returns the node representing the first contiguous region of
137 1-bits in RS, or a null pointer if RS is empty.
138 Any call to range_tower_set1, range_tower_set0, or
139 range_tower_allocate invalidates the returned node. */
140 static inline const struct range_tower_node *
141 range_tower_first (const struct range_tower *rs)
142 {
143 const struct range_tower_node *node = range_tower_first__ (rs);
144 return node->n_ones ? node : NULL;
145 }
146
147 /* If NODE is nonnull, returns the node representing the next
148 contiguous region of 1-bits in RS following NODE, or a null
149 pointer if NODE is the last region in RS.
150 If NODE is null, returns the first region in RS, as for
151 range_tower_first.
152 Any call to range_tower_set1, range_tower_set0, or
153 range_tower_allocate invalidates the returned node. */
154 static inline const struct range_tower_node *
155 range_tower_next (const struct range_tower *rs,
156 const struct range_tower_node *node)
157 {
158 if (node != NULL)
159 {
160 const struct range_tower_node *next = range_tower_next__ (rs, node);
161 return next != NULL && next->n_ones ? next : NULL;
162 }
163 else
164 return range_tower_first (rs);
165 }
166
167 /* Returns the node representing the last contiguous region of
168 1-bits in RS, or a null pointer if RS is empty.
169 Any call to range_tower_set1, range_tower_set0, or
170 range_tower_allocate invalidates the returned node. */
171 static inline const struct range_tower_node *
172 range_tower_last (const struct range_tower *rs)
173 {
174 const struct range_tower_node *node = range_tower_last__ (rs);
175 return node->n_ones ? node : range_tower_prev__(rs, node);
176 }
177
178 /* If NODE is nonnull, returns the node representing the previous
179 contiguous region of 1-bits in RS following NODE, or a null
180 pointer if NODE is the first region in RS.
181 If NODE is null, returns the last region in RS, as for
182 range_tower_last.
183 Any call to range_tower_set1, range_tower_set0, or
184 range_tower_allocate invalidates the returned node. */
185 static inline const struct range_tower_node *
186 range_tower_prev (const struct range_tower *rs,
187 const struct range_tower_node *node)
188 {
189 return node != NULL ? range_tower_prev__ (rs, node) : range_tower_last (rs);
190 }
191
192 /* Returns the number of contiguous 1-bits in NODE. */
193 static inline unsigned long int
194 range_tower_node_get_width (const struct range_tower_node *node)
195 {
196 return node->n_ones;
197 }
198
199 /* Internal helper functions. */
200
201 /* Returns the range_tower_node corresponding to the given
202 ABT_NODE. Returns a null pointer if ABT_NODE is null. */
203 static inline struct range_tower_node *
204 range_tower_node_from_abt__ (const struct abt_node *abt_node)
205 {
206 return (abt_node
207 ? abt_data (abt_node, struct range_tower_node, abt_node)
208 : NULL);
209 }
210
211 /* Returns the next range_tower_node in RS after NODE,
212 or a null pointer if NODE is the last node in RS. */
213 static inline struct range_tower_node *
214 range_tower_next__ (const struct range_tower *rs,
215 const struct range_tower_node *node)
216 {
217 return range_tower_node_from_abt__ (abt_next (&rs->abt, &node->abt_node));
218 }
219
220 /* Returns the first range_tower_node in RS,
221 or a null pointer if RS is empty. */
222 static inline struct range_tower_node *
223 range_tower_first__ (const struct range_tower *rs)
224 {
225 return range_tower_node_from_abt__ (abt_first (&rs->abt));
226 }
227
228 /* Returns the previous range_tower_node in RS after NODE,
229 or a null pointer if NODE is the first node in RS. */
230 static inline struct range_tower_node *
231 range_tower_prev__ (const struct range_tower *rs,
232 const struct range_tower_node *node)
233 {
234 return range_tower_node_from_abt__ (abt_prev (&rs->abt, &node->abt_node));
235 }
236
237 /* Returns the last range_tower_node in RS,
238 or a null pointer if RS is empty. */
239 static inline struct range_tower_node *
240 range_tower_last__ (const struct range_tower *rs)
241 {
242 return range_tower_node_from_abt__ (abt_last (&rs->abt));
243 }
244
245 struct range_tower_node *range_tower_lookup (
246 const struct range_tower *, unsigned long int position,
247 unsigned long int *node_start);
248
249 #endif /* libpspp/range-tower.h */
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
104104
105105 new->disk = ext_array_create ();
106106 new->disk_rows = range_set_clone (old->disk_rows, NULL);
107 for (node = range_set_first (old->disk_rows); node != NULL;
108 node = range_set_next (old->disk_rows, node))
107 RANGE_SET_FOR_EACH (node, old->disk_rows)
109108 {
110109 unsigned long int start = range_set_node_get_start (node);
111110 unsigned long int end = range_set_node_get_end (node);
206205 sx->disk_rows = NULL;
207206 return false;
208207 }
209 range_set_insert (sx->disk_rows, idx, 1);
208 range_set_set1 (sx->disk_rows, idx, 1);
210209 }
211210 sparse_array_destroy (sx->memory);
212211 sx->memory = NULL;
263262 return ext_array_write (sx->disk, ofs + start, n, data);
264263 else
265264 {
266 range_set_insert (sx->disk_rows, row, 1);
265 range_set_set1 (sx->disk_rows, row, 1);
267266 return (ext_array_write (sx->disk, ofs, start, sx->default_row)
268267 && ext_array_write (sx->disk, ofs + start, n, data)
269268 && ext_array_write (sx->disk, ofs + start + n,
335334 {
336335 const struct range_set_node *node;
337336
338 for (node = range_set_first (sx->disk_rows); node != NULL;
339 node = range_set_next (sx->disk_rows, node))
337 RANGE_SET_FOR_EACH (node, sx->disk_rows)
340338 {
341339 unsigned long int start_row = range_set_node_get_start (node);
342340 unsigned long int end_row = range_set_node_get_end (node);
445443 const struct range_set_node *node;
446444 void *tmp = xmalloc (sx->n_bytes);
447445
448 for (node = range_set_first (sx->disk_rows); node != NULL;
449 node = range_set_next (sx->disk_rows, node))
446 RANGE_SET_FOR_EACH (node, sx->disk_rows)
450447 {
451448 unsigned long int start = range_set_node_get_start (node);
452449 unsigned long int end = range_set_node_get_end (node);
586583 void *tmp = xmalloc (sx->n_bytes);
587584
588585 md4_process_bytes ("d", 1, &ctx);
589 for (node = range_set_first (sx->disk_rows); node != NULL;
590 node = range_set_next (sx->disk_rows, node))
586 RANGE_SET_FOR_EACH (node, sx->disk_rows)
591587 {
592588 unsigned long int start = range_set_node_get_start (node);
593589 unsigned long int end = range_set_node_get_end (node);
3232 const struct tower_node *);
3333 static unsigned long int get_subtree_size (const struct abt_node *);
3434 static unsigned long int get_subtree_count (const struct abt_node *);
35 static void reaugment_tower_node (struct abt_node *,
36 const struct abt_node *,
37 const struct abt_node *,
38 const void *aux);
35 static void reaugment_tower_node (struct abt_node *, const void *aux);
3936
4037 /* Returns the height of the bottom of the given tower NODE.
4138
350347 return p != NULL ? abt_to_tower_node (p)->subtree_count : 0;
351348 }
352349
353 /* Recalculates the subtree_size of NODE based on its LEFT and
354 RIGHT children's subtree_sizes. */
350 /* Recalculates the subtree_size of NODE based on the subtree_sizes of its
351 children. */
355352 static void
356 reaugment_tower_node (struct abt_node *node_,
357 const struct abt_node *left,
358 const struct abt_node *right,
359 const void *aux UNUSED)
353 reaugment_tower_node (struct abt_node *node_, const void *aux UNUSED)
360354 {
361355 struct tower_node *node = abt_to_tower_node (node_);
362356 node->subtree_size = node->size;
363357 node->subtree_count = 1;
364 if (left != NULL)
365 {
366 struct tower_node *left_node = abt_to_tower_node (left);
367 node->subtree_size += left_node->subtree_size;
368 node->subtree_count += left_node->subtree_count;
369 }
370 if (right != NULL)
371 {
372 struct tower_node *right_node = abt_to_tower_node (right);
373 node->subtree_size += right_node->subtree_size;
374 node->subtree_count += right_node->subtree_count;
375 }
376 }
358
359 if (node->abt_node.down[0] != NULL)
360 {
361 struct tower_node *left = abt_to_tower_node (node->abt_node.down[0]);
362 node->subtree_size += left->subtree_size;
363 node->subtree_count += left->subtree_count;
364 }
365
366 if (node->abt_node.down[1] != NULL)
367 {
368 struct tower_node *right = abt_to_tower_node (node->abt_node.down[1]);
369 node->subtree_size += right->subtree_size;
370 node->subtree_count += right->subtree_count;
371 }
372 }
2121 #include <float.h>
2222
2323 #include "data/case.h"
24 #include "data/data-out.h"
2425 #include "data/val-type.h"
2526 #include "data/variable.h"
2627 #include "libpspp/assertion.h"
8182 o->extreme = extreme;
8283 ds_init_empty (&o->label);
8384
84 ds_put_format (&o->label,
85 "%ld",
86 (casenumber) case_data_idx (cx, bw->casenumber_idx)->f);
85 if (bw->id_var)
86 {
87 char *s = data_out (case_data_idx (cx, bw->id_idx),
88 var_get_encoding (bw->id_var),
89 var_get_print_format (bw->id_var));
90
91 ds_put_cstr (&o->label, s);
92 free (s);
93 }
94 else
95 {
96 ds_put_format (&o->label,
97 "%ld",
98 (casenumber) case_data_idx (cx, bw->id_idx)->f);
99 }
87100
88101 ll_push_head (&bw->outliers, &o->ll);
89102 }
114127
115128 TH are the tukey hinges of the dataset.
116129
117 Casenumber_idx is the index into the casereader which will be used to label
130 id_idx is the index into the casereader which will be used to label
118131 outliers.
132 id_var is the variable from which that label came, or NULL
119133 */
120134 struct box_whisker *
121135 box_whisker_create (const struct tukey_hinges *th,
122 size_t casenumber_idx)
136 size_t id_idx, const struct variable *id_var)
123137 {
124138 struct box_whisker *w = xzalloc (sizeof (*w));
125139 struct order_stats *os = &w->parent;
132146
133147 tukey_hinges_calculate (th, w->hinges);
134148
135 w->casenumber_idx = casenumber_idx;
149 w->id_idx = id_idx;
150 w->id_var = id_var;
136151
137152 w->step = (w->hinges[2] - w->hinges[0]) * 1.5;
138153
2525 However, there's no reason not to use it for other purposes too.
2626 */
2727 struct tukey_hinges;
28 struct variable;
2829
2930 struct outlier
3031 {
4647
4748 double step;
4849
49 size_t casenumber_idx;
50 size_t id_idx;
51 const struct variable *id_var;
5052 };
5153
5254 struct box_whisker * box_whisker_create (const struct tukey_hinges *,
53 size_t);
55 size_t id_idx, const struct variable *id_var);
5456
5557 void box_whisker_whiskers (const struct box_whisker *bw, double whiskers[2]);
5658
164164
165165 struct pool *pool;
166166
167 /* Missing values to be excluded */
168 enum mv_class exclude;
167 /* Missing values in the dependent varirable to be excluded */
168 enum mv_class dep_excl;
169
170 /* Missing values in the factor variables to be excluded */
171 enum mv_class fctr_excl;
169172
170173 const void *aux1;
171174 void *aux2;
294297
295298 struct categoricals *
296299 categoricals_create (struct interaction *const*inter, size_t n_inter,
297 const struct variable *wv, enum mv_class exclude)
300 const struct variable *wv, enum mv_class dep_excl, enum mv_class fctr_excl)
298301 {
299302 size_t i;
300303 struct categoricals *cat = xmalloc (sizeof *cat);
306309 cat->reverse_variable_map_short = NULL;
307310 cat->reverse_variable_map_long = NULL;
308311 cat->pool = pool_create ();
309 cat->exclude = exclude;
312 cat->dep_excl = dep_excl;
313 cat->fctr_excl = fctr_excl;
310314 cat->payload = NULL;
311315 cat->aux2 = NULL;
312316
377381 size_t hash;
378382 struct interaction_value *node;
379383
380 if ( interaction_case_is_missing (iact, c, cat->exclude))
384 if ( interaction_case_is_missing (iact, c, cat->fctr_excl))
381385 continue;
382386
383387 hash = interaction_case_hash (iact, c, 0);
2828 union value ;
2929
3030 struct categoricals *categoricals_create (struct interaction *const *, size_t n_int,
31 const struct variable *wv, enum mv_class exclude);
31 const struct variable *wv, enum mv_class dep_excl,
32 enum mv_class fctr_excl);
3233
3334 void categoricals_destroy (struct categoricals *);
3435
1919
2020 #include "chart-geometry.h"
2121
22 static const double standard_ticks[] = {1, 2, 5, 10};
23
24
2225 /* Adjust tick to be a sensible value
2326 ie: ... 0.1,0.2,0.5, 1,2,5, 10,20,50 ... */
2427 double
25 chart_rounded_tick(double tick)
28 chart_rounded_tick (double tick)
2629 {
27
2830 int i;
2931
3032 double diff = DBL_MAX;
3133 double t = tick;
3234
33 static const double standard_ticks[] = {1, 2, 5, 10};
35 double factor;
3436
35 const double factor = pow(10,ceil(log10(standard_ticks[0] / tick))) ;
37 /* Avoid arithmetic problems with very small values */
38 if (fabs (tick) < DBL_EPSILON)
39 return 0;
40
41 factor = pow (10,ceil (log10 (standard_ticks[0] / tick)));
3642
3743 for (i = 3 ; i >= 0 ; --i)
3844 {
39 const double d = fabs( tick - standard_ticks[i] / factor ) ;
45 const double d = fabs (tick - standard_ticks[i] / factor);
4046
4147 if ( d < diff )
4248 {
4652 }
4753
4854 return t;
49
5055 }
5156
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2004, 2008, 2009, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2004, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
2020 #include <gsl/gsl_histogram.h>
2121 #include <math.h>
2222
23 #include "libpspp/message.h"
2324 #include "libpspp/assertion.h"
2425 #include "libpspp/cast.h"
2526 #include "math/chart-geometry.h"
2627
28 #include "gettext.h"
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
31
32
2733 #include "gl/xalloc.h"
2834
2935 void
3339 stat->accumulate (stat, NULL, c, 0, y);
3440 }
3541
36
37
3842 static void
3943 acc (struct statistic *s, const struct ccase *cx UNUSED, double c, double cc UNUSED, double y)
4044 {
4246
4347 gsl_histogram_accumulate (hist->gsl_hist, y, c);
4448 }
45
4649
4750 static void
4851 destroy (struct statistic *s)
5356 }
5457
5558
59 static
60 double get_slack (double limit, double half_bin_width, int *n_half_bins)
61 {
62 double ipart, remainder;
63
64 assert (half_bin_width > 0);
65
66 remainder = modf (limit / half_bin_width, &ipart);
67
68 /* In C modf and % behave in an unexpected (to me at any rate) manner
69 when presented with a negative value
70
71 For example, modf (-7.0 / 3.0) returns -2.0 R -0.3333
72 */
73
74
75 *n_half_bins = ipart;
76
77 return remainder * half_bin_width;
78 }
79
80
81 /* This functions adjusts the upper and lower range of the histogram to make them fit BIN_WIDTH
82 MIN and MAX are the lowest and highest data to be plotted in the histogram.
83 ADJ_MIN and ADJ_MAX are locations of the adjusted values of MIN and MAX (the range will
84 always be equal or slightly larger).
85 Returns the number of bins.
86 */
87 static int
88 adjust_bin_ranges (double bin_width, double min, double max, double *adj_min, double *adj_max)
89 {
90 const double half_bin_width = bin_width / 2.0;
91
92 /* The lower and upper limits of the histogram, in units of half
93 bin widths */
94 int lower_limit, upper_limit;
95
96 double lower_slack = get_slack (min, half_bin_width, &lower_limit);
97 double upper_slack = -get_slack (max, half_bin_width, &upper_limit);
98
99 assert (max > min);
100
101 /* If min is negative, then lower_slack may be less than zero.
102 In this case, the lower bound must be extended in the negative direction
103 so that it is less than OR EQUAL to min.
104 */
105 if (lower_slack < 0)
106 {
107 lower_limit--;
108 lower_slack += half_bin_width;
109 }
110 assert (lower_limit * half_bin_width <= min);
111
112 /* However, the upper bound must be extended regardless, because histogram bins
113 span the range [lower, upper). In other words, the upper bound must be
114 greater than max.
115 */
116 upper_limit++;;
117 upper_slack += half_bin_width;
118 assert (upper_limit * half_bin_width > max);
119
120 /* The range must be an EVEN number of half bin_widths */
121 if ( (upper_limit - lower_limit) % 2)
122 {
123 /* Extend the range at the end which gives the least unused space */
124 if (upper_slack > lower_slack)
125 {
126 lower_limit--;
127 lower_slack += half_bin_width;
128 }
129 else
130 {
131 upper_limit++;
132 upper_slack += half_bin_width;
133 }
134 }
135
136 /* But the range should be aligned to an ODD number of
137 half bin widths, so that the labels are aesthetically pleasing ones.
138 Otherwise we are likely to get labels such as -3 -1 1 3 instead of -2 0 2 4
139 */
140 if ( lower_limit % 2 == 0)
141 {
142 /* If there is not enough slack at either end to perform a shift,
143 then we must extend the range so that there is. We must extend
144 by two half bin widths in order to preserve the EVEN condition
145 established above. Also, we extend on the end with the least
146 slack, in order to keep things as balanced as possible. */
147 if ( upper_slack > lower_slack && upper_slack <= half_bin_width)
148 {
149 lower_limit -= 2;
150 lower_slack += 2 * half_bin_width;
151 }
152
153 if (lower_slack > upper_slack && lower_slack < half_bin_width)
154 {
155 upper_limit += 2;
156 upper_slack += 2 * half_bin_width;
157 }
158
159 if (upper_slack > lower_slack)
160 {
161 assert (upper_slack > half_bin_width);
162
163 /* Adjust the range to the left */
164 lower_limit --;
165 upper_limit --;
166 upper_slack -= half_bin_width;
167 lower_slack += half_bin_width;
168 }
169 else
170 {
171 assert (lower_slack >= half_bin_width);
172
173 /* Adjust the range to the right */
174 lower_limit ++;
175 upper_limit ++;
176 lower_slack -= half_bin_width;
177 upper_slack += half_bin_width;
178 }
179 }
180
181 /* If there are any completely empty bins, then remove them,
182 since empty bins don't really add much information to the histogram.
183 */
184 if (upper_slack > 2 * half_bin_width)
185 {
186 upper_slack -= 2 * half_bin_width;
187 upper_limit -=2;
188 }
189
190 if (lower_slack >= 2 * half_bin_width)
191 {
192 lower_slack -= 2 * half_bin_width;
193 lower_limit +=2;
194 }
195
196 *adj_min = lower_limit * half_bin_width;
197 *adj_max = upper_limit * half_bin_width;
198
199 assert (*adj_max > max);
200 assert (*adj_min <= min);
201
202 return (upper_limit - lower_limit) / 2.0;
203 }
204
205
206
56207 struct histogram *
57 histogram_create (int bins, double min, double max)
58 {
59 struct histogram *h = xmalloc (sizeof *h);
60 struct statistic *stat = &h->parent;
61 double upper_limit, lower_limit;
62
63 double bin_width = chart_rounded_tick ((max - min) / (double) bins);
64 double bin_width_2 = bin_width / 2.0;
65
66 int n = ceil (max / (bin_width_2) ) ;
67
68 assert (max >= min);
69
70 if ( ! (n % 2 ) ) n++;
71 upper_limit = n * bin_width_2;
72
73 n = floor (min / (bin_width_2) ) ;
74 if ( ! (n % 2 ) ) n--;
75 lower_limit = n * bin_width_2;
208 histogram_create (double bin_width, double min, double max)
209 {
210 const int MAX_BINS = 25;
211 struct histogram *h;
212 struct statistic *stat;
213 int bins;
214 double adjusted_min, adjusted_max;
215
216 if (max == min)
217 {
218 msg (MW, _("Not creating histogram because the data contains less than 2 distinct values"));
219 return NULL;
220 }
221
222 assert (bin_width > 0);
223
224 bin_width = chart_rounded_tick (bin_width);
225 bins = adjust_bin_ranges (bin_width, min, max, &adjusted_min, &adjusted_max);
226
227 /* Force the number of bins to lie in a sensible range. */
228 if (bins > MAX_BINS)
229 {
230 bin_width = chart_rounded_tick ((max - min) / (double) (MAX_BINS - 1));
231 bins = adjust_bin_ranges (bin_width,
232 min, max, &adjusted_min, &adjusted_max);
233 }
234
235 /* Can this ever happen? */
236 if (bins < 1)
237 bins = 1;
238
239 h = xmalloc (sizeof *h);
76240
77241 h->gsl_hist = gsl_histogram_alloc (bins);
78 gsl_histogram_set_ranges_uniform (h->gsl_hist, lower_limit, upper_limit);
79
242
243 gsl_histogram_set_ranges_uniform (h->gsl_hist, adjusted_min, adjusted_max);
244
245 stat = &h->parent;
80246 stat->accumulate = acc;
81247 stat->destroy = destroy;
82248
2929 gsl_histogram *gsl_hist;
3030 };
3131
32 struct histogram * histogram_create (int bins, double max, double min);
32 /*
33 Prepare a histogram for data which lies in the range [min, max)
34 bin_width is a nominal figure only. It is a hint about what might be
35 an good approximate bin width, but the implementation will adjust it
36 as it thinks fit.
37 */
38 struct histogram * histogram_create (double bin_width, double min, double max);
3339
3440 void histogram_add (struct histogram *h, double y, double c);
3541
1919 src/output/charts/plot-hist.h \
2020 src/output/charts/roc-chart.c \
2121 src/output/charts/roc-chart.h \
22 src/output/charts/spreadlevel-plot.c \
23 src/output/charts/spreadlevel-plot.h \
2224 src/output/charts/scree.c \
2325 src/output/charts/scree.h \
2426 src/output/csv.c \
6567 src/output/charts/piechart-cairo.c \
6668 src/output/charts/plot-hist-cairo.c \
6769 src/output/charts/roc-chart-cairo.c \
68 src/output/charts/scree-cairo.c
70 src/output/charts/scree-cairo.c \
71 src/output/charts/spreadlevel-cairo.c
6972 endif
7073 if ODF_WRITE_SUPPORT
7174 src_output_liboutput_la_SOURCES += src/output/odt.c
4545 xrchart_geometry_init (cairo_t *cr, struct xrchart_geometry *geom,
4646 double width, double length)
4747 {
48 /* Set default chartetry. */
49 geom->data_top = 0.900 * length;
50 geom->data_right = 0.800 * width;
51 geom->data_bottom = 0.120 * length;
52 geom->data_left = 0.150 * width;
53 geom->abscissa_top = 0.070 * length;
54 geom->ordinate_right = 0.120 * width;
48 /* Set default chart geometry. */
49 geom->axis[SCALE_ORDINATE].data_max = 0.900 * length;
50 geom->axis[SCALE_ORDINATE].data_min = 0.120 * length;
51
52 geom->axis[SCALE_ABSCISSA].data_min = 0.150 * width;
53 geom->axis[SCALE_ABSCISSA].data_max = 0.800 * width;
54 geom->abscissa_bottom = 0.070 * length;
55 geom->ordinate_left = 0.050 * width;
5556 geom->title_bottom = 0.920 * length;
5657 geom->legend_left = 0.810 * width;
5758 geom->legend_right = width;
6667
6768 cairo_set_line_width (cr, 1.0);
6869
69 cairo_rectangle (cr, geom->data_left, geom->data_bottom,
70 geom->data_right - geom->data_left,
71 geom->data_top - geom->data_bottom);
70 cairo_rectangle (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->axis[SCALE_ORDINATE].data_min,
71 geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min,
72 geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min);
7273 cairo_stroke (cr);
7374 }
7475
149150 }
150151
151152 void
152 xrchart_label (cairo_t *cr, int horz_justify, int vert_justify,
153 double font_size, const char *string)
153 xrchart_label_rotate (cairo_t *cr, int horz_justify, int vert_justify,
154 double font_size, const char *string, double angle)
154155 {
155156 PangoFontDescription *desc;
156157 PangoLayout *layout;
165166 pango_font_description_set_absolute_size (desc, font_size * PANGO_SCALE);
166167
167168 cairo_save (cr);
169 cairo_rotate (cr, angle);
168170 cairo_get_current_point (cr, &x, &y);
169171 cairo_translate (cr, x, y);
170172 cairo_move_to (cr, 0, 0);
213215 pango_font_description_free (desc);
214216 }
215217
218 void
219 xrchart_label (cairo_t *cr, int horz_justify, int vert_justify,
220 double font_size, const char *string)
221 {
222 xrchart_label_rotate (cr, horz_justify, vert_justify, font_size, string, 0);
223 }
224
225
216226 /* Draw a tick mark at position
217 If label is non zero, then print it at the tick mark
227 If label is non null, then print it at the tick mark
218228 */
229 static void
230 draw_tick_internal (cairo_t *cr, const struct xrchart_geometry *geom,
231 enum tick_orientation orientation,
232 bool rotated,
233 double position,
234 const char *s);
235
219236 void
220237 draw_tick (cairo_t *cr, const struct xrchart_geometry *geom,
221238 enum tick_orientation orientation,
239 bool rotated,
222240 double position,
223241 const char *label, ...)
224242 {
243 va_list ap;
244 char *s;
245 va_start (ap, label);
246 s = xvasprintf (label, ap);
247
248 if (fabs (position) < DBL_EPSILON)
249 position = 0;
250
251 draw_tick_internal (cr, geom, orientation, rotated, position, s);
252 free (s);
253 va_end (ap);
254 }
255
256
257 static void
258 draw_tick_internal (cairo_t *cr, const struct xrchart_geometry *geom,
259 enum tick_orientation orientation,
260 bool rotated,
261 double position,
262 const char *s)
263 {
225264 const int tickSize = 10;
226265 double x, y;
227266
228 cairo_move_to (cr, geom->data_left, geom->data_bottom);
229
230 if (orientation == TICK_ABSCISSA)
267 cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->axis[SCALE_ORDINATE].data_min);
268
269 if (orientation == SCALE_ABSCISSA)
231270 {
232271 cairo_rel_move_to (cr, position, 0);
233272 cairo_rel_line_to (cr, 0, -tickSize);
234273 }
235 else if (orientation == TICK_ORDINATE)
274 else if (orientation == SCALE_ORDINATE)
236275 {
237276 cairo_rel_move_to (cr, 0, position);
238277 cairo_rel_line_to (cr, -tickSize, 0);
243282
244283 cairo_stroke (cr);
245284
246 if (label != NULL)
247 {
248 va_list ap;
249 char *s;
250
285 if (s != NULL)
286 {
251287 cairo_move_to (cr, x, y);
252288
253 va_start (ap, label);
254 s = xvasprintf (label, ap);
255 if (orientation == TICK_ABSCISSA)
256 xrchart_label (cr, 'c', 't', geom->font_size, s);
257 else if (orientation == TICK_ORDINATE)
289 if (orientation == SCALE_ABSCISSA)
290 {
291 if ( rotated)
292 xrchart_label_rotate (cr, 'l', 'c', geom->font_size, s, -G_PI_4);
293 else
294 xrchart_label (cr, 'c', 't', geom->font_size, s);
295 }
296 else if (orientation == SCALE_ORDINATE)
258297 {
259298 if (fabs (position) < DBL_EPSILON)
260299 cairo_rel_move_to (cr, 0, 10);
261300 xrchart_label (cr, 'r', 'c', geom->font_size, s);
262301 }
263 free (s);
264 va_end (ap);
265302 }
266303 }
267304
275312 char *s;
276313
277314 cairo_save (cr);
278 cairo_move_to (cr, geom->data_left, geom->title_bottom);
315 cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->title_bottom);
279316
280317 va_start(ap, title);
281318 s = xvasprintf (title, ap);
287324 }
288325
289326
290 /* Set the scale for the abscissa */
291 void
292 xrchart_write_xscale (cairo_t *cr, struct xrchart_geometry *geom,
293 double min, double max, int ticks)
294 {
295 double x;
327
328 static void
329 xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom,
330 double smin, double smax, int ticks, enum tick_orientation orient)
331 {
332 int s;
296333
297334 const double tick_interval =
298 chart_rounded_tick ((max - min) / (double) ticks);
299
300 geom->x_max = ceil (max / tick_interval) * tick_interval;
301 geom->x_min = floor (min / tick_interval) * tick_interval;
302 geom->abscissa_scale = fabs(geom->data_right - geom->data_left) /
303 fabs(geom->x_max - geom->x_min);
304
305 for (x = geom->x_min; x <= geom->x_max; x += tick_interval)
306 draw_tick (cr, geom, TICK_ABSCISSA,
307 (x - geom->x_min) * geom->abscissa_scale, "%g", x);
308 }
309
335 chart_rounded_tick ((smax - smin) / (double) ticks);
336
337 int upper = ceil (smax / tick_interval);
338 int lower = floor (smin / tick_interval);
339
340 geom->axis[orient].max = tick_interval * upper;
341 geom->axis[orient].min = tick_interval * lower;
342
343 geom->axis[orient].scale = (fabs (geom->axis[orient].data_max - geom->axis[orient].data_min)
344 / fabs (geom->axis[orient].max - geom->axis[orient].min));
345
346 for (s = 0 ; s < upper - lower; ++s)
347 {
348 double pos = (s + lower) * tick_interval;
349 draw_tick (cr, geom, orient, false,
350 s * tick_interval * geom->axis[orient].scale, "%g", pos);
351 }
352 }
310353
311354 /* Set the scale for the ordinate */
312355 void
313356 xrchart_write_yscale (cairo_t *cr, struct xrchart_geometry *geom,
314357 double smin, double smax, int ticks)
315358 {
316 double y;
317
318 const double tick_interval =
319 chart_rounded_tick ((smax - smin) / (double) ticks);
320
321 geom->y_max = ceil (smax / tick_interval) * tick_interval;
322 geom->y_min = floor (smin / tick_interval) * tick_interval;
323
324 geom->ordinate_scale =
325 (fabs (geom->data_top - geom->data_bottom)
326 / fabs (geom->y_max - geom->y_min));
327
328 for (y = geom->y_min; y <= geom->y_max; y += tick_interval)
329 draw_tick (cr, geom, TICK_ORDINATE,
330 (y - geom->y_min) * geom->ordinate_scale, "%g", y);
331 }
359 xrchart_write_scale (cr, geom, smin, smax, ticks, SCALE_ORDINATE);
360 }
361
362 /* Set the scale for the abscissa */
363 void
364 xrchart_write_xscale (cairo_t *cr, struct xrchart_geometry *geom,
365 double smin, double smax, int ticks)
366 {
367 xrchart_write_scale (cr, geom, smin, smax, ticks, SCALE_ABSCISSA);
368 }
369
332370
333371 /* Write the abscissa label */
334372 void
335373 xrchart_write_xlabel (cairo_t *cr, const struct xrchart_geometry *geom,
336374 const char *label)
337375 {
338 cairo_move_to (cr, geom->data_left, geom->abscissa_top);
376 cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->abscissa_bottom);
339377 xrchart_label (cr, 'l', 't', geom->font_size, label);
340378 }
341379
345383 const char *label)
346384 {
347385 cairo_save (cr);
348 cairo_translate (cr, -geom->data_bottom, -geom->ordinate_right);
349 cairo_move_to (cr, 0, 0);
386 cairo_translate (cr, geom->ordinate_left, geom->axis[SCALE_ORDINATE].data_min);
350387 cairo_rotate (cr, M_PI / 2.0);
388
351389 xrchart_label (cr, 'l', 'x', geom->font_size, label);
352390 cairo_restore (cr);
353391 }
361399 const int xpad = 10;
362400 const int ypad = 10;
363401 const int swatch = 20;
364 const int legend_top = geom->data_top;
402 const int legend_top = geom->axis[SCALE_ORDINATE].data_max;
365403 const int legend_bottom = legend_top -
366404 (vstep * geom->n_datasets + 2 * ypad );
367405
424462 xrchart_datum (cairo_t *cr, const struct xrchart_geometry *geom,
425463 int dataset UNUSED, double x, double y)
426464 {
427 double x_pos = (x - geom->x_min) * geom->abscissa_scale + geom->data_left;
428 double y_pos = (y - geom->y_min) * geom->ordinate_scale + geom->data_bottom;
465 double x_pos = (x - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale + geom->axis[SCALE_ABSCISSA].data_min;
466 double y_pos = (y - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale + geom->axis[SCALE_ORDINATE].data_min;
429467
430468 xrchart_draw_marker (cr, x_pos, y_pos, XRMARKER_SQUARE, 15);
431469 }
443481 xrchart_vector (cairo_t *cr, struct xrchart_geometry *geom, double x, double y)
444482 {
445483 const double x_pos =
446 (x - geom->x_min) * geom->abscissa_scale + geom->data_left ;
484 (x - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale + geom->axis[SCALE_ABSCISSA].data_min ;
447485
448486 const double y_pos =
449 (y - geom->y_min) * geom->ordinate_scale + geom->data_bottom ;
487 (y - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale + geom->axis[SCALE_ORDINATE].data_min ;
450488
451489 if (geom->in_path)
452490 cairo_line_to (cr, x_pos, y_pos);
487525 y2 = slope * x2 + intercept;
488526 }
489527
490 y1 = (y1 - geom->y_min) * geom->ordinate_scale + geom->data_bottom;
491 y2 = (y2 - geom->y_min) * geom->ordinate_scale + geom->data_bottom;
492 x1 = (x1 - geom->x_min) * geom->abscissa_scale + geom->data_left;
493 x2 = (x2 - geom->x_min) * geom->abscissa_scale + geom->data_left;
528 y1 = (y1 - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale + geom->axis[SCALE_ORDINATE].data_min;
529 y2 = (y2 - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale + geom->axis[SCALE_ORDINATE].data_min;
530 x1 = (x1 - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale + geom->axis[SCALE_ABSCISSA].data_min;
531 x2 = (x2 - geom->axis[SCALE_ABSCISSA].min) * geom->axis[SCALE_ABSCISSA].scale + geom->axis[SCALE_ABSCISSA].data_min;
494532
495533 cairo_move_to (cr, x1, y1);
496534 cairo_line_to (cr, x2, y2);
3030 uint8_t blue;
3131 };
3232
33 struct xrchart_axis
34 {
35 int data_max;
36 int data_min;
37
38 double scale;
39 double min;
40 double max;
41 };
42
3343 /* The geometry of a chart. */
3444 struct xrchart_geometry
3545 {
36 int data_top;
37 int data_right;
38 int data_bottom;
39 int data_left;
46 /* Bottom of the abscissa segment */
47 int abscissa_bottom;
4048
41 int abscissa_top;
42
43 int ordinate_right;
49 /* Left of the ordinate segment */
50 int ordinate_left;
4451
4552 int title_bottom;
4653
5663 struct xrchart_colour fill_colour;
5764
5865 /* Stuff particular to cartesians and boxplots. */
59 double ordinate_scale;
60 double abscissa_scale;
61 double x_min;
62 double x_max;
63 double y_min;
64 double y_max;
66 struct xrchart_axis axis[2];
67
68 /* True iff a path is currently being drawn */
6569 bool in_path;
6670 };
6771
7478
7579 enum tick_orientation
7680 {
77 TICK_ABSCISSA=0,
78 TICK_ORDINATE
81 SCALE_ABSCISSA=0,
82 SCALE_ORDINATE
7983 };
8084
8185 enum xrmarker_type
9195 void xrchart_label (cairo_t *, int horz_justify, int vert_justify,
9296 double font_size, const char *);
9397
98 void xrchart_label_rotate (cairo_t *cr, int horz_justify, int vert_justify,
99 double font_size, const char *string, double angle);
100
101
94102 /* Draw a tick mark at position
95103 If label is non zero, then print it at the tick mark
96104 */
97105 void draw_tick (cairo_t *, const struct xrchart_geometry *,
98 enum tick_orientation orientation, double position,
106 enum tick_orientation orientation,
107 bool rotated,
108 double position,
99109 const char *label, ...)
100 PRINTF_FORMAT (5, 6);
110 PRINTF_FORMAT (6, 7);
101111
102112
103113 /* Write the title on a chart*/
160170 struct xrchart_geometry *);
161171 void xrchart_draw_scree (const struct chart_item *, cairo_t *,
162172 struct xrchart_geometry *);
173 void xrchart_draw_spreadlevel (const struct chart_item *, cairo_t *,
174 struct xrchart_geometry *);
175
163176
164177 #endif /* output/cairo-chart.h */
3131 #include "output/charts/piechart.h"
3232 #include "output/charts/plot-hist.h"
3333 #include "output/charts/roc-chart.h"
34 #include "output/charts/spreadlevel-plot.h"
3435 #include "output/charts/scree.h"
3536 #include "output/driver-provider.h"
3637 #include "output/message-item.h"
10901091 xrchart_draw_roc (chart_item, cr, &geom);
10911092 else if (is_scree (chart_item))
10921093 xrchart_draw_scree (chart_item, cr, &geom);
1094 else if (is_spreadlevel_plot_chart (chart_item))
1095 xrchart_draw_spreadlevel (chart_item, cr, &geom);
10931096 else
10941097 NOT_REACHED ();
10951098 xrchart_geometry_free (cr, &geom);
3030 draw_case (cairo_t *cr, const struct xrchart_geometry *geom, double centreline,
3131 const struct outlier *outlier)
3232 {
33 double y = geom->data_bottom + (outlier->value - geom->y_min) * geom->ordinate_scale;
33 double y = geom->axis[SCALE_ORDINATE].data_min + (outlier->value - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
3434 xrchart_draw_marker (cr, centreline, y,
3535 outlier->extreme ? XRMARKER_ASTERISK : XRMARKER_CIRCLE,
3636 20);
6464 box_whisker_whiskers (bw, whisker);
6565 box_whisker_hinges (bw, hinge);
6666
67 box_bottom = geom->data_bottom + (hinge[0] - geom->y_min ) * geom->ordinate_scale;
67 box_bottom = geom->axis[SCALE_ORDINATE].data_min + (hinge[0] - geom->axis[SCALE_ORDINATE].min ) * geom->axis[SCALE_ORDINATE].scale;
6868
69 box_top = geom->data_bottom + (hinge[2] - geom->y_min ) * geom->ordinate_scale;
69 box_top = geom->axis[SCALE_ORDINATE].data_min + (hinge[2] - geom->axis[SCALE_ORDINATE].min ) * geom->axis[SCALE_ORDINATE].scale;
7070
71 bottom_whisker = geom->data_bottom + (whisker[0] - geom->y_min) *
72 geom->ordinate_scale;
71 bottom_whisker = geom->axis[SCALE_ORDINATE].data_min + (whisker[0] - geom->axis[SCALE_ORDINATE].min) *
72 geom->axis[SCALE_ORDINATE].scale;
7373
74 top_whisker = geom->data_bottom + (whisker[1] - geom->y_min) * geom->ordinate_scale;
74 top_whisker = geom->axis[SCALE_ORDINATE].data_min + (whisker[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale;
7575
7676 /* Draw the box */
7777 cairo_rectangle (cr,
9393 cairo_set_line_width (cr, cairo_get_line_width (cr) * 5);
9494 cairo_move_to (cr,
9595 box_left,
96 geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale);
96 geom->axis[SCALE_ORDINATE].data_min + (hinge[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale);
9797 cairo_line_to (cr,
9898 box_right,
99 geom->data_bottom + (hinge[1] - geom->y_min) * geom->ordinate_scale);
99 geom->axis[SCALE_ORDINATE].data_min + (hinge[1] - geom->axis[SCALE_ORDINATE].min) * geom->axis[SCALE_ORDINATE].scale);
100100 cairo_stroke (cr);
101101 cairo_restore (cr);
102102
130130 }
131131
132132 /* Draw tick mark on x axis */
133 draw_tick(cr, geom, TICK_ABSCISSA, box_centre - geom->data_left, "%s", name);
134 }
135
136 static void
137 boxplot_draw_yscale (cairo_t *cr, struct xrchart_geometry *geom,
138 double y_max, double y_min)
139 {
140 double y_tick;
141 double d;
142
143 geom->y_max = y_max;
144 geom->y_min = y_min;
145
146 y_tick = chart_rounded_tick (fabs (geom->y_max - geom->y_min) / 5.0);
147
148 geom->y_min = (ceil (geom->y_min / y_tick) - 1.0) * y_tick;
149
150 geom->y_max = (floor (geom->y_max / y_tick) + 1.0) * y_tick;
151
152 geom->ordinate_scale = (fabs (geom->data_top - geom->data_bottom)
153 / fabs (geom->y_max - geom->y_min));
154
155 for (d = geom->y_min; d <= geom->y_max; d += y_tick)
156 draw_tick (cr, geom, TICK_ORDINATE,
157 (d - geom->y_min) * geom->ordinate_scale, "%g", d);
133 draw_tick (cr, geom, SCALE_ABSCISSA, false,
134 box_centre - geom->axis[SCALE_ABSCISSA].data_min, "%s", name);
158135 }
159136
160137 void
165142 double box_width;
166143 size_t i;
167144
168 boxplot_draw_yscale (cr, geom, boxplot->y_max, boxplot->y_min);
145 xrchart_write_yscale (cr, geom, boxplot->y_min, boxplot->y_max, 5);
169146 xrchart_write_title (cr, geom, "%s", chart_item->title);
170147
171 box_width = (geom->data_right - geom->data_left) / boxplot->n_boxes / 2.0;
148 box_width = (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / boxplot->n_boxes / 2.0;
172149 for (i = 0; i < boxplot->n_boxes; i++)
173150 {
174151 const struct boxplot_box *box = &boxplot->boxes[i];
175 const double box_centre = (i * 2 + 1) * box_width + geom->data_left;
152 const double box_centre = (i * 2 + 1) * box_width + geom->axis[SCALE_ABSCISSA].data_min;
176153 boxplot_draw_box (cr, geom, box_centre, box_width, box->bw, box->label);
177154 }
178155 }
5656 double angle;
5757 int i;
5858
59 centre_x = (geom->data_right + geom->data_left) / 2.0 ;
60 centre_y = (geom->data_top + geom->data_bottom) / 2.0 ;
59 centre_x = (geom->axis[SCALE_ABSCISSA].data_max + geom->axis[SCALE_ORDINATE].data_min) / 2.0 ;
60 centre_y = (geom->axis[SCALE_ORDINATE].data_max + geom->axis[SCALE_ORDINATE].data_min) / 2.0 ;
6161
62 left_label = geom->data_left + (geom->data_right - geom->data_left)/10.0;
63 right_label = geom->data_right - (geom->data_right - geom->data_left)/10.0;
62 left_label = geom->axis[SCALE_ORDINATE].data_min + (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ORDINATE].data_min)/10.0;
63 right_label = geom->axis[SCALE_ABSCISSA].data_max - (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ORDINATE].data_min)/10.0;
6464
65 radius = MIN (5.0 / 12.0 * (geom->data_top - geom->data_bottom),
66 1.0 / 4.0 * (geom->data_right - geom->data_left));
65 radius = MIN (5.0 / 12.0 * (geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min),
66 1.0 / 4.0 * (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ORDINATE].data_min));
6767
68 radius = MIN (5.0 / 12.0 * (geom->data_top - geom->data_bottom),
69 1.0 / 4.0 * (geom->data_right - geom->data_left));
68 radius = MIN (5.0 / 12.0 * (geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min),
69 1.0 / 4.0 * (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ORDINATE].data_min));
7070
7171 xrchart_write_title (cr, geom, "%s", chart_item_get_title (chart_item));
7272
3232 histogram_write_legend (cairo_t *cr, const struct xrchart_geometry *geom,
3333 double n, double mean, double stddev)
3434 {
35 double y = geom->data_bottom;
35 double y = geom->axis[SCALE_ORDINATE].data_min;
3636 cairo_save (cr);
3737
3838 if (n != SYSMIS)
3939 {
40 char *buf = xasprintf ("N = %.2f", n);
40 char *buf = xasprintf (_("N = %.2f"), n);
4141 cairo_move_to (cr, geom->legend_left, y);
4242 xrchart_label (cr, 'l', 'b', geom->font_size, buf);
4343 y += geom->font_size * 1.5;
4646
4747 if (mean != SYSMIS)
4848 {
49 char *buf = xasprintf ("Mean = %.1f", mean);
49 char *buf = xasprintf (_("Mean = %.1f"), mean);
5050 cairo_move_to (cr,geom->legend_left, y);
5151 xrchart_label (cr, 'l', 'b', geom->font_size, buf);
5252 y += geom->font_size * 1.5;
5555
5656 if (stddev != SYSMIS)
5757 {
58 char *buf = xasprintf ("Std. Dev = %.2f", stddev);
58 char *buf = xasprintf (_("Std. Dev = %.2f"), stddev);
5959 cairo_move_to (cr, geom->legend_left, y);
6060 xrchart_label (cr, 'l', 'b', geom->font_size, buf);
6161 free (buf);
6666
6767 static void
6868 hist_draw_bar (cairo_t *cr, const struct xrchart_geometry *geom,
69 const gsl_histogram *h, int bar)
69 const gsl_histogram *h, int bar, bool label)
7070 {
7171 double upper;
7272 double lower;
7373 double height;
7474
7575 const size_t bins = gsl_histogram_bins (h);
76 const double x_pos = (geom->data_right - geom->data_left) * bar / (double) bins ;
77 const double width = (geom->data_right - geom->data_left) / (double) bins ;
76
77 const double x_pos =
78 (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) *
79 bar / (double) bins ;
80
81 const double width =
82 (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / (double) bins ;
7883
7984 assert ( 0 == gsl_histogram_get_range (h, bar, &lower, &upper));
8085
8186 assert ( upper >= lower);
8287
83 height = gsl_histogram_get (h, bar) *
84 (geom->data_top - geom->data_bottom) / gsl_histogram_max_val (h);
88 height = geom->axis[SCALE_ORDINATE].scale * gsl_histogram_get (h, bar);
8589
86 cairo_rectangle (cr, geom->data_left + x_pos, geom->data_bottom,
90 cairo_rectangle (cr,
91 geom->axis[SCALE_ABSCISSA].data_min + x_pos,
92 geom->axis[SCALE_ORDINATE].data_min,
8793 width, height);
8894 cairo_save (cr);
8995 cairo_set_source_rgb (cr,
94100 cairo_restore (cr);
95101 cairo_stroke (cr);
96102
97 draw_tick (cr, geom, TICK_ABSCISSA,
98 x_pos + width / 2.0, "%g", (upper + lower) / 2.0);
103 if (label)
104 draw_tick (cr, geom, SCALE_ABSCISSA, bins > 10,
105 x_pos + width / 2.0, "%g", (upper + lower) / 2.0);
99106 }
100107
101108 void
122129 xrchart_write_yscale (cr, geom, 0, gsl_histogram_max_val (h->gsl_hist), 5);
123130
124131 for (i = 0; i < bins; i++)
125 hist_draw_bar (cr, geom, h->gsl_hist, i);
132 {
133 hist_draw_bar (cr, geom, h->gsl_hist, i, true);
134 }
126135
127136 histogram_write_legend (cr, geom, h->n, h->mean, h->stddev);
128137
140149 range = not_used - x_min;
141150 gsl_histogram_get_range (h->gsl_hist, bins - 1, &not_used, &x_max);
142151
143 abscissa_scale = (geom->data_right - geom->data_left) / (x_max - x_min);
144 ordinate_scale = (geom->data_top - geom->data_bottom) /
152 abscissa_scale = (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / (x_max - x_min);
153 ordinate_scale = (geom->axis[SCALE_ORDINATE].data_max - geom->axis[SCALE_ORDINATE].data_min) /
145154 gsl_histogram_max_val (h->gsl_hist);
146155
147 cairo_move_to (cr, geom->data_left, geom->data_bottom);
148 for (d = geom->data_left;
149 d <= geom->data_right;
150 d += (geom->data_right - geom->data_left) / 100.0)
156 cairo_move_to (cr, geom->axis[SCALE_ABSCISSA].data_min, geom->axis[SCALE_ORDINATE].data_min);
157 for (d = geom->axis[SCALE_ABSCISSA].data_min;
158 d <= geom->axis[SCALE_ABSCISSA].data_max;
159 d += (geom->axis[SCALE_ABSCISSA].data_max - geom->axis[SCALE_ABSCISSA].data_min) / 100.0)
151160 {
152 const double x = (d - geom->data_left) / abscissa_scale + x_min;
161 const double x = (d - geom->axis[SCALE_ABSCISSA].data_min) / abscissa_scale + x_min;
153162 const double y = h->n * range *
154163 gsl_ran_gaussian_pdf (x - h->mean, h->stddev);
155164
156 cairo_line_to (cr, d, geom->data_bottom + y * ordinate_scale);
165 cairo_line_to (cr, d, geom->axis[SCALE_ORDINATE].data_min + y * ordinate_scale);
157166
158167 }
159168 cairo_stroke (cr);
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "output/charts/spreadlevel-plot.h"
19
20 #include <math.h>
21
22 #include "output/cairo-chart.h"
23
24 #include "gettext.h"
25 #define _(msgid) gettext (msgid)
26
27 void
28 xrchart_draw_spreadlevel (const struct chart_item *chart_item, cairo_t *cr,
29 struct xrchart_geometry *geom)
30 {
31 const struct spreadlevel_plot_chart *sl = to_spreadlevel_plot_chart (chart_item);
32 size_t i;
33
34 const char *name = chart_item_get_title (chart_item);
35
36 xrchart_write_title (cr, geom, _("Spread vs. Level Plot of %s"), name);
37 xrchart_write_xlabel (cr, geom, _("Level"));
38 xrchart_write_ylabel (cr, geom, _("Spread"));
39
40
41 xrchart_write_xscale (cr, geom, sl->x_lower, sl->x_upper, 5);
42 xrchart_write_yscale (cr, geom, sl->y_lower, sl->y_upper, 5);
43
44 for (i = 0 ; i < sl->n_data; ++i)
45 {
46 xrchart_datum (cr, geom, 0, sl->data[i].x, sl->data[i].y);
47 }
48 }
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "output/charts/spreadlevel-plot.h"
19
20 #include "libpspp/cast.h"
21 #include "output/chart-item-provider.h"
22
23 #include "gl/xalloc.h"
24 #include "gl/minmax.h"
25
26 #include <math.h>
27 #include <float.h>
28 #include <stdlib.h>
29
30 struct chart_item *
31 spreadlevel_plot_create (const char *label, double tx_pwr)
32 {
33 struct spreadlevel_plot_chart *sl = xzalloc (sizeof *sl);
34 chart_item_init (&sl->chart_item, &spreadlevel_plot_chart_class, label);
35
36 sl->x_lower = DBL_MAX;
37 sl->x_upper = -DBL_MAX;
38
39 sl->y_lower = DBL_MAX;
40 sl->y_upper = -DBL_MAX;
41
42 sl->tx_pwr = tx_pwr;
43
44 sl->n_data = 0;
45 sl->data = NULL;
46
47 return &sl->chart_item;
48 }
49
50 void
51 spreadlevel_plot_add (struct chart_item *ci, double spread, double level)
52 {
53 struct spreadlevel_plot_chart *sl = to_spreadlevel_plot_chart (ci);
54
55 if ( sl->tx_pwr == 0)
56 {
57 spread = log (spread);
58 level = log (level);
59 }
60 else
61 {
62 spread = pow (spread, sl->tx_pwr);
63 level = pow (level, sl->tx_pwr);
64 }
65
66 sl->x_lower = MIN (sl->x_lower, level);
67 sl->x_upper = MAX (sl->x_upper, level);
68
69 sl->y_lower = MIN (sl->y_lower, spread);
70 sl->y_upper = MAX (sl->y_upper, spread);
71
72 sl->n_data++;
73 sl->data = xrealloc (sl->data, sizeof (*sl->data) * sl->n_data);
74 sl->data[sl->n_data - 1].x = level;
75 sl->data[sl->n_data - 1].y = spread;
76 }
77
78
79 static void
80 spreadlevel_plot_chart_destroy (struct chart_item *chart_item)
81 {
82 struct spreadlevel_plot_chart *sl = to_spreadlevel_plot_chart (chart_item);
83
84 free (sl->data);
85 free (sl);
86 }
87
88 const struct chart_item_class spreadlevel_plot_chart_class =
89 {
90 spreadlevel_plot_chart_destroy
91 };
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef OUTPUT_CHARTS_SL_PLOT_H
17 #define OUTPUT_CHARTS_SL_PLOT_H 1
18
19 #include "output/chart-item.h"
20
21 struct datum
22 {
23 double x;
24 double y;
25 };
26
27 struct spreadlevel_plot_chart
28 {
29 struct chart_item chart_item;
30
31 /* Calculated parameters */
32 double y_lower, y_upper;
33 double x_lower, x_upper;
34
35 double tx_pwr;
36
37 size_t n_data;
38 struct datum *data;
39 };
40
41 struct chart_item *spreadlevel_plot_create (const char *label, double slp);
42
43 void spreadlevel_plot_add (struct chart_item *, double spread, double level);
44
45
46
47 /* This boilerplate for spreadlevel_plot_chart, a subclass of chart_item, was
48 autogenerated by mk-class-boilerplate. */
49
50 #include <assert.h>
51 #include "libpspp/cast.h"
52
53 extern const struct chart_item_class spreadlevel_plot_chart_class;
54
55 /* Returns true if SUPER is a spreadlevel_plot_chart, otherwise false. */
56 static inline bool
57 is_spreadlevel_plot_chart (const struct chart_item *super)
58 {
59 return super->class == &spreadlevel_plot_chart_class;
60 }
61
62 /* Returns SUPER converted to spreadlevel_plot_chart. SUPER must be a spreadlevel_plot_chart, as
63 reported by is_spreadlevel_plot_chart. */
64 static inline struct spreadlevel_plot_chart *
65 to_spreadlevel_plot_chart (const struct chart_item *super)
66 {
67 assert (is_spreadlevel_plot_chart (super));
68 return UP_CAST (super, struct spreadlevel_plot_chart, chart_item);
69 }
70
71 /* Returns INSTANCE converted to chart_item. */
72 static inline struct chart_item *
73 spreadlevel_plot_chart_super (const struct spreadlevel_plot_chart *instance)
74 {
75 return CONST_CAST (struct chart_item *, &instance->chart_item);
76 }
77
78 /* Increments INSTANCE's reference count and returns INSTANCE. */
79 static inline struct spreadlevel_plot_chart *
80 spreadlevel_plot_chart_ref (const struct spreadlevel_plot_chart *instance)
81 {
82 return to_spreadlevel_plot_chart (chart_item_ref (&instance->chart_item));
83 }
84
85 /* Decrements INSTANCE's reference count, then destroys INSTANCE if
86 the reference count is now zero. */
87 static inline void
88 spreadlevel_plot_chart_unref (struct spreadlevel_plot_chart *instance)
89 {
90 chart_item_unref (&instance->chart_item);
91 }
92
93 /* Returns true if INSTANCE's reference count is greater than 1,
94 false otherwise. */
95 static inline bool
96 spreadlevel_plot_chart_is_shared (const struct spreadlevel_plot_chart *instance)
97 {
98 return chart_item_is_shared (&instance->chart_item);
99 }
100
101 static inline void
102 spreadlevel_plot_chart_submit (struct spreadlevel_plot_chart *instance)
103 {
104 chart_item_submit (&instance->chart_item);
105 }
106
107 #endif
225225 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (cb), renderer, "text", 0);
226226
227227 gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (list));
228 g_object_unref (list);
228229 }
229230
230231
526527 G_TYPE_DOUBLE);
527528
528529 psppire_acr_set_model (PSPPIRE_ACR (fd.summary_acr), list);
530 g_object_unref (list);
529531
530532 psppire_acr_set_get_value_func (PSPPIRE_ACR (fd.summary_acr),
531533 get_summary_spec, &fd);
1717 src/ui/gui/factor.ui \
1818 src/ui/gui/find.ui \
1919 src/ui/gui/frequencies.ui \
20 src/ui/gui/indep-samples.ui \
2021 src/ui/gui/k-means.ui \
2122 src/ui/gui/k-related.ui \
2223 src/ui/gui/ks-one-sample.ui \
7374 src/libpspp.la \
7475 src/libpspp-core.la \
7576 $(GTK_LIBS) \
77 $(GTHREAD_LIBS) \
7678 $(GTKSOURCEVIEW_LIBS) \
7779 $(CAIRO_LIBS) \
7880 $(LIBINTL) \
128130 $(top_srcdir)/src/ui/gui/icons/16x16/scale.png \
129131 $(top_srcdir)/src/ui/gui/icons/16x16/string.png \
130132 $(top_srcdir)/src/ui/gui/icons/16x16/date-scale.png \
131 $(top_srcdir)/src/ui/gui/icons/splash.png
132
133 $(top_srcdir)/src/ui/gui/icons/splash.png \
134 $(top_srcdir)/src/ui/gui/psppire.gtkrc
133135
134136 src_ui_gui_psppire_SOURCES = \
137 src/ui/gui/pspp-sheet-private.h \
138 src/ui/gui/pspp-sheet-selection.c \
139 src/ui/gui/pspp-sheet-selection.h \
140 src/ui/gui/pspp-sheet-view-column.c \
141 src/ui/gui/pspp-sheet-view-column.h \
142 src/ui/gui/pspp-sheet-view.c \
143 src/ui/gui/pspp-sheet-view.h \
144 src/ui/gui/pspp-widget-facade.c \
145 src/ui/gui/pspp-widget-facade.h \
146 src/ui/gui/psppire-button-editable.c \
147 src/ui/gui/psppire-button-editable.h \
148 src/ui/gui/psppire-cell-renderer-button.c \
149 src/ui/gui/psppire-cell-renderer-button.h \
135150 src/ui/gui/psppire-dialog.c \
136151 src/ui/gui/psppire-keypad.c \
137152 src/ui/gui/psppire-selector.c \
169184 src/ui/gui/dict-display.c \
170185 src/ui/gui/entry-dialog.c \
171186 src/ui/gui/entry-dialog.h \
172 src/ui/gui/examine-dialog.c \
173 src/ui/gui/examine-dialog.h \
174187 src/ui/gui/executor.c \
175188 src/ui/gui/executor.h \
176189 src/ui/gui/find-dialog.c \
177190 src/ui/gui/find-dialog.h \
178 src/ui/gui/factor-dialog.c \
179 src/ui/gui/factor-dialog.h \
180191 src/ui/gui/frequencies-dialog.c \
181192 src/ui/gui/frequencies-dialog.h \
182193 src/ui/gui/goto-case-dialog.c \
215226 src/ui/gui/psppire-dialog-action-correlation.h \
216227 src/ui/gui/psppire-dialog-action-descriptives.c \
217228 src/ui/gui/psppire-dialog-action-descriptives.h \
229 src/ui/gui/psppire-dialog-action-examine.c \
230 src/ui/gui/psppire-dialog-action-examine.h \
231 src/ui/gui/psppire-dialog-action-factor.c \
232 src/ui/gui/psppire-dialog-action-factor.h \
233 src/ui/gui/psppire-dialog-action-indep-samps.c \
234 src/ui/gui/psppire-dialog-action-indep-samps.h \
218235 src/ui/gui/psppire-dialog-action-kmeans.c \
219236 src/ui/gui/psppire-dialog-action-kmeans.h \
220237 src/ui/gui/psppire-dialog-action-means.c \
221238 src/ui/gui/psppire-dialog-action-means.h \
239 src/ui/gui/psppire-dialog-action-rank.c \
240 src/ui/gui/psppire-dialog-action-rank.h \
241 src/ui/gui/psppire-dialog-action-regression.c \
242 src/ui/gui/psppire-dialog-action-regression.h \
222243 src/ui/gui/psppire-dialog-action-reliability.c \
223244 src/ui/gui/psppire-dialog-action-reliability.h \
245 src/ui/gui/psppire-dialog-action-roc.c \
246 src/ui/gui/psppire-dialog-action-roc.h \
224247 src/ui/gui/psppire-dialog-action-sort.c \
225248 src/ui/gui/psppire-dialog-action-sort.h \
226249 src/ui/gui/psppire-dialog-action-var-info.c \
227250 src/ui/gui/psppire-dialog-action-var-info.h \
228 src/ui/gui/psppire-dialog-action-roc.c \
229 src/ui/gui/psppire-dialog-action-roc.h \
230251 src/ui/gui/psppire-dict.c \
231252 src/ui/gui/psppire-dict.h \
232253 src/ui/gui/psppire-dictview.c \
233254 src/ui/gui/psppire-dictview.h \
255 src/ui/gui/psppire-empty-list-store.c \
256 src/ui/gui/psppire-empty-list-store.h \
234257 src/ui/gui/psppire-encoding-selector.c \
235258 src/ui/gui/psppire-encoding-selector.h \
259 src/ui/gui/psppire-format.c \
260 src/ui/gui/psppire-format.h \
236261 src/ui/gui/psppire-hbuttonbox.h \
237262 src/ui/gui/psppire-keypad.h \
238263 src/ui/gui/psppire-lex-reader.c \
250275 src/ui/gui/psppire-syntax-window.h \
251276 src/ui/gui/psppire-val-chooser.c \
252277 src/ui/gui/psppire-val-chooser.h \
278 src/ui/gui/psppire-value-entry.c \
279 src/ui/gui/psppire-value-entry.h \
253280 src/ui/gui/psppire-var-ptr.c \
254281 src/ui/gui/psppire-var-ptr.h \
255282 src/ui/gui/psppire-var-sheet.c \
263290 src/ui/gui/psppire-window-base.h \
264291 src/ui/gui/psppire-window-register.c \
265292 src/ui/gui/psppire-window-register.h \
266 src/ui/gui/rank-dialog.c \
267 src/ui/gui/rank-dialog.h \
268293 src/ui/gui/recode-dialog.c \
269294 src/ui/gui/recode-dialog.h \
270 src/ui/gui/regression-dialog.c \
271 src/ui/gui/regression-dialog.h \
272295 src/ui/gui/runs-dialog.c \
273296 src/ui/gui/runs-dialog.h \
274297 src/ui/gui/select-cases-dialog.c \
279302 src/ui/gui/text-data-import-dialog.h \
280303 src/ui/gui/transpose-dialog.c \
281304 src/ui/gui/transpose-dialog.h \
282 src/ui/gui/t-test-independent-samples-dialog.c \
283 src/ui/gui/t-test-independent-samples-dialog.h \
284305 src/ui/gui/t-test-one-sample.c \
285306 src/ui/gui/t-test-one-sample.h \
286307 src/ui/gui/t-test-options.c \
362383 mv $@-t $@
363384 CLEANFILES += src/ui/gui/include/gtk/gtk.h
364385 EXTRA_DIST += src/ui/gui/include/gtk/gtk.in.h
386
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007 Free Software Foundation
1 Copyright (C) 2007, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
5454
5555 list = gtk_list_store_new (N_CHECKBOX_COLUMNS,
5656 G_TYPE_STRING, G_TYPE_BOOLEAN);
57 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (list));
5857
5958 for (i = 0; i < n_items; i++)
6059 {
6665 (default_items & (1u << i)) != 0,
6766 -1);
6867 }
68
69 gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (list));
70 g_object_unref (list);
6971 }
7072
7173 static void
236236 break;
237237 }
238238
239 g_object_unref (csd.expected_list);
239240 g_object_unref (xml);
240241 }
501501 }
502502
503503 gtk_tree_view_set_model (tv, GTK_TREE_MODEL (liststore));
504 g_object_unref (liststore);
504505 }
505506
506507
164164 }
165165
166166
167 g_object_unref (cnt.value_list);
167168 g_object_unref (builder);
168169 }
169170
3636 #define N_(msgid) msgid
3737
3838
39 #define CROSSTABS_STATS \
40 CS (CHISQ, N_("Chisq")) \
41 CS (PHI, N_("Phi")) \
42 CS (CC, N_("CC")) \
43 CS (LAMBDA, N_("Lambda")) \
44 CS (UC, N_("UC")) \
45 CS (BTAU, N_("BTau")) \
46 CS (CTAU, N_("CTau")) \
47 CS (RISK, N_("Risk")) \
39 #define CROSSTABS_STATS \
40 CS (CHISQ, N_("Chisq")) \
41 CS (PHI, N_("Phi")) \
42 CS (CC, N_("CC")) \
43 CS (LAMBDA, N_("Lambda")) \
44 CS (UC, N_("UC")) \
45 CS (BTAU, N_("BTau")) \
46 CS (CTAU, N_("CTau")) \
47 CS (RISK, N_("Risk")) \
4848 CS (GAMMA, N_("Gamma")) \
49 CS (D, N_("D")) \
50 CS (KAPPA, N_("Kappa")) \
51 CS (ETA, N_("Eta")) \
52 CS (CORR, N_("Corr")) \
49 CS (D, N_("D")) \
50 CS (KAPPA, N_("Kappa")) \
51 CS (ETA, N_("Eta")) \
52 CS (CORR, N_("Corr")) \
5353 CS (STATS_NONE, N_("None"))
5454
55 #define CROSSTABS_CELLS \
56 CS (COUNT, N_("Count")) \
57 CS (ROW, N_("Row")) \
58 CS (COLUMN, N_("Column")) \
59 CS (TOTAL, N_("Total")) \
60 CS (EXPECTED, N_("Expected")) \
61 CS (RESIDUAL, N_("Residual")) \
62 CS (SRESIDUAL, N_("Std. Residual")) \
63 CS (ASRESIDUAL, N_("Adjusted Std. Residual")) \
55 #define CROSSTABS_CELLS \
56 CS (COUNT, N_("Count")) \
57 CS (ROW, N_("Row")) \
58 CS (COLUMN, N_("Column")) \
59 CS (TOTAL, N_("Total")) \
60 CS (EXPECTED, N_("Expected")) \
61 CS (RESIDUAL, N_("Residual")) \
62 CS (SRESIDUAL, N_("Std. Residual")) \
63 CS (ASRESIDUAL, N_("Adjusted Std. Residual")) \
6464 CS (CELLS_NONE, N_("None"))
6565
6666 enum
301301 </object>
302302 </child>
303303 <child>
304 <object class="GtkAction" id="transform_rank">
304 <object class="PsppireDialogActionRank" id="transform_rank">
305305 <property name="name">transform_rank</property>
306 <property name="manager">uimanager1</property>
306307 <property name="label" translatable="yes">Ran_k Cases...</property>
307308 </object>
308309 </child>
357358 </object>
358359 </child>
359360 <child>
360 <object class="GtkAction" id="analyze_explore">
361 <object class="PsppireDialogActionExamine" id="explore">
361362 <property name="name">analyze_explore</property>
363 <property name="manager">uimanager1</property>
362364 <property name="label" translatable="yes">_Explore...</property>
363365 </object>
364366 </child>
388390 </object>
389391 </child>
390392 <child>
391 <object class="GtkAction" id="indep-t-test">
393 <object class="PsppireDialogActionIndepSamps" id="indep-t-test">
392394 <property name="name">indep-t-test</property>
395 <property name="manager">uimanager1</property>
393396 <property name="label" translatable="yes">_Independent Samples T Test...</property>
394397 </object>
395398 </child>
427430 </object>
428431 </child>
429432 <child>
430 <object class="GtkAction" id="factor-analysis">
433 <object class="PsppireDialogActionFactor" id="factor-analysis">
431434 <property name="name">factor-analysis</property>
435 <property name="manager">uimanager1</property>
432436 <property name="label" translatable="yes">Factor _Analysis...</property>
433437 </object>
434438 </child>
440444 </object>
441445 </child>
442446 <child>
443 <object class="GtkAction" id="linear-regression">
447 <object class="PsppireDialogActionRegression" id="linear-regression">
444448 <property name="name">linear-regression</property>
449 <property name="manager">uimanager1</property>
445450 <property name="label" translatable="yes">Linear _Regression...</property>
446451 </object>
447452 </child>
606611 <menu action="descriptive-statistics">
607612 <menuitem action="analyze_frequencies"/>
608613 <menuitem action="analyze_descriptives"/>
609 <menuitem action="analyze_explore"/>
614 <menuitem action="explore"/>
610615 <menuitem action="crosstabs"/>
611616 </menu>
612617 <menu action="compare-means">
+0
-314
src/ui/gui/examine-dialog.c less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "examine-dialog.h"
19 #include "psppire-var-view.h"
20
21 #include <gtk/gtk.h>
22 #include <stdlib.h>
23
24 #include <ui/gui/psppire-data-window.h>
25 #include <ui/gui/dialog-common.h>
26 #include <ui/gui/dict-display.h>
27 #include <ui/gui/builder-wrapper.h>
28 #include <ui/gui/psppire-dialog.h>
29 #include <ui/gui/psppire-var-store.h>
30 #include "executor.h"
31 #include "helper.h"
32
33 #include "gettext.h"
34 #define _(msgid) gettext (msgid)
35 #define N_(msgid) msgid
36
37 enum opts
38 {
39 OPT_LISTWISE,
40 OPT_PAIRWISE,
41 OPT_REPORT
42 };
43
44
45 #define STAT_DESCRIPTIVES 0x01
46 #define STAT_EXTREMES 0x02
47 #define STAT_PERCENTILES 0x04
48
49
50 struct examine_dialog
51 {
52 PsppireDict *dict;
53
54 GtkWidget *dep_list ;
55 GtkWidget *fct_list ;
56 GtkWidget *id_entry ;
57
58 GtkWidget *stats_dialog;
59 GtkWidget *opts_dialog;
60
61 /* Options */
62 enum opts opts;
63 guint stats;
64 GtkWidget *listwise;
65 GtkWidget *pairwise;
66 GtkWidget *report;
67
68 GtkToggleButton *descriptives_button;
69 GtkToggleButton *extremes_button;
70 GtkToggleButton *percentiles_button;
71 };
72
73 static void
74 refresh (PsppireDialog *dialog, struct examine_dialog *ex_d)
75 {
76 GtkTreeModel *liststore =
77 gtk_tree_view_get_model (GTK_TREE_VIEW (ex_d->dep_list));
78
79 gtk_list_store_clear (GTK_LIST_STORE (liststore));
80
81 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (ex_d->fct_list));
82 gtk_list_store_clear (GTK_LIST_STORE (liststore));
83
84
85 gtk_entry_set_text (GTK_ENTRY (ex_d->id_entry), "");
86
87 ex_d->opts = OPT_LISTWISE;
88 ex_d->stats = 0x00;
89 }
90
91 static char *
92 generate_syntax (const struct examine_dialog *ed)
93 {
94 const char *label;
95 gchar *text = NULL;
96 GString *str = g_string_new ("EXAMINE ");
97
98 g_string_append (str, "\n\t/VARIABLES=");
99 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (ed->dep_list), 0, str);
100
101 if ( 0 < gtk_tree_model_iter_n_children
102 (gtk_tree_view_get_model (GTK_TREE_VIEW (ed->fct_list)), NULL))
103 {
104 g_string_append (str, "\n\tBY ");
105 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (ed->fct_list), 0, str);
106 }
107
108 label = gtk_entry_get_text (GTK_ENTRY (ed->id_entry));
109 if ( 0 != strcmp (label, "") )
110 {
111 g_string_append (str, "\n\t/ID = ");
112 g_string_append (str, label);
113 }
114
115 if ( ed->stats & (STAT_DESCRIPTIVES | STAT_EXTREMES))
116 {
117 g_string_append (str, "\n\t/STATISTICS =");
118
119 if ( ed->stats & STAT_DESCRIPTIVES)
120 g_string_append (str, " DESCRIPTIVES");
121
122 if ( ed->stats & STAT_EXTREMES)
123 g_string_append (str, " EXTREME");
124 }
125
126 if ( ed->stats & STAT_PERCENTILES)
127 g_string_append (str, "\n\t/PERCENTILES");
128
129 g_string_append (str, "\n\t/MISSING=");
130 switch (ed->opts)
131 {
132 case OPT_REPORT:
133 g_string_append (str, "REPORT");
134 break;
135 case OPT_PAIRWISE:
136 g_string_append (str, "PAIRWISE");
137 break;
138 default:
139 g_string_append (str, "LISTWISE");
140 break;
141 };
142
143 g_string_append (str, ".");
144
145 text = str->str;
146
147 g_string_free (str, FALSE);
148
149 return text;
150 }
151
152 /* Dialog is valid iff at least one variable has been selected */
153 static gboolean
154 dialog_state_valid (gpointer data)
155 {
156 struct examine_dialog *ex_d = data;
157
158 GtkTreeModel *vars =
159 gtk_tree_view_get_model (GTK_TREE_VIEW (ex_d->dep_list));
160
161 GtkTreeIter notused;
162
163 return gtk_tree_model_get_iter_first (vars, &notused);
164 }
165
166
167 static void
168 run_stats_dialog (struct examine_dialog *ed)
169 {
170 gint response;
171
172 gtk_toggle_button_set_active (ed->descriptives_button,
173 ed->stats & STAT_DESCRIPTIVES);
174
175 gtk_toggle_button_set_active (ed->extremes_button,
176 ed->stats & STAT_EXTREMES);
177
178 gtk_toggle_button_set_active (ed->percentiles_button,
179 ed->stats & STAT_PERCENTILES);
180
181 response = psppire_dialog_run (PSPPIRE_DIALOG (ed->stats_dialog));
182
183 if ( response == PSPPIRE_RESPONSE_CONTINUE )
184 {
185 ed->stats = 0;
186 if ( gtk_toggle_button_get_active (ed->descriptives_button) )
187 ed->stats |= STAT_DESCRIPTIVES;
188
189 if ( gtk_toggle_button_get_active (ed->extremes_button) )
190 ed->stats |= STAT_EXTREMES;
191
192 if ( gtk_toggle_button_get_active (ed->percentiles_button) )
193 ed->stats |= STAT_PERCENTILES;
194 }
195 }
196
197 static void
198 run_opts_dialog (struct examine_dialog *ed)
199 {
200 gint response;
201
202
203 switch (ed->opts)
204 {
205 case OPT_LISTWISE:
206 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->listwise), TRUE);
207 break;
208 case OPT_PAIRWISE:
209 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->pairwise), TRUE);
210 break;
211 case OPT_REPORT:
212 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->report), TRUE);
213 break;
214 default:
215 g_assert_not_reached ();
216 break;
217 };
218
219 response = psppire_dialog_run (PSPPIRE_DIALOG (ed->opts_dialog));
220
221 if ( response == PSPPIRE_RESPONSE_CONTINUE )
222 {
223 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->listwise)))
224 ed->opts = OPT_LISTWISE;
225 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->pairwise)))
226 ed->opts = OPT_PAIRWISE;
227 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->report)))
228 ed->opts = OPT_REPORT;
229 }
230 }
231
232
233
234 /* Pops up the Examine dialog box */
235 void
236 examine_dialog (PsppireDataWindow *de)
237 {
238 gint response;
239
240 struct examine_dialog ex_d;
241
242 GtkBuilder *xml = builder_new ("examine.ui");
243
244 GtkWidget *dialog = get_widget_assert (xml, "examine-dialog");
245 GtkWidget *source = get_widget_assert (xml, "treeview1");
246
247 GtkWidget *stats_button = get_widget_assert (xml, "stats-button");
248 GtkWidget *opts_button = get_widget_assert (xml, "opts-button");
249
250
251 GtkWidget *dep_selector = get_widget_assert (xml, "psppire-selector1");
252
253 PsppireVarStore *vs = NULL;
254
255 g_object_get (de->data_editor, "var-store", &vs, NULL);
256
257 ex_d.dep_list = get_widget_assert (xml, "treeview2");
258 ex_d.fct_list = get_widget_assert (xml, "treeview3");
259 ex_d.id_entry = get_widget_assert (xml, "entry1");
260 ex_d.stats_dialog = get_widget_assert (xml, "statistics-dialog");
261 ex_d.opts_dialog = get_widget_assert (xml, "options-dialog");
262 ex_d.listwise = get_widget_assert (xml, "radiobutton1");
263 ex_d.pairwise = get_widget_assert (xml, "radiobutton2");
264 ex_d.report = get_widget_assert (xml, "radiobutton3");
265
266 ex_d.descriptives_button = GTK_TOGGLE_BUTTON
267 (get_widget_assert (xml, "descriptives-button"));
268
269 ex_d.extremes_button = GTK_TOGGLE_BUTTON
270 (get_widget_assert (xml, "extremes-button"));
271
272 ex_d.percentiles_button = GTK_TOGGLE_BUTTON
273 (get_widget_assert (xml, "percentiles-button"));
274
275 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
276 gtk_window_set_transient_for (GTK_WINDOW (ex_d.stats_dialog), GTK_WINDOW (de));
277 gtk_window_set_transient_for (GTK_WINDOW (ex_d.opts_dialog), GTK_WINDOW (de));
278
279 g_object_get (vs, "dictionary", &ex_d.dict, NULL);
280 g_object_set (source, "model", ex_d.dict, NULL);
281
282 psppire_selector_set_allow (PSPPIRE_SELECTOR (dep_selector),
283 numeric_only);
284
285 g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &ex_d);
286
287 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
288 dialog_state_valid, &ex_d);
289
290
291 g_signal_connect_swapped (stats_button, "clicked",
292 G_CALLBACK (run_stats_dialog), &ex_d);
293
294 g_signal_connect_swapped (opts_button, "clicked",
295 G_CALLBACK (run_opts_dialog), &ex_d);
296
297 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
298
299
300 switch (response)
301 {
302 case GTK_RESPONSE_OK:
303 g_free (execute_syntax_string (de, generate_syntax (&ex_d)));
304 break;
305 case PSPPIRE_RESPONSE_PASTE:
306 g_free (paste_syntax_to_window (generate_syntax (&ex_d)));
307 break;
308 default:
309 break;
310 }
311
312 g_object_unref (xml);
313 }
+0
-24
src/ui/gui/examine-dialog.h less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2010 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef __EXAMINE_DIALOG_H
17 #define __EXAMINE_DIALOG_H
18
19 #include "psppire-data-window.h"
20
21 void examine_dialog (PsppireDataWindow * data);
22
23 #endif
430430 </child>
431431 <child>
432432 <object class="GtkRadioButton" id="radiobutton3">
433 <property name="label" translatable="yes">Repeat values</property>
433 <property name="label" translatable="yes">Report values</property>
434434 <property name="visible">True</property>
435435 <property name="can_focus">True</property>
436436 <property name="receives_default">False</property>
+0
-500
src/ui/gui/factor-dialog.c less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "dialog-common.h"
19 #include <ui/syntax-gen.h>
20 #include <libpspp/str.h>
21
22 #include "factor-dialog.h"
23 #include "psppire-selector.h"
24 #include "psppire-dictview.h"
25 #include "psppire-dialog.h"
26
27 #include "psppire-data-window.h"
28 #include "psppire-var-view.h"
29
30 #include "psppire-scanf.h"
31
32 #include "executor.h"
33 #include "helper.h"
34 #include "builder-wrapper.h"
35
36 #include <gtk/gtk.h>
37
38 #include "gettext.h"
39 #define _(msgid) gettext (msgid)
40 #define N_(msgid) msgid
41
42
43 struct extraction_parameters
44 {
45 gdouble mineigen;
46 gint n_factors;
47 gint n_iterations;
48
49 gboolean explicit_nfactors;
50 gboolean covariance;
51
52 gboolean scree;
53 gboolean unrotated;
54
55 gboolean paf;
56 };
57
58 enum rotation_type {
59 ROT_NONE,
60 ROT_VARIMAX,
61 ROT_QUARTIMAX,
62 ROT_EQUIMAX
63 };
64
65 static const char *rot_method_syntax[] =
66 {
67 "NOROTATE",
68 "VARIMAX",
69 "QUARTIMAX",
70 "EQUAMAX"
71 };
72
73 struct rotation_parameters
74 {
75 gboolean rotated_solution;
76 gint iterations;
77
78 enum rotation_type method;
79 };
80
81
82
83 static const struct extraction_parameters default_extraction_parameters = {1.0, 0, 25, FALSE, TRUE, FALSE, TRUE, FALSE};
84
85 static const struct rotation_parameters default_rotation_parameters = {TRUE, 25, ROT_VARIMAX};
86
87 struct factor
88 {
89 GtkBuilder *xml;
90 PsppireDict *dict;
91
92 GtkWidget *variables;
93 PsppireDataWindow *de ;
94
95 /* The Extraction subdialog */
96 GtkWidget *extraction_dialog;
97 GtkWidget *rotation_dialog;
98
99 GtkWidget *n_factors;
100 GtkWidget *mineigen;
101 GtkWidget *extract_iterations;
102
103 GtkWidget *nfactors_toggle;
104 GtkWidget *mineigen_toggle;
105
106 GtkWidget *covariance_toggle;
107 GtkWidget *correlation_toggle;
108
109 GtkWidget *scree_button;
110 GtkWidget *unrotated_button;
111
112 GtkWidget *extraction_combo;
113
114
115 /* Rotation Widgets */
116 GtkWidget *rotate_iterations;
117 GtkWidget *display_rotated_solution;
118 GtkWidget *rotation_none;
119 GtkWidget *rotation_varimax;
120 GtkWidget *rotation_quartimax;
121 GtkWidget *rotation_equimax;
122
123
124 struct extraction_parameters extraction;
125 struct rotation_parameters rotation;
126 };
127
128 static void
129 load_rotation_parameters (struct factor *fd, const struct rotation_parameters *p)
130 {
131 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution),
132 p->rotated_solution);
133
134 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->rotate_iterations),
135 p->iterations);
136
137 switch (p->method)
138 {
139 case ROT_NONE:
140 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_none), TRUE);
141 break;
142 case ROT_VARIMAX:
143 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax), TRUE);
144 break;
145 case ROT_QUARTIMAX:
146 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax), TRUE);
147 break;
148 case ROT_EQUIMAX:
149 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax), TRUE);
150 break;
151 default:
152 g_assert_not_reached ();
153 break;
154 }
155 }
156
157 static void
158 load_extraction_parameters (struct factor *fd, const struct extraction_parameters *p)
159 {
160 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->mineigen), p->mineigen);
161 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->n_factors), p->n_factors);
162
163 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->extract_iterations), p->n_iterations);
164
165
166 if (p->explicit_nfactors)
167 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle), TRUE);
168 else
169 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->mineigen_toggle), TRUE);
170
171 if (p->covariance)
172 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle), TRUE);
173 else
174 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->correlation_toggle), TRUE);
175
176
177 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->scree_button), p->scree);
178 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->unrotated_button), p->unrotated);
179
180 if ( p->paf )
181 gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 1);
182 else
183 gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 0);
184
185 }
186
187 static void
188 set_rotation_parameters (const struct factor *fd, struct rotation_parameters *p)
189 {
190 p->iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->rotate_iterations));
191 p->rotated_solution = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution));
192
193
194 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_none)))
195 p->method = ROT_NONE;
196
197 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax)))
198 p->method = ROT_VARIMAX;
199
200 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax)))
201 p->method = ROT_QUARTIMAX;
202
203 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax)))
204 p->method = ROT_EQUIMAX;
205 }
206
207 static void
208 set_extraction_parameters (const struct factor *fd, struct extraction_parameters *p)
209 {
210 p->mineigen = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->mineigen));
211 p->n_factors = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->n_factors));
212 p->n_iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (fd->extract_iterations));
213
214 p->explicit_nfactors = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle));
215 p->covariance = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle));
216
217 p->scree = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->scree_button));
218 p->unrotated = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fd->unrotated_button));
219
220 p->paf = (gtk_combo_box_get_active (GTK_COMBO_BOX (fd->extraction_combo)) == 1);
221 }
222
223 static void
224 run_extractions_subdialog (struct factor *fd)
225 {
226 struct extraction_parameters *ex = &fd->extraction;
227
228 gint response = psppire_dialog_run (PSPPIRE_DIALOG (fd->extraction_dialog));
229
230 if ( response == PSPPIRE_RESPONSE_CONTINUE )
231 {
232 /* Set the parameters from their respective widgets */
233 set_extraction_parameters (fd, ex);
234 }
235 else
236 {
237 /* Cancelled. Reset the widgets to their old state */
238 load_extraction_parameters (fd, ex);
239 }
240 }
241
242 static void
243 run_rotations_subdialog (struct factor *fd)
244 {
245 struct rotation_parameters *rot = &fd->rotation;
246
247 gint response = psppire_dialog_run (PSPPIRE_DIALOG (fd->rotation_dialog));
248
249 if ( response == PSPPIRE_RESPONSE_CONTINUE )
250 {
251 /* Set the parameters from their respective widgets */
252 set_rotation_parameters (fd, rot);
253 }
254 else
255 {
256 /* Cancelled. Reset the widgets to their old state */
257 load_rotation_parameters (fd, rot);
258 }
259 }
260
261
262 static char * generate_syntax (const struct factor *rd);
263
264
265 static void
266 refresh (struct factor *fd)
267 {
268 GtkTreeModel *liststore =
269 gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
270 gtk_list_store_clear (GTK_LIST_STORE (liststore));
271
272 load_extraction_parameters (fd, &default_extraction_parameters);
273 load_rotation_parameters (fd, &default_rotation_parameters);
274 }
275
276
277 static gboolean
278 dialog_state_valid (gpointer data)
279 {
280 struct factor *fd = data;
281
282 GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
283
284 if (gtk_tree_model_iter_n_children (liststore, NULL) < 2)
285 return FALSE;
286
287 return TRUE;
288 }
289
290 static void
291 on_show (struct factor *fd, GtkWidget *dialog)
292 {
293 GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
294
295 gint n_vars = gtk_tree_model_iter_n_children (liststore, NULL);
296
297 gtk_spin_button_set_range (GTK_SPIN_BUTTON (fd->n_factors), 1, n_vars - 1);
298 }
299
300
301 static void
302 on_extract_toggle (GtkToggleButton *button, struct factor *f)
303 {
304 gboolean active = gtk_toggle_button_get_active (button);
305
306 gtk_widget_set_sensitive (GTK_WIDGET (f->n_factors), active);
307 gtk_widget_set_sensitive (GTK_WIDGET (f->mineigen), ! active);
308 }
309
310 /* Pops up the Factor dialog box */
311 void
312 factor_dialog (PsppireDataWindow *dw)
313 {
314 struct factor fd;
315 gint response;
316
317 PsppireVarStore *vs;
318
319 GtkWidget *dialog ;
320 GtkWidget *source ;
321 GtkWidget *extraction_button ;
322 GtkWidget *rotation_button ;
323
324 fd.xml = builder_new ("factor.ui");
325
326 fd.extraction = default_extraction_parameters;
327 fd.rotation = default_rotation_parameters;
328
329 dialog = get_widget_assert (fd.xml, "factor-dialog");
330 source = get_widget_assert (fd.xml, "dict-view");
331 extraction_button = get_widget_assert (fd.xml, "button-extractions");
332 rotation_button = get_widget_assert (fd.xml, "button-rotations");
333
334 fd.extraction_dialog = get_widget_assert (fd.xml, "extractions-dialog");
335 fd.rotation_dialog = get_widget_assert (fd.xml, "rotations-dialog");
336
337 fd.de = dw;
338
339 g_signal_connect_swapped (dialog, "refresh", G_CALLBACK (refresh), &fd);
340
341 {
342 GtkWidget *hbox = get_widget_assert (fd.xml, "hbox6");
343 GtkWidget *eigenvalue_extraction ;
344
345 fd.mineigen_toggle = get_widget_assert (fd.xml, "mineigen-radiobutton");
346
347 eigenvalue_extraction = psppire_scanf_new (_("_Eigenvalues over %4.2f times the mean eigenvalue"), &fd.mineigen);
348
349 g_object_set (eigenvalue_extraction,
350 "use-underline", TRUE,
351 "mnemonic-widget", fd.mineigen_toggle,
352 NULL);
353
354 fd.nfactors_toggle = get_widget_assert (fd.xml, "nfactors-radiobutton");
355 fd.n_factors = get_widget_assert (fd.xml, "spinbutton-nfactors");
356 fd.extract_iterations = get_widget_assert (fd.xml, "spinbutton-extract-iterations");
357 fd.covariance_toggle = get_widget_assert (fd.xml, "covariance-radiobutton");
358 fd.correlation_toggle = get_widget_assert (fd.xml, "correlations-radiobutton");
359
360 fd.scree_button = get_widget_assert (fd.xml, "scree-button");
361 fd.unrotated_button = get_widget_assert (fd.xml, "unrotated-button");
362 fd.extraction_combo = get_widget_assert (fd.xml, "combobox1");
363
364 gtk_container_add (GTK_CONTAINER (hbox), eigenvalue_extraction);
365
366 g_signal_connect (fd.nfactors_toggle, "toggled", G_CALLBACK (on_extract_toggle), &fd);
367
368 gtk_widget_show_all (eigenvalue_extraction);
369 }
370
371 {
372 fd.rotate_iterations = get_widget_assert (fd.xml, "spinbutton-rot-iterations");
373
374 fd.display_rotated_solution = get_widget_assert (fd.xml, "checkbutton-rotated-solution");
375
376 fd.rotation_none = get_widget_assert (fd.xml, "radiobutton-none");
377 fd.rotation_varimax = get_widget_assert (fd.xml, "radiobutton-varimax");
378 fd.rotation_quartimax = get_widget_assert (fd.xml, "radiobutton-quartimax");
379 fd.rotation_equimax = get_widget_assert (fd.xml, "radiobutton-equimax");
380 }
381
382 g_signal_connect_swapped (extraction_button, "clicked", G_CALLBACK (run_extractions_subdialog), &fd);
383 g_signal_connect_swapped (rotation_button, "clicked", G_CALLBACK (run_rotations_subdialog), &fd);
384
385 g_signal_connect_swapped (fd.extraction_dialog, "show", G_CALLBACK (on_show), &fd);
386
387 fd.variables = get_widget_assert (fd.xml, "psppire-var-view1");
388
389 g_object_get (fd.de->data_editor, "var-store", &vs, NULL);
390
391 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (fd.de));
392 gtk_window_set_transient_for (GTK_WINDOW (fd.extraction_dialog), GTK_WINDOW (fd.de));
393 gtk_window_set_transient_for (GTK_WINDOW (fd.rotation_dialog), GTK_WINDOW (fd.de));
394
395 g_object_get (vs, "dictionary", &fd.dict, NULL);
396 g_object_set (source, "model", fd.dict, NULL);
397
398
399 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
400 dialog_state_valid, &fd);
401
402 psppire_selector_set_allow (PSPPIRE_SELECTOR (get_widget_assert (fd.xml, "dep-selector")),
403 numeric_only);
404
405 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
406
407 switch (response)
408 {
409 case GTK_RESPONSE_OK:
410 g_free (execute_syntax_string (dw, generate_syntax (&fd)));
411 break;
412 case PSPPIRE_RESPONSE_PASTE:
413 g_free (paste_syntax_to_window (generate_syntax (&fd)));
414 break;
415 default:
416 break;
417 }
418
419 g_object_unref (fd.xml);
420 }
421
422
423
424
425 static char *
426 generate_syntax (const struct factor *rd)
427 {
428 gchar *text;
429
430 GString *string = g_string_new ("FACTOR ");
431
432 g_string_append (string, "VARIABLES = ");
433
434 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->variables), 0, string);
435
436
437 g_string_append (string, "\n\t/CRITERIA = ");
438 if ( rd->extraction.explicit_nfactors )
439 g_string_append_printf (string, "FACTORS (%d)", rd->extraction.n_factors);
440 else
441 g_string_append_printf (string, "MINEIGEN (%g)", rd->extraction.mineigen);
442
443 /*
444 The CRITERIA = ITERATE subcommand is overloaded.
445 It applies to the next /ROTATION and/or EXTRACTION command whatever comes first.
446 */
447 g_string_append_printf (string, " ITERATE (%d)", rd->extraction.n_iterations);
448
449
450 g_string_append (string, "\n\t/EXTRACTION =");
451 if ( rd->extraction.paf)
452 g_string_append (string, "PAF");
453 else
454 g_string_append (string, "PC");
455
456
457
458
459 g_string_append (string, "\n\t/METHOD = ");
460 if ( rd->extraction.covariance )
461 g_string_append (string, "COVARIANCE");
462 else
463 g_string_append (string, "CORRELATION");
464
465
466
467 if ( rd->extraction.scree )
468 {
469 g_string_append (string, "\n\t/PLOT = ");
470 g_string_append (string, "EIGEN");
471 }
472
473 g_string_append (string, "\n\t/PRINT = ");
474 g_string_append (string, "INITIAL ");
475
476 if ( rd->extraction.unrotated )
477 g_string_append (string, "EXTRACTION ");
478
479 if ( rd->rotation.rotated_solution )
480 g_string_append (string, "ROTATION");
481
482
483 /* The CRITERIA = ITERATE subcommand is overloaded.
484 It applies to the next /ROTATION and/or EXTRACTION command whatever comes first.
485 */
486 g_string_append_printf (string, "\n\t/CRITERIA = ITERATE (%d)", rd->rotation.iterations );
487
488 g_string_append (string, "\n\t/ROTATION = ");
489 g_string_append (string, rot_method_syntax[rd->rotation.method]);
490
491
492 g_string_append (string, ".\n");
493
494 text = string->str;
495
496 g_string_free (string, FALSE);
497
498 return text;
499 }
+0
-24
src/ui/gui/factor-dialog.h less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2009, 2010 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef __FACTOR_DIALOG_H
17 #define __FACTOR_DIALOG_H
18
19 #include "psppire-data-window.h"
20
21 void factor_dialog (PsppireDataWindow * data);
22
23 #endif
248248 <property name="visible">True</property>
249249 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
250250 <property name="border_width">5</property>
251 <property name="buttons">PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK | PSPPIRE_BUTTON_RESET_MASK</property>
251 <property name="buttons">PSPPIRE_BUTTON_CLOSE_MASK | PSPPIRE_BUTTON_HELP_MASK | PSPPIRE_BUTTON_RESET_MASK</property>
252252 </object>
253253 <packing>
254254 <property name="expand">False</property>
111111 </child>
112112 </object>
113113 <packing>
114 <property name="expand">False</property>
115 <property name="fill">False</property>
116114 <property name="position">0</property>
117115 </packing>
118116 </child>
175173 <property name="visible">True</property>
176174 <child>
177175 <object class="GtkButton" id="charts-button">
178 <property name="label" translatable="yes">Charts...</property>
176 <property name="label" translatable="yes">Ch_arts...</property>
179177 <property name="visible">True</property>
180178 <property name="can_focus">True</property>
181179 <property name="receives_default">True</property>
182180 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
181 <property name="use_underline">True</property>
183182 </object>
184183 <packing>
185184 <property name="expand">False</property>
189188 </child>
190189 <child>
191190 <object class="GtkButton" id="tables-button">
192 <property name="label" translatable="yes">Frequency Tables...</property>
191 <property name="label" translatable="yes">Frequency _Tables...</property>
193192 <property name="visible">True</property>
194193 <property name="can_focus">True</property>
195194 <property name="receives_default">True</property>
196195 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
196 <property name="use_underline">True</property>
197197 </object>
198198 <packing>
199199 <property name="expand">False</property>
276276 <property name="homogeneous">True</property>
277277 <child>
278278 <object class="GtkRadioButton" id="always">
279 <property name="label" translatable="yes">Always</property>
279 <property name="label" translatable="yes">_Always</property>
280280 <property name="visible">True</property>
281281 <property name="can_focus">True</property>
282282 <property name="receives_default">False</property>
283283 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
284 <property name="use_underline">True</property>
284285 <property name="active">True</property>
285286 <property name="draw_indicator">True</property>
286287 </object>
292293 </child>
293294 <child>
294295 <object class="GtkRadioButton" id="never">
295 <property name="label" translatable="yes">Never</property>
296 <property name="label" translatable="yes">_Never</property>
296297 <property name="visible">True</property>
297298 <property name="can_focus">True</property>
298299 <property name="receives_default">False</property>
299300 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
301 <property name="use_underline">True</property>
300302 <property name="draw_indicator">True</property>
301303 <property name="group">always</property>
302304 </object>
311313 <property name="visible">True</property>
312314 <child>
313315 <object class="GtkRadioButton" id="limit">
314 <property name="label" translatable="yes">If no more than </property>
316 <property name="label" translatable="yes">If no _more than </property>
315317 <property name="visible">True</property>
316318 <property name="can_focus">True</property>
317319 <property name="receives_default">False</property>
318320 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
321 <property name="use_underline">True</property>
319322 <property name="draw_indicator">True</property>
320323 <property name="group">always</property>
321324 </object>
369372 </child>
370373 </object>
371374 <packing>
372 <property name="expand">False</property>
373375 <property name="position">0</property>
374376 </packing>
375377 </child>
391393 <property name="homogeneous">True</property>
392394 <child>
393395 <object class="GtkRadioButton" id="avalue">
394 <property name="label" translatable="yes">Ascending value</property>
396 <property name="label" translatable="yes">A_scending value</property>
395397 <property name="visible">True</property>
396398 <property name="can_focus">True</property>
397399 <property name="receives_default">False</property>
398400 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
401 <property name="use_underline">True</property>
399402 <property name="active">True</property>
400403 <property name="draw_indicator">True</property>
401404 </object>
407410 </child>
408411 <child>
409412 <object class="GtkRadioButton" id="dvalue">
410 <property name="label" translatable="yes">Descending value</property>
413 <property name="label" translatable="yes">D_escending value</property>
411414 <property name="visible">True</property>
412415 <property name="can_focus">True</property>
413416 <property name="receives_default">False</property>
414417 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
418 <property name="use_underline">True</property>
415419 <property name="draw_indicator">True</property>
416420 <property name="group">avalue</property>
417421 </object>
423427 </child>
424428 <child>
425429 <object class="GtkRadioButton" id="afreq">
426 <property name="label" translatable="yes">Ascending frequency</property>
430 <property name="label" translatable="yes">Ascending _frequency</property>
427431 <property name="visible">True</property>
428432 <property name="can_focus">True</property>
429433 <property name="receives_default">False</property>
430434 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
435 <property name="use_underline">True</property>
431436 <property name="draw_indicator">True</property>
432437 <property name="group">avalue</property>
433438 </object>
439444 </child>
440445 <child>
441446 <object class="GtkRadioButton" id="dfreq">
442 <property name="label" translatable="yes">Descending frequency</property>
447 <property name="label" translatable="yes">Descending f_requency</property>
443448 <property name="visible">True</property>
444449 <property name="can_focus">True</property>
445450 <property name="receives_default">False</property>
446451 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
452 <property name="use_underline">True</property>
447453 <property name="draw_indicator">True</property>
448454 <property name="group">avalue</property>
449455 </object>
467473 </child>
468474 </object>
469475 <packing>
470 <property name="expand">False</property>
471476 <property name="position">1</property>
472477 </packing>
473478 </child>
532537 <property name="visible">True</property>
533538 <child>
534539 <object class="GtkCheckButton" id="min">
535 <property name="label" translatable="yes">Exclude values below </property>
536 <property name="visible">True</property>
537 <property name="can_focus">True</property>
538 <property name="receives_default">False</property>
540 <property name="label" translatable="yes">Exclude values _below </property>
541 <property name="visible">True</property>
542 <property name="can_focus">True</property>
543 <property name="receives_default">False</property>
544 <property name="use_underline">True</property>
539545 <property name="draw_indicator">True</property>
540546 </object>
541547 <packing>
567573 <property name="visible">True</property>
568574 <child>
569575 <object class="GtkCheckButton" id="max">
570 <property name="label" translatable="yes">Exclude values above </property>
571 <property name="visible">True</property>
572 <property name="can_focus">True</property>
573 <property name="receives_default">False</property>
576 <property name="label" translatable="yes">Exclude values _above </property>
577 <property name="visible">True</property>
578 <property name="can_focus">True</property>
579 <property name="receives_default">False</property>
580 <property name="use_underline">True</property>
574581 <property name="draw_indicator">True</property>
575582 </object>
576583 <packing>
629636 <property name="orientation">vertical</property>
630637 <child>
631638 <object class="GtkCheckButton" id="hist">
632 <property name="label" translatable="yes">Draw histograms</property>
639 <property name="label" translatable="yes">Draw _histograms</property>
633640 <property name="visible">True</property>
634641 <property name="can_focus">True</property>
635642 <property name="receives_default">False</property>
643 <property name="use_underline">True</property>
636644 <property name="draw_indicator">True</property>
637645 </object>
638646 <packing>
641649 </child>
642650 <child>
643651 <object class="GtkCheckButton" id="normal">
644 <property name="label" translatable="yes">Superimpose normal curve</property>
652 <property name="label" translatable="yes">Superimpose _normal curve</property>
645653 <property name="visible">True</property>
646654 <property name="can_focus">True</property>
647655 <property name="receives_default">False</property>
656 <property name="use_underline">True</property>
648657 <property name="draw_indicator">True</property>
649658 </object>
650659 <packing>
665674 </child>
666675 <child>
667676 <object class="GtkRadioButton" id="freqs">
668 <property name="label" translatable="yes">Frequencies</property>
669 <property name="visible">True</property>
670 <property name="can_focus">True</property>
671 <property name="receives_default">False</property>
677 <property name="label" translatable="yes">_Frequencies</property>
678 <property name="visible">True</property>
679 <property name="can_focus">True</property>
680 <property name="receives_default">False</property>
681 <property name="use_underline">True</property>
672682 <property name="active">True</property>
673683 <property name="draw_indicator">True</property>
674684 </object>
678688 </child>
679689 <child>
680690 <object class="GtkRadioButton" id="percents">
681 <property name="label" translatable="yes">Percentages</property>
682 <property name="visible">True</property>
683 <property name="can_focus">True</property>
684 <property name="receives_default">False</property>
691 <property name="label" translatable="yes">_Percentages</property>
692 <property name="visible">True</property>
693 <property name="can_focus">True</property>
694 <property name="receives_default">False</property>
695 <property name="use_underline">True</property>
685696 <property name="draw_indicator">True</property>
686697 <property name="group">freqs</property>
687698 </object>
725736 <property name="orientation">vertical</property>
726737 <child>
727738 <object class="GtkCheckButton" id="pie">
728 <property name="label" translatable="yes">Draw pie charts</property>
739 <property name="label" translatable="yes">Draw _pie charts</property>
729740 <property name="visible">True</property>
730741 <property name="can_focus">True</property>
731742 <property name="receives_default">False</property>
743 <property name="use_underline">True</property>
732744 <property name="draw_indicator">True</property>
733745 </object>
734746 <packing>
737749 </child>
738750 <child>
739751 <object class="GtkCheckButton" id="pie-include-missing">
740 <property name="label" translatable="yes">Include slices for missing values</property>
752 <property name="label" translatable="yes">Include slices for _missing values</property>
741753 <property name="visible">True</property>
742754 <property name="can_focus">True</property>
743755 <property name="receives_default">False</property>
756 <property name="use_underline">True</property>
744757 <property name="draw_indicator">True</property>
745758 </object>
746759 <packing>
4646
4747 #include <gettext.h>
4848
49 /* Returns a copy of IN with each underscore doubled. The caller should free
50 the returned string (with free()) when it is no longer needed. */
51 char *
52 escape_underscores (const char *in)
53 {
54 char *out = xmalloc (2 * strlen (in) + 1);
55 char *p;
56
57 p = out;
58 for (; *in != '\0'; in++)
59 {
60 if (*in == '_')
61 *p++ = '_';
62 *p++ = *in;
63 }
64 *p = '\0';
65
66 return out;
67 }
68
4969 /* Formats a value according to VAR's print format and strips white space
5070 appropriately for VAR's type. That is, if VAR is numeric, strips leading
5171 white space (because numbers are right-justified within their fields), and
5777 gchar *
5878 value_to_text (union value v, const struct variable *var)
5979 {
80 return value_to_text__ (v, var_get_print_format (var),
81 var_get_encoding (var));
82 }
83
84 /* Formats a value with format FORMAT and strips white space appropriately for
85 FORMATs' type. That is, if FORMAT is numeric, strips leading white space
86 (because numbers are right-justified within their fields), and if FORMAT is
87 string, strips trailing white space (because spaces pad out string values on
88 the right).
89
90 Returns an allocated string. The returned string must be freed when no
91 longer required. */
92 gchar *
93 value_to_text__ (union value v,
94 const struct fmt_spec *format, const char *encoding)
95 {
6096 gchar *s;
6197
62 s = data_out (&v, var_get_encoding (var), var_get_print_format (var));
63 if (var_is_numeric (var))
98 s = data_out (&v, encoding, format);
99 if (fmt_is_numeric (format->type))
64100 g_strchug (s);
65101 else
66102 g_strchomp (s);
67103
68104 return s;
69105 }
70
71106
72107 /* Converts TEXT to a value.
73108
4343 return param;
4444 }
4545
46 char *escape_underscores (const char *);
4647
4748 gchar * value_to_text (union value v, const struct variable *);
49 gchar * value_to_text__ (union value v, const struct fmt_spec *,
50 const char *encoding);
4851
4952
5053 union value *
162162 }
163163 #endif /* gtk < 2.18 */
164164
165 #if !GTK_CHECK_VERSION(2,22,0)
166 /**
167 * gtk_button_get_event_window:
168 * @button: a #GtkButton
169 *
170 * Returns the button's event window if it is realized, %NULL otherwise.
171 * This function should be rarely needed.
172 *
173 * Return value: (transfer none): @button's event window.
174 *
175 * Since: 2.22
176 */
177 static inline GdkWindow*
178 gtk_button_get_event_window (GtkButton *button)
179 {
180 g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
181
182 return button->event_window;
183 }
184 #endif /* gtk < 2.22 */
185
165186 #endif /* PSPP_GTK_GTK_H */
0 <?xml version="1.0"?>
1 <interface>
2 <requires lib="psppire" version="2054.17080"/>
3 <!-- interface-requires gtk+ 2.12 -->
4 <!-- interface-naming-policy project-wide -->
5 <object class="PsppireDialog" id="independent-samples-dialog">
6 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
7 <property name="title" translatable="yes">Independent-Samples T Test</property>
8 <property name="modal">True</property>
9 <child internal-child="hbox">
10 <object class="GtkHBox" id="dialog-hbox15">
11 <property name="visible">True</property>
12 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
13 <property name="spacing">2</property>
14 <child>
15 <object class="GtkHBox" id="hbox23">
16 <property name="visible">True</property>
17 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
18 <property name="spacing">5</property>
19 <child>
20 <object class="GtkScrolledWindow" id="scrolledwindow14">
21 <property name="visible">True</property>
22 <property name="can_focus">True</property>
23 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
24 <property name="hscrollbar_policy">never</property>
25 <property name="vscrollbar_policy">automatic</property>
26 <property name="shadow_type">etched-in</property>
27 <child>
28 <object class="PsppireDictView" id="indep-samples-treeview1">
29 <property name="visible">True</property>
30 <property name="can_focus">True</property>
31 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
32 <property name="headers_visible">False</property>
33 </object>
34 </child>
35 </object>
36 <packing>
37 <property name="position">0</property>
38 </packing>
39 </child>
40 <child>
41 <object class="GtkTable" id="table4">
42 <property name="visible">True</property>
43 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
44 <property name="n_rows">3</property>
45 <property name="n_columns">2</property>
46 <child>
47 <object class="GtkHButtonBox" id="hbuttonbox1">
48 <property name="visible">True</property>
49 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
50 <property name="layout_style">spread</property>
51 <child>
52 <object class="GtkButton" id="define-groups-button">
53 <property name="label" translatable="yes">Define Groups</property>
54 <property name="visible">True</property>
55 <property name="can_focus">True</property>
56 <property name="receives_default">True</property>
57 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
58 </object>
59 <packing>
60 <property name="expand">False</property>
61 <property name="fill">False</property>
62 <property name="position">0</property>
63 </packing>
64 </child>
65 <child>
66 <object class="GtkButton" id="indep-samples-options-button">
67 <property name="label" translatable="yes">Options...</property>
68 <property name="visible">True</property>
69 <property name="can_focus">True</property>
70 <property name="receives_default">True</property>
71 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
72 </object>
73 <packing>
74 <property name="expand">False</property>
75 <property name="fill">False</property>
76 <property name="position">1</property>
77 </packing>
78 </child>
79 </object>
80 <packing>
81 <property name="right_attach">2</property>
82 <property name="top_attach">2</property>
83 <property name="bottom_attach">3</property>
84 <property name="y_options">GTK_FILL</property>
85 <property name="y_padding">5</property>
86 </packing>
87 </child>
88 <child>
89 <object class="PsppireSelector" id="indep-samples-selector1">
90 <property name="visible">True</property>
91 <property name="can_focus">True</property>
92 <property name="receives_default">True</property>
93 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
94 <property name="border_width">5</property>
95 <property name="source_widget">indep-samples-treeview1</property>
96 <property name="dest_widget">indep-samples-treeview2</property>
97 </object>
98 <packing>
99 <property name="x_options"></property>
100 <property name="y_options">GTK_EXPAND</property>
101 </packing>
102 </child>
103 <child>
104 <object class="PsppireSelector" id="indep-samples-selector2">
105 <property name="visible">True</property>
106 <property name="can_focus">True</property>
107 <property name="receives_default">True</property>
108 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
109 <property name="border_width">5</property>
110 <property name="source_widget">indep-samples-treeview1</property>
111 <property name="dest_widget">indep-samples-entry</property>
112 </object>
113 <packing>
114 <property name="top_attach">1</property>
115 <property name="bottom_attach">2</property>
116 <property name="x_options"></property>
117 <property name="y_options"></property>
118 </packing>
119 </child>
120 <child>
121 <object class="GtkVBox" id="vbox29">
122 <property name="visible">True</property>
123 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
124 <property name="orientation">vertical</property>
125 <child>
126 <object class="GtkLabel" id="label35">
127 <property name="visible">True</property>
128 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
129 <property name="xalign">0</property>
130 <property name="label" translatable="yes">_Test Variable(s):</property>
131 <property name="use_underline">True</property>
132 <property name="mnemonic_widget">indep-samples-treeview2</property>
133 </object>
134 <packing>
135 <property name="expand">False</property>
136 <property name="fill">False</property>
137 <property name="position">0</property>
138 </packing>
139 </child>
140 <child>
141 <object class="GtkScrolledWindow" id="scrolledwindow15">
142 <property name="visible">True</property>
143 <property name="can_focus">True</property>
144 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
145 <property name="hscrollbar_policy">automatic</property>
146 <property name="vscrollbar_policy">automatic</property>
147 <property name="shadow_type">etched-in</property>
148 <child>
149 <object class="PsppireVarView" id="indep-samples-treeview2">
150 <property name="visible">True</property>
151 <property name="can_focus">True</property>
152 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
153 <property name="headers_visible">False</property>
154 </object>
155 </child>
156 </object>
157 <packing>
158 <property name="position">1</property>
159 </packing>
160 </child>
161 </object>
162 <packing>
163 <property name="left_attach">1</property>
164 <property name="right_attach">2</property>
165 </packing>
166 </child>
167 <child>
168 <object class="GtkVBox" id="vbox30">
169 <property name="visible">True</property>
170 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
171 <property name="orientation">vertical</property>
172 <child>
173 <object class="GtkLabel" id="label36">
174 <property name="visible">True</property>
175 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
176 <property name="xalign">0</property>
177 <property name="label" translatable="yes">_Grouping Variable:</property>
178 <property name="use_underline">True</property>
179 <property name="mnemonic_widget">indep-samples-entry</property>
180 </object>
181 <packing>
182 <property name="expand">False</property>
183 <property name="fill">False</property>
184 <property name="position">0</property>
185 </packing>
186 </child>
187 <child>
188 <object class="GtkEntry" id="indep-samples-entry">
189 <property name="visible">True</property>
190 <property name="can_focus">True</property>
191 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
192 </object>
193 <packing>
194 <property name="position">1</property>
195 </packing>
196 </child>
197 </object>
198 <packing>
199 <property name="left_attach">1</property>
200 <property name="right_attach">2</property>
201 <property name="top_attach">1</property>
202 <property name="bottom_attach">2</property>
203 <property name="y_options"></property>
204 </packing>
205 </child>
206 </object>
207 <packing>
208 <property name="position">1</property>
209 </packing>
210 </child>
211 </object>
212 <packing>
213 <property name="position">0</property>
214 </packing>
215 </child>
216 <child>
217 <object class="PsppireVButtonBox" id="psppire-vbuttonbox2">
218 <property name="visible">True</property>
219 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
220 <property name="border_width">5</property>
221 <property name="orientation">vertical</property>
222 </object>
223 <packing>
224 <property name="expand">False</property>
225 <property name="fill">False</property>
226 <property name="pack_type">end</property>
227 <property name="position">1</property>
228 </packing>
229 </child>
230 </object>
231 </child>
232 </object>
233 <object class="PsppireDialog" id="define-groups-dialog">
234 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
235 <property name="title" translatable="yes">Define Groups</property>
236 <property name="modal">True</property>
237 <child internal-child="hbox">
238 <object class="GtkHBox" id="dialog-hbox2">
239 <property name="visible">True</property>
240 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
241 <property name="spacing">2</property>
242 <child>
243 <object class="GtkTable" id="table1">
244 <property name="visible">True</property>
245 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
246 <property name="n_rows">3</property>
247 <property name="n_columns">2</property>
248 <property name="column_spacing">5</property>
249 <property name="row_spacing">5</property>
250 <child>
251 <object class="GtkRadioButton" id="radiobutton3">
252 <property name="visible">True</property>
253 <property name="can_focus">True</property>
254 <property name="receives_default">False</property>
255 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
256 <property name="active">True</property>
257 <property name="draw_indicator">True</property>
258 </object>
259 <packing>
260 <property name="x_options"></property>
261 </packing>
262 </child>
263 <child>
264 <object class="GtkTable" id="table2">
265 <property name="visible">True</property>
266 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
267 <property name="n_rows">2</property>
268 <property name="n_columns">2</property>
269 <property name="column_spacing">5</property>
270 <property name="row_spacing">5</property>
271 <child>
272 <object class="GtkLabel" id="label2">
273 <property name="visible">True</property>
274 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
275 <property name="label" translatable="yes">Group_2 value:</property>
276 <property name="use_underline">True</property>
277 <property name="mnemonic_widget">group2-entry</property>
278 </object>
279 <packing>
280 <property name="top_attach">1</property>
281 <property name="bottom_attach">2</property>
282 <property name="x_options"></property>
283 </packing>
284 </child>
285 <child>
286 <object class="GtkLabel" id="label1">
287 <property name="visible">True</property>
288 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
289 <property name="label" translatable="yes">Group_1 value:</property>
290 <property name="use_underline">True</property>
291 <property name="mnemonic_widget">group1-entry</property>
292 </object>
293 <packing>
294 <property name="x_options"></property>
295 </packing>
296 </child>
297 <child>
298 <object class="PsppireValueEntry" id="group2-entry">
299 <property name="visible">True</property>
300 <property name="can_focus">True</property>
301 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
302 </object>
303 <packing>
304 <property name="left_attach">1</property>
305 <property name="right_attach">2</property>
306 <property name="top_attach">1</property>
307 <property name="bottom_attach">2</property>
308 </packing>
309 </child>
310 <child>
311 <object class="PsppireValueEntry" id="group1-entry">
312 <property name="visible">True</property>
313 <property name="can_focus">True</property>
314 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
315 </object>
316 <packing>
317 <property name="left_attach">1</property>
318 <property name="right_attach">2</property>
319 </packing>
320 </child>
321 </object>
322 <packing>
323 <property name="left_attach">1</property>
324 <property name="right_attach">2</property>
325 <property name="top_attach">1</property>
326 <property name="bottom_attach">2</property>
327 <property name="y_options">GTK_EXPAND</property>
328 </packing>
329 </child>
330 <child>
331 <object class="GtkHBox" id="hbox1">
332 <property name="visible">True</property>
333 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
334 <child>
335 <object class="GtkLabel" id="label5">
336 <property name="visible">True</property>
337 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
338 <property name="xalign">0</property>
339 <property name="label" translatable="yes">_Cut point:</property>
340 <property name="use_underline">True</property>
341 <property name="mnemonic_widget">radiobutton4</property>
342 </object>
343 <packing>
344 <property name="position">0</property>
345 </packing>
346 </child>
347 <child>
348 <object class="PsppireValueEntry" id="cut-point-entry">
349 <property name="visible">True</property>
350 <property name="can_focus">True</property>
351 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
352 </object>
353 <packing>
354 <property name="position">1</property>
355 </packing>
356 </child>
357 </object>
358 <packing>
359 <property name="left_attach">1</property>
360 <property name="right_attach">2</property>
361 <property name="top_attach">2</property>
362 <property name="bottom_attach">3</property>
363 <property name="y_options"></property>
364 <property name="y_padding">5</property>
365 </packing>
366 </child>
367 <child>
368 <object class="GtkLabel" id="label4">
369 <property name="visible">True</property>
370 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
371 <property name="xalign">0</property>
372 <property name="label" translatable="yes">_Use specified values:</property>
373 <property name="use_underline">True</property>
374 <property name="mnemonic_widget">radiobutton3</property>
375 </object>
376 <packing>
377 <property name="left_attach">1</property>
378 <property name="right_attach">2</property>
379 <property name="y_options"></property>
380 </packing>
381 </child>
382 <child>
383 <object class="GtkRadioButton" id="radiobutton4">
384 <property name="visible">True</property>
385 <property name="can_focus">True</property>
386 <property name="receives_default">False</property>
387 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
388 <property name="active">True</property>
389 <property name="draw_indicator">True</property>
390 <property name="group">radiobutton3</property>
391 </object>
392 <packing>
393 <property name="top_attach">2</property>
394 <property name="bottom_attach">3</property>
395 <property name="x_options"></property>
396 <property name="y_options"></property>
397 </packing>
398 </child>
399 <child>
400 <placeholder/>
401 </child>
402 </object>
403 <packing>
404 <property name="padding">5</property>
405 <property name="position">0</property>
406 </packing>
407 </child>
408 <child>
409 <object class="PsppireVButtonBox" id="psppire-vbuttonbox1">
410 <property name="visible">True</property>
411 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
412 <property name="border_width">5</property>
413 <property name="orientation">vertical</property>
414 <property name="buttons">PSPPIRE_BUTTON_CONTINUE_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK</property>
415 </object>
416 <packing>
417 <property name="expand">False</property>
418 <property name="fill">False</property>
419 <property name="pack_type">end</property>
420 <property name="position">1</property>
421 </packing>
422 </child>
423 </object>
424 </child>
425 </object>
426 </interface>
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2004, 2005, 2006, 2010, 2011 Free Software Foundation
1 Copyright (C) 2004, 2005, 2006, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
4949 OPT_HELP,
5050 OPT_VERSION,
5151 OPT_NO_SPLASH,
52 OPT_MEASURE_STARTUP,
5253 N_STARTUP_OPTIONS
5354 };
5455
5657 {
5758 {"help", 'h', no_argument, OPT_HELP},
5859 {"version", 'V', no_argument, OPT_VERSION},
59 {"no-splash", 'q', no_argument, OPT_NO_SPLASH}
60 {"no-splash", 'q', no_argument, OPT_NO_SPLASH},
61 {"measure-startup", 0, no_argument, OPT_MEASURE_STARTUP},
6062 };
63
64 /* --measure-startup: Prints the elapsed time to start up and load any file
65 specified on the command line. */
66 static gboolean measure_startup;
67 static GTimer *startup;
6168
6269 static void
6370 usage (void)
137144 *show_splash = FALSE;
138145 break;
139146
147 case OPT_MEASURE_STARTUP:
148 measure_startup = TRUE;
149 break;
150
140151 default:
141152 NOT_REACHED ();
142153 }
176187 return FALSE;
177188 }
178189
190 static gboolean
191 print_startup_time (gpointer data)
192 {
193 g_timer_stop (startup);
194 printf ("%.3f seconds elapsed\n", g_timer_elapsed (startup, NULL));
195 g_timer_destroy (startup);
196 startup = NULL;
197
198 return FALSE;
199 }
179200
180201 static gboolean
181202 quit_one_loop (gpointer data)
198219 initialize (ip->data_file);
199220
200221 g_timeout_add (500, hide_splash_window, ip->splash_window);
222
223 if (measure_startup)
224 {
225 GSource *source = g_idle_source_new ();
226 g_source_set_priority (source, G_PRIORITY_LOW);
227 g_source_set_callback (source, print_startup_time, NULL, NULL);
228 g_source_attach (source, NULL);
229 g_source_unref (source);
230 }
201231
202232 gtk_main ();
203233
249279 set_program_name (argv[0]);
250280
251281 g_mem_set_vtable (&vtable);
282 g_thread_init (NULL);
252283
253284 gtk_disable_setlocale ();
254285
286 startup = g_timer_new ();
287 g_timer_start (startup);
255288
256289 if ( ! gtk_parse_args (&argc, &argv) )
257290 {
00 #List of custom marshallers used by psppire
11
22 BOOLEAN:BOOLEAN
3 BOOLEAN:BOOLEAN,BOOLEAN,BOOLEAN
4 BOOLEAN:BOXED
35 BOOLEAN:ENUM
6 BOOLEAN:ENUM,INT
7 BOOLEAN:BOXED,BOXED
48 BOOLEAN:BOXED,POINTER
9 BOOLEAN:OBJECT
510 BOOLEAN:VOID
611 VOID:BOXED,BOXED
12 VOID:BOXED,OBJECT
713 VOID:INT,INT
814 VOID:INT,LONG
9 VOID:INT,INT,INT
1015 VOID:INT,INT,INT,INT
1116 VOID:INT,POINTER
1217 VOID:OBJECT,OBJECT
18 VOID:POINTER,INT,INT
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeprivate.h
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #ifndef __GTK_TREE_PRIVATE_H__
36 #define __GTK_TREE_PRIVATE_H__
37
38
39 #include <gtk/gtk.h>
40 #include "libpspp/range-tower.h"
41 #include "ui/gui/pspp-sheet-view.h"
42 #include "ui/gui/pspp-sheet-view-column.h"
43
44 #define TREE_VIEW_DRAG_WIDTH 6
45
46 typedef enum
47 {
48 PSPP_SHEET_VIEW_IN_COLUMN_RESIZE = 1 << 2,
49 PSPP_SHEET_VIEW_HEADERS_VISIBLE = 1 << 4,
50 PSPP_SHEET_VIEW_DRAW_KEYFOCUS = 1 << 5,
51 PSPP_SHEET_VIEW_MODEL_SETUP = 1 << 6,
52 PSPP_SHEET_VIEW_IN_COLUMN_DRAG = 1 << 7
53 } PsppSheetViewFlags;
54
55 typedef enum
56 {
57 GTK_TREE_SELECT_MODE_TOGGLE = 1 << 0,
58 GTK_TREE_SELECT_MODE_EXTEND = 1 << 1
59 }
60 GtkTreeSelectMode;
61
62 enum
63 {
64 DRAG_COLUMN_WINDOW_STATE_UNSET = 0,
65 DRAG_COLUMN_WINDOW_STATE_ORIGINAL = 1,
66 DRAG_COLUMN_WINDOW_STATE_ARROW = 2,
67 DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT = 3,
68 DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT = 4
69 };
70
71 enum
72 {
73 RUBBER_BAND_OFF = 0,
74 RUBBER_BAND_MAYBE_START = 1,
75 RUBBER_BAND_ACTIVE = 2
76 };
77
78 #define PSPP_SHEET_VIEW_SET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags|=flag); }G_STMT_END
79 #define PSPP_SHEET_VIEW_UNSET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags&=~(flag)); }G_STMT_END
80 #define PSPP_SHEET_VIEW_FLAG_SET(tree_view, flag) ((tree_view->priv->flags&flag)==flag)
81 #define TREE_VIEW_HEADER_HEIGHT(tree_view) (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE)?tree_view->priv->header_height:0)
82 #define TREE_VIEW_COLUMN_REQUESTED_WIDTH(column) (CLAMP (column->requested_width, (column->min_width!=-1)?column->min_width:column->requested_width, (column->max_width!=-1)?column->max_width:column->requested_width))
83
84 /* This lovely little value is used to determine how far away from the title bar
85 * you can move the mouse and still have a column drag work.
86 */
87 #define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view) (10*TREE_VIEW_HEADER_HEIGHT(tree_view))
88
89 typedef struct _PsppSheetViewColumnReorder PsppSheetViewColumnReorder;
90 struct _PsppSheetViewColumnReorder
91 {
92 gint left_align;
93 gint right_align;
94 PsppSheetViewColumn *left_column;
95 PsppSheetViewColumn *right_column;
96 };
97
98 struct _PsppSheetViewPrivate
99 {
100 GtkTreeModel *model;
101
102 guint flags;
103 /* tree information */
104 gint row_count;
105 struct range_tower *selected;
106
107 /* Container info */
108 GList *children;
109 gint width;
110 gint height;
111
112 /* Adjustments */
113 GtkAdjustment *hadjustment;
114 GtkAdjustment *vadjustment;
115
116 /* Sub windows */
117 GdkWindow *bin_window;
118 GdkWindow *header_window;
119
120 /* Scroll position state keeping */
121 GtkTreeRowReference *top_row;
122 gint top_row_dy;
123 /* dy == y pos of top_row + top_row_dy */
124 /* we cache it for simplicity of the code */
125 gint dy;
126
127 guint presize_handler_timer;
128 guint validate_rows_timer;
129 guint scroll_sync_timer;
130
131 /* Indentation and expander layout */
132 gint expander_size;
133
134 /* Key navigation (focus), selection */
135 gint cursor_offset;
136
137 GtkTreeRowReference *anchor;
138 GtkTreeRowReference *cursor;
139
140 PsppSheetViewColumn *focus_column;
141
142 /* Current pressed node, previously pressed, prelight */
143 gint pressed_button;
144 gint press_start_x;
145 gint press_start_y;
146 gint press_start_node;
147
148 gint event_last_x;
149 gint event_last_y;
150
151 guint last_button_time;
152 gint last_button_x;
153 gint last_button_y;
154
155 int prelight_node;
156
157 /* Cell Editing */
158 PsppSheetViewColumn *edited_column;
159
160 /* Selection information */
161 PsppSheetSelection *selection;
162
163 /* Header information */
164 gint n_columns;
165 GList *columns;
166 gint header_height;
167 gint n_selected_columns;
168
169 PsppSheetViewColumnDropFunc column_drop_func;
170 gpointer column_drop_func_data;
171 GDestroyNotify column_drop_func_data_destroy;
172 GList *column_drag_info;
173 PsppSheetViewColumnReorder *cur_reorder;
174
175 /* Interactive Header reordering */
176 GdkWindow *drag_window;
177 GdkWindow *drag_highlight_window;
178 PsppSheetViewColumn *drag_column;
179 gint drag_column_x;
180
181 /* Interactive Header Resizing */
182 gint drag_pos;
183 gint x_drag;
184
185 /* Non-interactive Header Resizing, expand flag support */
186 gint prev_width;
187
188 /* ATK Hack */
189 PsppSheetDestroyCountFunc destroy_count_func;
190 gpointer destroy_count_data;
191 GDestroyNotify destroy_count_destroy;
192
193 /* Scroll timeout (e.g. during dnd, rubber banding) */
194 guint scroll_timeout;
195
196 /* Row drag-and-drop */
197 GtkTreeRowReference *drag_dest_row;
198 PsppSheetViewDropPosition drag_dest_pos;
199 guint open_dest_timeout;
200
201 /* Rubber banding */
202 gint rubber_band_status;
203 gint rubber_band_x;
204 gint rubber_band_y;
205 gint rubber_band_shift;
206 gint rubber_band_ctrl;
207
208 int rubber_band_start_node;
209
210 int rubber_band_end_node;
211
212 /* Rectangular selection. */
213 PsppSheetViewColumn *anchor_column; /* XXX needs to be a weak pointer? */
214
215 /* fixed height */
216 gint fixed_height;
217 gboolean fixed_height_set;
218
219 /* Scroll-to functionality when unrealized */
220 GtkTreeRowReference *scroll_to_path;
221 PsppSheetViewColumn *scroll_to_column;
222 gfloat scroll_to_row_align;
223 gfloat scroll_to_col_align;
224
225 /* Interactive search */
226 gint selected_iter;
227 gint search_column;
228 PsppSheetViewSearchPositionFunc search_position_func;
229 PsppSheetViewSearchEqualFunc search_equal_func;
230 gpointer search_user_data;
231 GDestroyNotify search_destroy;
232 gpointer search_position_user_data;
233 GDestroyNotify search_position_destroy;
234 GtkWidget *search_window;
235 GtkWidget *search_entry;
236 guint search_entry_changed_id;
237 guint typeselect_flush_timeout;
238
239 /* Grid and tree lines */
240 PsppSheetViewGridLines grid_lines;
241 GdkGC *grid_line_gc;
242
243 /* Special cells. */
244 PsppSheetViewSpecialCells special_cells;
245
246 /* Tooltip support */
247 gint tooltip_column;
248
249 /* Cached style for button facades in columns. */
250 GtkStyle *button_style;
251
252 /* Here comes the bitfield */
253 guint scroll_to_use_align : 1;
254
255 guint reorderable : 1;
256 guint header_has_focus : 1;
257 guint drag_column_window_state : 3;
258 /* hint to display rows in alternating colors */
259 guint has_rules : 1;
260
261 /* for DnD */
262 guint empty_view_drop : 1;
263
264 guint ctrl_pressed : 1;
265 guint shift_pressed : 1;
266
267 guint init_hadjust_value : 1;
268
269 guint in_top_row_to_dy : 1;
270
271 /* interactive search */
272 guint enable_search : 1;
273 guint disable_popdown : 1;
274 guint search_custom_entry_set : 1;
275
276 guint hover_selection : 1;
277 guint imcontext_changed : 1;
278
279 guint rubber_banding_enable : 1;
280
281 guint in_grab : 1;
282
283 guint post_validation_flag : 1;
284
285 /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
286 guint search_entry_avoid_unhandled_binding : 1;
287 };
288
289 #ifdef __GNUC__
290
291 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
292 if (!(expr)) \
293 { \
294 g_log (G_LOG_DOMAIN, \
295 G_LOG_LEVEL_CRITICAL, \
296 "%s (%s): assertion `%s' failed.\n" \
297 "There is a disparity between the internal view of the PsppSheetView,\n" \
298 "and the GtkTreeModel. This generally means that the model has changed\n"\
299 "without letting the view know. Any display from now on is likely to\n" \
300 "be incorrect.\n", \
301 G_STRLOC, \
302 G_STRFUNC, \
303 #expr); \
304 return ret; \
305 }; }G_STMT_END
306
307 #define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
308 if (!(expr)) \
309 { \
310 g_log (G_LOG_DOMAIN, \
311 G_LOG_LEVEL_CRITICAL, \
312 "%s (%s): assertion `%s' failed.\n" \
313 "There is a disparity between the internal view of the PsppSheetView,\n" \
314 "and the GtkTreeModel. This generally means that the model has changed\n"\
315 "without letting the view know. Any display from now on is likely to\n" \
316 "be incorrect.\n", \
317 G_STRLOC, \
318 G_STRFUNC, \
319 #expr); \
320 return; \
321 }; }G_STMT_END
322
323 #else
324
325 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret) G_STMT_START{ \
326 if (!(expr)) \
327 { \
328 g_log (G_LOG_DOMAIN, \
329 G_LOG_LEVEL_CRITICAL, \
330 "file %s: line %d: assertion `%s' failed.\n" \
331 "There is a disparity between the internal view of the PsppSheetView,\n" \
332 "and the GtkTreeModel. This generally means that the model has changed\n"\
333 "without letting the view know. Any display from now on is likely to\n" \
334 "be incorrect.\n", \
335 __FILE__, \
336 __LINE__, \
337 #expr); \
338 return ret; \
339 }; }G_STMT_END
340
341 #define TREE_VIEW_INTERNAL_ASSERT_VOID(expr) G_STMT_START{ \
342 if (!(expr)) \
343 { \
344 g_log (G_LOG_DOMAIN, \
345 G_LOG_LEVEL_CRITICAL, \
346 "file %s: line %d: assertion '%s' failed.\n" \
347 "There is a disparity between the internal view of the PsppSheetView,\n" \
348 "and the GtkTreeModel. This generally means that the model has changed\n"\
349 "without letting the view know. Any display from now on is likely to\n" \
350 "be incorrect.\n", \
351 __FILE__, \
352 __LINE__, \
353 #expr); \
354 return; \
355 }; }G_STMT_END
356 #endif
357
358
359 /* functions that shouldn't be exported */
360 void _pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection,
361 int node,
362 GtkTreePath *path,
363 GtkTreeSelectMode mode,
364 gboolean override_browse_mode);
365 void _pspp_sheet_selection_emit_changed (PsppSheetSelection *selection);
366 void _pspp_sheet_view_find_node (PsppSheetView *tree_view,
367 GtkTreePath *path,
368 int *node);
369 GtkTreePath *_pspp_sheet_view_find_path (PsppSheetView *tree_view,
370 int node);
371 void _pspp_sheet_view_child_move_resize (PsppSheetView *tree_view,
372 GtkWidget *widget,
373 gint x,
374 gint y,
375 gint width,
376 gint height);
377 void _pspp_sheet_view_queue_draw_node (PsppSheetView *tree_view,
378 int node,
379 const GdkRectangle *clip_rect);
380
381 void _pspp_sheet_view_column_realize_button (PsppSheetViewColumn *column);
382 void _pspp_sheet_view_column_unrealize_button (PsppSheetViewColumn *column);
383 void _pspp_sheet_view_column_set_tree_view (PsppSheetViewColumn *column,
384 PsppSheetView *tree_view);
385 void _pspp_sheet_view_column_unset_model (PsppSheetViewColumn *column,
386 GtkTreeModel *old_model);
387 void _pspp_sheet_view_column_unset_tree_view (PsppSheetViewColumn *column);
388 void _pspp_sheet_view_column_set_width (PsppSheetViewColumn *column,
389 gint width);
390 void _pspp_sheet_view_column_start_drag (PsppSheetView *tree_view,
391 PsppSheetViewColumn *column);
392 gboolean _pspp_sheet_view_column_cell_event (PsppSheetViewColumn *tree_column,
393 GtkCellEditable **editable_widget,
394 GdkEvent *event,
395 gchar *path_string,
396 const GdkRectangle *background_area,
397 const GdkRectangle *cell_area,
398 guint flags);
399 void _pspp_sheet_view_column_start_editing (PsppSheetViewColumn *tree_column,
400 GtkCellEditable *editable_widget);
401 void _pspp_sheet_view_column_stop_editing (PsppSheetViewColumn *tree_column);
402 void _pspp_sheet_view_install_mark_rows_col_dirty (PsppSheetView *tree_view);
403 void _pspp_sheet_view_column_autosize (PsppSheetView *tree_view,
404 PsppSheetViewColumn *column);
405
406 gboolean _pspp_sheet_view_column_has_editable_cell (PsppSheetViewColumn *column);
407 GtkCellRenderer *_pspp_sheet_view_column_get_edited_cell (PsppSheetViewColumn *column);
408 gint _pspp_sheet_view_column_count_special_cells (PsppSheetViewColumn *column);
409 GtkCellRenderer *_pspp_sheet_view_column_get_cell_at_pos (PsppSheetViewColumn *column,
410 gint x);
411
412 PsppSheetSelection* _pspp_sheet_selection_new (void);
413 PsppSheetSelection* _pspp_sheet_selection_new_with_tree_view (PsppSheetView *tree_view);
414 void _pspp_sheet_selection_set_tree_view (PsppSheetSelection *selection,
415 PsppSheetView *tree_view);
416
417 void _pspp_sheet_view_column_cell_render (PsppSheetViewColumn *tree_column,
418 GdkWindow *window,
419 const GdkRectangle *background_area,
420 const GdkRectangle *cell_area,
421 const GdkRectangle *expose_area,
422 guint flags);
423 void _pspp_sheet_view_column_get_focus_area (PsppSheetViewColumn *tree_column,
424 const GdkRectangle *background_area,
425 const GdkRectangle *cell_area,
426 GdkRectangle *focus_area);
427 gboolean _pspp_sheet_view_column_cell_focus (PsppSheetViewColumn *tree_column,
428 gint direction,
429 gboolean left,
430 gboolean right);
431 void _pspp_sheet_view_column_cell_draw_focus (PsppSheetViewColumn *tree_column,
432 GdkWindow *window,
433 const GdkRectangle *background_area,
434 const GdkRectangle *cell_area,
435 const GdkRectangle *expose_area,
436 guint flags);
437 void _pspp_sheet_view_column_cell_set_dirty (PsppSheetViewColumn *tree_column);
438 void _pspp_sheet_view_column_get_neighbor_sizes (PsppSheetViewColumn *column,
439 GtkCellRenderer *cell,
440 gint *left,
441 gint *right);
442
443 gboolean pspp_sheet_view_node_is_selected (PsppSheetView *tree_view,
444 int node);
445 void pspp_sheet_view_node_select (PsppSheetView *tree_view,
446 int node);
447 void pspp_sheet_view_node_unselect (PsppSheetView *tree_view,
448 int node);
449
450 gint
451 pspp_sheet_view_node_next (PsppSheetView *tree_view,
452 gint node);
453 gint
454 pspp_sheet_view_node_prev (PsppSheetView *tree_view,
455 gint node);
456
457 #endif /* __GTK_TREE_PRIVATE_H__ */
458
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeselection.h
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #include <config.h>
36
37 #include "ui/gui/pspp-sheet-private.h"
38
39 #include <gtk/gtk.h>
40 #include <string.h>
41
42 #include "ui/gui/pspp-sheet-selection.h"
43
44 #include "libpspp/range-set.h"
45
46 static void pspp_sheet_selection_finalize (GObject *object);
47 static gint pspp_sheet_selection_real_select_all (PsppSheetSelection *selection);
48 static gint pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection);
49 static gint pspp_sheet_selection_real_select_node (PsppSheetSelection *selection,
50 int node,
51 gboolean select);
52
53 enum
54 {
55 CHANGED,
56 LAST_SIGNAL
57 };
58
59 static guint tree_selection_signals [LAST_SIGNAL] = { 0 };
60
61 G_DEFINE_TYPE (PsppSheetSelection, pspp_sheet_selection, G_TYPE_OBJECT)
62
63 static void
64 pspp_sheet_selection_class_init (PsppSheetSelectionClass *class)
65 {
66 GObjectClass *object_class;
67
68 object_class = (GObjectClass*) class;
69
70 object_class->finalize = pspp_sheet_selection_finalize;
71 class->changed = NULL;
72
73 tree_selection_signals[CHANGED] =
74 g_signal_new ("changed",
75 G_OBJECT_CLASS_TYPE (object_class),
76 G_SIGNAL_RUN_FIRST,
77 G_STRUCT_OFFSET (PsppSheetSelectionClass, changed),
78 NULL, NULL,
79 g_cclosure_marshal_VOID__VOID,
80 G_TYPE_NONE, 0);
81 }
82
83 static void
84 pspp_sheet_selection_init (PsppSheetSelection *selection)
85 {
86 selection->type = PSPP_SHEET_SELECTION_SINGLE;
87 }
88
89 static void
90 pspp_sheet_selection_finalize (GObject *object)
91 {
92 G_OBJECT_CLASS (pspp_sheet_selection_parent_class)->finalize (object);
93 }
94
95 /**
96 * _pspp_sheet_selection_new:
97 *
98 * Creates a new #PsppSheetSelection object. This function should not be invoked,
99 * as each #PsppSheetView will create its own #PsppSheetSelection.
100 *
101 * Return value: A newly created #PsppSheetSelection object.
102 **/
103 PsppSheetSelection*
104 _pspp_sheet_selection_new (void)
105 {
106 PsppSheetSelection *selection;
107
108 selection = g_object_new (PSPP_TYPE_SHEET_SELECTION, NULL);
109
110 return selection;
111 }
112
113 /**
114 * _pspp_sheet_selection_new_with_tree_view:
115 * @tree_view: The #PsppSheetView.
116 *
117 * Creates a new #PsppSheetSelection object. This function should not be invoked,
118 * as each #PsppSheetView will create its own #PsppSheetSelection.
119 *
120 * Return value: A newly created #PsppSheetSelection object.
121 **/
122 PsppSheetSelection*
123 _pspp_sheet_selection_new_with_tree_view (PsppSheetView *tree_view)
124 {
125 PsppSheetSelection *selection;
126
127 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
128
129 selection = _pspp_sheet_selection_new ();
130 _pspp_sheet_selection_set_tree_view (selection, tree_view);
131
132 return selection;
133 }
134
135 /**
136 * _pspp_sheet_selection_set_tree_view:
137 * @selection: A #PsppSheetSelection.
138 * @tree_view: The #PsppSheetView.
139 *
140 * Sets the #PsppSheetView of @selection. This function should not be invoked, as
141 * it is used internally by #PsppSheetView.
142 **/
143 void
144 _pspp_sheet_selection_set_tree_view (PsppSheetSelection *selection,
145 PsppSheetView *tree_view)
146 {
147 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
148 if (tree_view != NULL)
149 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
150
151 selection->tree_view = tree_view;
152 }
153
154 /**
155 * pspp_sheet_selection_set_mode:
156 * @selection: A #PsppSheetSelection.
157 * @type: The selection mode
158 *
159 * Sets the selection mode of the @selection. If the previous type was
160 * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE, then the
161 * anchor is kept selected, if it was previously selected.
162 **/
163 void
164 pspp_sheet_selection_set_mode (PsppSheetSelection *selection,
165 PsppSheetSelectionMode type)
166 {
167 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
168
169 if (selection->type == type)
170 return;
171
172 if (type == PSPP_SHEET_SELECTION_NONE)
173 {
174 pspp_sheet_selection_unselect_all (selection);
175
176 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
177 selection->tree_view->priv->anchor = NULL;
178 }
179 else if (type == PSPP_SHEET_SELECTION_SINGLE ||
180 type == PSPP_SHEET_SELECTION_BROWSE)
181 {
182 int node = -1;
183 gint selected = FALSE;
184 GtkTreePath *anchor_path = NULL;
185
186 if (selection->tree_view->priv->anchor)
187 {
188 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
189
190 if (anchor_path)
191 {
192 _pspp_sheet_view_find_node (selection->tree_view,
193 anchor_path,
194 &node);
195
196 if (node >= 0 && pspp_sheet_view_node_is_selected (selection->tree_view, node))
197 selected = TRUE;
198 }
199 }
200
201 /* We do this so that we unconditionally unset all rows
202 */
203 pspp_sheet_selection_unselect_all (selection);
204
205 if (node >= 0 && selected)
206 _pspp_sheet_selection_internal_select_node (selection,
207 node,
208 anchor_path,
209 0,
210 FALSE);
211 if (anchor_path)
212 gtk_tree_path_free (anchor_path);
213 }
214
215 /* XXX unselect all columns when switching to/from rectangular selection? */
216
217 selection->type = type;
218 }
219
220 /**
221 * pspp_sheet_selection_get_mode:
222 * @selection: a #PsppSheetSelection
223 *
224 * Gets the selection mode for @selection. See
225 * pspp_sheet_selection_set_mode().
226 *
227 * Return value: the current selection mode
228 **/
229 PsppSheetSelectionMode
230 pspp_sheet_selection_get_mode (PsppSheetSelection *selection)
231 {
232 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), PSPP_SHEET_SELECTION_SINGLE);
233
234 return selection->type;
235 }
236
237 /**
238 * pspp_sheet_selection_get_tree_view:
239 * @selection: A #PsppSheetSelection
240 *
241 * Returns the tree view associated with @selection.
242 *
243 * Return value: A #PsppSheetView
244 **/
245 PsppSheetView *
246 pspp_sheet_selection_get_tree_view (PsppSheetSelection *selection)
247 {
248 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
249
250 return selection->tree_view;
251 }
252
253 /**
254 * pspp_sheet_selection_get_selected:
255 * @selection: A #PsppSheetSelection.
256 * @model: (out) (allow-none): A pointer to set to the #GtkTreeModel, or NULL.
257 * @iter: (allow-none): The #GtkTreeIter, or NULL.
258 *
259 * Sets @iter to the currently selected node if @selection is set to
260 * #PSPP_SHEET_SELECTION_SINGLE or #PSPP_SHEET_SELECTION_BROWSE. @iter may be
261 * NULL if you just want to test if @selection has any selected nodes. @model
262 * is filled with the current model as a convenience. This function will not
263 * work if @selection's mode is #PSPP_SHEET_SELECTION_MULTIPLE or
264 * #PSPP_SHEET_SELECTION_RECTANGLE.
265 *
266 * Return value: TRUE, if there is a selected node.
267 **/
268 gboolean
269 pspp_sheet_selection_get_selected (PsppSheetSelection *selection,
270 GtkTreeModel **model,
271 GtkTreeIter *iter)
272 {
273 int node;
274 GtkTreePath *anchor_path;
275 gboolean retval;
276
277 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
278 g_return_val_if_fail (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
279 selection->type != PSPP_SHEET_SELECTION_RECTANGLE,
280 FALSE);
281 g_return_val_if_fail (selection->tree_view != NULL, FALSE);
282
283 /* Clear the iter */
284 if (iter)
285 memset (iter, 0, sizeof (GtkTreeIter));
286
287 if (model)
288 *model = selection->tree_view->priv->model;
289
290 if (selection->tree_view->priv->anchor == NULL)
291 return FALSE;
292
293 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
294
295 if (anchor_path == NULL)
296 return FALSE;
297
298 retval = FALSE;
299
300 _pspp_sheet_view_find_node (selection->tree_view,
301 anchor_path,
302 &node);
303
304 if (pspp_sheet_view_node_is_selected (selection->tree_view, node))
305 {
306 /* we only want to return the anchor if it exists in the rbtree and
307 * is selected.
308 */
309 if (iter == NULL)
310 retval = TRUE;
311 else
312 retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
313 iter,
314 anchor_path);
315 }
316 else
317 {
318 /* We don't want to return the anchor if it isn't actually selected.
319 */
320 retval = FALSE;
321 }
322
323 gtk_tree_path_free (anchor_path);
324
325 return retval;
326 }
327
328 /**
329 * pspp_sheet_selection_get_selected_rows:
330 * @selection: A #PsppSheetSelection.
331 * @model: (allow-none): A pointer to set to the #GtkTreeModel, or NULL.
332 *
333 * Creates a list of path of all selected rows. Additionally, if you are
334 * planning on modifying the model after calling this function, you may
335 * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
336 * To do this, you can use gtk_tree_row_reference_new().
337 *
338 * To free the return value, use:
339 * |[
340 * g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
341 * g_list_free (list);
342 * ]|
343 *
344 * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row.
345 *
346 * Since: 2.2
347 **/
348 GList *
349 pspp_sheet_selection_get_selected_rows (PsppSheetSelection *selection,
350 GtkTreeModel **model)
351 {
352 const struct range_tower_node *node;
353 unsigned long int start;
354 GList *list = NULL;
355
356 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
357 g_return_val_if_fail (selection->tree_view != NULL, NULL);
358
359 if (model)
360 *model = selection->tree_view->priv->model;
361
362 if (selection->tree_view->priv->row_count == 0)
363 return NULL;
364
365 if (selection->type == PSPP_SHEET_SELECTION_NONE)
366 return NULL;
367 else if (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
368 selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
369 {
370 GtkTreeIter iter;
371
372 if (pspp_sheet_selection_get_selected (selection, NULL, &iter))
373 {
374 GtkTreePath *path;
375
376 path = gtk_tree_model_get_path (selection->tree_view->priv->model, &iter);
377 list = g_list_append (list, path);
378
379 return list;
380 }
381
382 return NULL;
383 }
384
385 RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
386 {
387 unsigned long int width = range_tower_node_get_width (node);
388 unsigned long int index;
389
390 for (index = start; index < start + width; index++)
391 list = g_list_prepend (list, gtk_tree_path_new_from_indices (index, -1));
392 }
393
394 return g_list_reverse (list);
395 }
396
397 /**
398 * pspp_sheet_selection_count_selected_rows:
399 * @selection: A #PsppSheetSelection.
400 *
401 * Returns the number of rows that have been selected in @tree.
402 *
403 * Return value: The number of rows selected.
404 *
405 * Since: 2.2
406 **/
407 gint
408 pspp_sheet_selection_count_selected_rows (PsppSheetSelection *selection)
409 {
410 const struct range_tower_node *node;
411 unsigned long int start;
412 gint count = 0;
413
414 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), 0);
415 g_return_val_if_fail (selection->tree_view != NULL, 0);
416
417 if (selection->tree_view->priv->row_count == 0)
418 return 0;
419
420 if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
421 selection->type == PSPP_SHEET_SELECTION_BROWSE)
422 {
423 if (pspp_sheet_selection_get_selected (selection, NULL, NULL))
424 return 1;
425 else
426 return 0;
427 }
428
429 count = 0;
430 RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
431 count += range_tower_node_get_width (node);
432
433 return count;
434 }
435
436 /* pspp_sheet_selection_selected_foreach helper */
437 static void
438 model_changed (gpointer data)
439 {
440 gboolean *stop = (gboolean *)data;
441
442 *stop = TRUE;
443 }
444
445 /**
446 * pspp_sheet_selection_selected_foreach:
447 * @selection: A #PsppSheetSelection.
448 * @func: The function to call for each selected node.
449 * @data: user data to pass to the function.
450 *
451 * Calls a function for each selected node. Note that you cannot modify
452 * the tree or selection from within this function. As a result,
453 * pspp_sheet_selection_get_selected_rows() might be more useful.
454 **/
455 void
456 pspp_sheet_selection_selected_foreach (PsppSheetSelection *selection,
457 PsppSheetSelectionForeachFunc func,
458 gpointer data)
459 {
460 const struct range_tower_node *node;
461 unsigned long int start;
462 GtkTreePath *path;
463 GtkTreeIter iter;
464 GtkTreeModel *model;
465
466 gulong inserted_id, deleted_id, reordered_id, changed_id;
467 gboolean stop = FALSE;
468
469 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
470 g_return_if_fail (selection->tree_view != NULL);
471
472 if (func == NULL ||
473 selection->tree_view->priv->row_count == 0)
474 return;
475
476 if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
477 selection->type == PSPP_SHEET_SELECTION_BROWSE)
478 {
479 if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
480 {
481 path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
482 gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
483 (* func) (selection->tree_view->priv->model, path, &iter, data);
484 gtk_tree_path_free (path);
485 }
486 return;
487 }
488
489 model = selection->tree_view->priv->model;
490 g_object_ref (model);
491
492 /* connect to signals to monitor changes in treemodel */
493 inserted_id = g_signal_connect_swapped (model, "row-inserted",
494 G_CALLBACK (model_changed),
495 &stop);
496 deleted_id = g_signal_connect_swapped (model, "row-deleted",
497 G_CALLBACK (model_changed),
498 &stop);
499 reordered_id = g_signal_connect_swapped (model, "rows-reordered",
500 G_CALLBACK (model_changed),
501 &stop);
502 changed_id = g_signal_connect_swapped (selection->tree_view, "notify::model",
503 G_CALLBACK (model_changed),
504 &stop);
505
506 RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
507 {
508 unsigned long int width = range_tower_node_get_width (node);
509 unsigned long int index;
510
511 for (index = start; index < start + width; index++)
512 {
513 GtkTreePath *path;
514 GtkTreeIter iter;
515
516 path = gtk_tree_path_new_from_indices (index, -1);
517 gtk_tree_model_get_iter (model, &iter, path);
518 (* func) (model, path, &iter, data);
519 gtk_tree_path_free (path);
520 }
521 }
522
523 g_signal_handler_disconnect (model, inserted_id);
524 g_signal_handler_disconnect (model, deleted_id);
525 g_signal_handler_disconnect (model, reordered_id);
526 g_signal_handler_disconnect (selection->tree_view, changed_id);
527 g_object_unref (model);
528
529 /* check if we have to spew a scary message */
530 if (stop)
531 g_warning ("The model has been modified from within pspp_sheet_selection_selected_foreach.\n"
532 "This function is for observing the selections of the tree only. If\n"
533 "you are trying to get all selected items from the tree, try using\n"
534 "pspp_sheet_selection_get_selected_rows instead.\n");
535 }
536
537 /**
538 * pspp_sheet_selection_select_path:
539 * @selection: A #PsppSheetSelection.
540 * @path: The #GtkTreePath to be selected.
541 *
542 * Select the row at @path.
543 **/
544 void
545 pspp_sheet_selection_select_path (PsppSheetSelection *selection,
546 GtkTreePath *path)
547 {
548 int node;
549 GtkTreeSelectMode mode = 0;
550
551 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
552 g_return_if_fail (selection->tree_view != NULL);
553 g_return_if_fail (path != NULL);
554
555 _pspp_sheet_view_find_node (selection->tree_view,
556 path,
557 &node);
558
559 if (node < 0 || pspp_sheet_view_node_is_selected (selection->tree_view, node))
560 return;
561
562 if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
563 selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
564 mode = GTK_TREE_SELECT_MODE_TOGGLE;
565
566 _pspp_sheet_selection_internal_select_node (selection,
567 node,
568 path,
569 mode,
570 FALSE);
571 }
572
573 /**
574 * pspp_sheet_selection_unselect_path:
575 * @selection: A #PsppSheetSelection.
576 * @path: The #GtkTreePath to be unselected.
577 *
578 * Unselects the row at @path.
579 **/
580 void
581 pspp_sheet_selection_unselect_path (PsppSheetSelection *selection,
582 GtkTreePath *path)
583 {
584 int node;
585
586 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
587 g_return_if_fail (selection->tree_view != NULL);
588 g_return_if_fail (path != NULL);
589
590 _pspp_sheet_view_find_node (selection->tree_view,
591 path,
592 &node);
593
594 if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
595 return;
596
597 _pspp_sheet_selection_internal_select_node (selection,
598 node,
599 path,
600 GTK_TREE_SELECT_MODE_TOGGLE,
601 TRUE);
602 }
603
604 /**
605 * pspp_sheet_selection_select_iter:
606 * @selection: A #PsppSheetSelection.
607 * @iter: The #GtkTreeIter to be selected.
608 *
609 * Selects the specified iterator.
610 **/
611 void
612 pspp_sheet_selection_select_iter (PsppSheetSelection *selection,
613 GtkTreeIter *iter)
614 {
615 GtkTreePath *path;
616
617 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
618 g_return_if_fail (selection->tree_view != NULL);
619 g_return_if_fail (selection->tree_view->priv->model != NULL);
620 g_return_if_fail (iter != NULL);
621
622 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
623 iter);
624
625 if (path == NULL)
626 return;
627
628 pspp_sheet_selection_select_path (selection, path);
629 gtk_tree_path_free (path);
630 }
631
632
633 /**
634 * pspp_sheet_selection_unselect_iter:
635 * @selection: A #PsppSheetSelection.
636 * @iter: The #GtkTreeIter to be unselected.
637 *
638 * Unselects the specified iterator.
639 **/
640 void
641 pspp_sheet_selection_unselect_iter (PsppSheetSelection *selection,
642 GtkTreeIter *iter)
643 {
644 GtkTreePath *path;
645
646 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
647 g_return_if_fail (selection->tree_view != NULL);
648 g_return_if_fail (selection->tree_view->priv->model != NULL);
649 g_return_if_fail (iter != NULL);
650
651 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
652 iter);
653
654 if (path == NULL)
655 return;
656
657 pspp_sheet_selection_unselect_path (selection, path);
658 gtk_tree_path_free (path);
659 }
660
661 /**
662 * pspp_sheet_selection_path_is_selected:
663 * @selection: A #PsppSheetSelection.
664 * @path: A #GtkTreePath to check selection on.
665 *
666 * Returns %TRUE if the row pointed to by @path is currently selected. If @path
667 * does not point to a valid location, %FALSE is returned
668 *
669 * Return value: %TRUE if @path is selected.
670 **/
671 gboolean
672 pspp_sheet_selection_path_is_selected (PsppSheetSelection *selection,
673 GtkTreePath *path)
674 {
675 int node;
676
677 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
678 g_return_val_if_fail (path != NULL, FALSE);
679 g_return_val_if_fail (selection->tree_view != NULL, FALSE);
680
681 if (selection->tree_view->priv->model == NULL)
682 return FALSE;
683
684 _pspp_sheet_view_find_node (selection->tree_view,
685 path,
686 &node);
687
688 if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
689 return FALSE;
690
691 return TRUE;
692 }
693
694 /**
695 * pspp_sheet_selection_iter_is_selected:
696 * @selection: A #PsppSheetSelection
697 * @iter: A valid #GtkTreeIter
698 *
699 * Returns %TRUE if the row at @iter is currently selected.
700 *
701 * Return value: %TRUE, if @iter is selected
702 **/
703 gboolean
704 pspp_sheet_selection_iter_is_selected (PsppSheetSelection *selection,
705 GtkTreeIter *iter)
706 {
707 GtkTreePath *path;
708 gboolean retval;
709
710 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
711 g_return_val_if_fail (iter != NULL, FALSE);
712 g_return_val_if_fail (selection->tree_view != NULL, FALSE);
713 g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
714
715 path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
716 if (path == NULL)
717 return FALSE;
718
719 retval = pspp_sheet_selection_path_is_selected (selection, path);
720 gtk_tree_path_free (path);
721
722 return retval;
723 }
724
725
726 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
727 * can use it in other places without fear of the signal being emitted.
728 */
729 static gint
730 pspp_sheet_selection_real_select_all (PsppSheetSelection *selection)
731 {
732 const struct range_tower_node *node;
733 int row_count = selection->tree_view->priv->row_count;
734
735 if (row_count == 0)
736 return FALSE;
737
738 node = range_tower_first (selection->tree_view->priv->selected);
739 if (node
740 && range_tower_node_get_start (node) == 0
741 && range_tower_node_get_width (node) >= row_count)
742 return FALSE;
743
744 range_tower_set1 (selection->tree_view->priv->selected, 0, row_count);
745 pspp_sheet_selection_select_all_columns (selection);
746
747 /* XXX we could invalidate individual visible rows instead */
748 gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
749
750 return TRUE;
751 }
752
753 /**
754 * pspp_sheet_selection_select_all:
755 * @selection: A #PsppSheetSelection.
756 *
757 * Selects all the nodes and column. @selection must be set to
758 * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE mode.
759 **/
760 void
761 pspp_sheet_selection_select_all (PsppSheetSelection *selection)
762 {
763 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
764 g_return_if_fail (selection->tree_view != NULL);
765
766 if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
767 return;
768
769 g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
770 selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
771
772 if (pspp_sheet_selection_real_select_all (selection))
773 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
774 }
775
776 static gint
777 pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection)
778 {
779 if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
780 selection->type == PSPP_SHEET_SELECTION_BROWSE)
781 {
782 int node = -1;
783 GtkTreePath *anchor_path;
784
785 if (selection->tree_view->priv->anchor == NULL)
786 return FALSE;
787
788 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
789
790 if (anchor_path == NULL)
791 return FALSE;
792
793 _pspp_sheet_view_find_node (selection->tree_view,
794 anchor_path,
795 &node);
796
797 gtk_tree_path_free (anchor_path);
798
799 if (node < 0)
800 return FALSE;
801
802 if (pspp_sheet_view_node_is_selected (selection->tree_view, node))
803 {
804 if (pspp_sheet_selection_real_select_node (selection, node, FALSE))
805 {
806 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
807 selection->tree_view->priv->anchor = NULL;
808 return TRUE;
809 }
810 }
811 return FALSE;
812 }
813 else if (range_tower_is_empty (selection->tree_view->priv->selected))
814 return FALSE;
815 else
816 {
817 range_tower_set0 (selection->tree_view->priv->selected, 0, ULONG_MAX);
818 pspp_sheet_selection_unselect_all_columns (selection);
819
820 /* XXX we could invalidate individual visible rows instead */
821 gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
822
823 return TRUE;
824 }
825 }
826
827 /**
828 * pspp_sheet_selection_unselect_all:
829 * @selection: A #PsppSheetSelection.
830 *
831 * Unselects all the nodes and columns.
832 **/
833 void
834 pspp_sheet_selection_unselect_all (PsppSheetSelection *selection)
835 {
836 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
837 g_return_if_fail (selection->tree_view != NULL);
838
839 if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
840 return;
841
842 if (pspp_sheet_selection_real_unselect_all (selection))
843 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
844 }
845
846 enum
847 {
848 RANGE_SELECT,
849 RANGE_UNSELECT
850 };
851
852 static gint
853 pspp_sheet_selection_real_modify_range (PsppSheetSelection *selection,
854 gint mode,
855 GtkTreePath *start_path,
856 GtkTreePath *end_path)
857 {
858 int start_node, end_node;
859 GtkTreePath *anchor_path = NULL;
860 gboolean dirty = FALSE;
861
862 switch (gtk_tree_path_compare (start_path, end_path))
863 {
864 case 1:
865 _pspp_sheet_view_find_node (selection->tree_view,
866 end_path,
867 &start_node);
868 _pspp_sheet_view_find_node (selection->tree_view,
869 start_path,
870 &end_node);
871 anchor_path = start_path;
872 break;
873 case 0:
874 _pspp_sheet_view_find_node (selection->tree_view,
875 start_path,
876 &start_node);
877 end_node = start_node;
878 anchor_path = start_path;
879 break;
880 case -1:
881 _pspp_sheet_view_find_node (selection->tree_view,
882 start_path,
883 &start_node);
884 _pspp_sheet_view_find_node (selection->tree_view,
885 end_path,
886 &end_node);
887 anchor_path = start_path;
888 break;
889 }
890
891 g_return_val_if_fail (start_node >= 0, FALSE);
892 g_return_val_if_fail (end_node >= 0, FALSE);
893
894 if (anchor_path)
895 {
896 if (selection->tree_view->priv->anchor)
897 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
898
899 selection->tree_view->priv->anchor =
900 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view),
901 selection->tree_view->priv->model,
902 anchor_path);
903 }
904
905 do
906 {
907 dirty |= pspp_sheet_selection_real_select_node (selection, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
908
909 if (start_node == end_node)
910 break;
911
912 start_node = pspp_sheet_view_node_next (selection->tree_view, start_node);
913 if (start_node < 0)
914 {
915 /* we just ran out of tree. That means someone passed in bogus values.
916 */
917 return dirty;
918 }
919 }
920 while (TRUE);
921
922 return dirty;
923 }
924
925 /**
926 * pspp_sheet_selection_select_range:
927 * @selection: A #PsppSheetSelection.
928 * @start_path: The initial node of the range.
929 * @end_path: The final node of the range.
930 *
931 * Selects a range of nodes, determined by @start_path and @end_path inclusive.
932 * @selection must be set to #PSPP_SHEET_SELECTION_MULTIPLE or
933 * #PSPP_SHEET_SELECTION_RECTANGLE mode.
934 **/
935 void
936 pspp_sheet_selection_select_range (PsppSheetSelection *selection,
937 GtkTreePath *start_path,
938 GtkTreePath *end_path)
939 {
940 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
941 g_return_if_fail (selection->tree_view != NULL);
942 g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
943 selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
944 g_return_if_fail (selection->tree_view->priv->model != NULL);
945
946 if (pspp_sheet_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
947 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
948 }
949
950 /**
951 * pspp_sheet_selection_unselect_range:
952 * @selection: A #PsppSheetSelection.
953 * @start_path: The initial node of the range.
954 * @end_path: The initial node of the range.
955 *
956 * Unselects a range of nodes, determined by @start_path and @end_path
957 * inclusive.
958 *
959 * Since: 2.2
960 **/
961 void
962 pspp_sheet_selection_unselect_range (PsppSheetSelection *selection,
963 GtkTreePath *start_path,
964 GtkTreePath *end_path)
965 {
966 g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
967 g_return_if_fail (selection->tree_view != NULL);
968 g_return_if_fail (selection->tree_view->priv->model != NULL);
969
970 if (pspp_sheet_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
971 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
972 }
973
974 struct range_set *
975 pspp_sheet_selection_get_range_set (PsppSheetSelection *selection)
976 {
977 const struct range_tower_node *node;
978 unsigned long int start;
979 struct range_set *set;
980
981 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection),
982 range_set_create ());
983 g_return_val_if_fail (selection->tree_view != NULL, range_set_create ());
984
985 set = range_set_create ();
986 RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
987 range_set_set1 (set, start, range_tower_node_get_width (node));
988 return set;
989 }
990
991 /* Called internally by gtktreeview.c It handles actually selecting the tree.
992 */
993
994 /*
995 * docs about the 'override_browse_mode', we set this flag when we want to
996 * unset select the node and override the select browse mode behaviour (that is
997 * 'one node should *always* be selected').
998 */
999 void
1000 _pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection,
1001 int node,
1002 GtkTreePath *path,
1003 GtkTreeSelectMode mode,
1004 gboolean override_browse_mode)
1005 {
1006 gint dirty = FALSE;
1007 GtkTreePath *anchor_path = NULL;
1008
1009 if (selection->type == PSPP_SHEET_SELECTION_NONE)
1010 return;
1011
1012 if (selection->tree_view->priv->anchor)
1013 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1014
1015 if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
1016 selection->type == PSPP_SHEET_SELECTION_BROWSE)
1017 {
1018 /* just unselect */
1019 if (selection->type == PSPP_SHEET_SELECTION_BROWSE && override_browse_mode)
1020 {
1021 dirty = pspp_sheet_selection_real_unselect_all (selection);
1022 }
1023 /* Did we try to select the same node again? */
1024 else if (selection->type == PSPP_SHEET_SELECTION_SINGLE &&
1025 anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
1026 {
1027 if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1028 {
1029 dirty = pspp_sheet_selection_real_unselect_all (selection);
1030 }
1031 }
1032 else
1033 {
1034 if (anchor_path)
1035 {
1036 dirty = pspp_sheet_selection_real_unselect_all (selection);
1037
1038 /* if dirty is TRUE at this point, we successfully unselected the
1039 * old one, and can then select the new one */
1040 if (dirty)
1041 {
1042 if (selection->tree_view->priv->anchor)
1043 {
1044 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1045 selection->tree_view->priv->anchor = NULL;
1046 }
1047
1048 if (pspp_sheet_selection_real_select_node (selection, node, TRUE))
1049 {
1050 selection->tree_view->priv->anchor =
1051 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1052 }
1053 }
1054 }
1055 else
1056 {
1057 if (pspp_sheet_selection_real_select_node (selection, node, TRUE))
1058 {
1059 dirty = TRUE;
1060 if (selection->tree_view->priv->anchor)
1061 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1062
1063 selection->tree_view->priv->anchor =
1064 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1065 }
1066 }
1067 }
1068 }
1069 else if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
1070 selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
1071 {
1072 if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND
1073 && (anchor_path == NULL))
1074 {
1075 if (selection->tree_view->priv->anchor)
1076 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1077
1078 selection->tree_view->priv->anchor =
1079 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1080 dirty = pspp_sheet_selection_real_select_node (selection, node, TRUE);
1081 }
1082 else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE))
1083 {
1084 pspp_sheet_selection_select_range (selection,
1085 anchor_path,
1086 path);
1087 }
1088 else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
1089 {
1090 bool selected = pspp_sheet_view_node_is_selected (selection->tree_view, node);
1091 if (selection->tree_view->priv->anchor)
1092 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1093
1094 selection->tree_view->priv->anchor =
1095 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1096
1097 if (selected)
1098 dirty |= pspp_sheet_selection_real_select_node (selection, node, FALSE);
1099 else
1100 dirty |= pspp_sheet_selection_real_select_node (selection, node, TRUE);
1101 }
1102 else if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND)
1103 {
1104 dirty = pspp_sheet_selection_real_unselect_all (selection);
1105 dirty |= pspp_sheet_selection_real_modify_range (selection,
1106 RANGE_SELECT,
1107 anchor_path,
1108 path);
1109 }
1110 else
1111 {
1112 dirty = pspp_sheet_selection_real_unselect_all (selection);
1113
1114 if (selection->tree_view->priv->anchor)
1115 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1116
1117 selection->tree_view->priv->anchor =
1118 gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1119
1120 dirty |= pspp_sheet_selection_real_select_node (selection, node, TRUE);
1121 }
1122 }
1123
1124 if (anchor_path)
1125 gtk_tree_path_free (anchor_path);
1126
1127 if (dirty)
1128 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1129 }
1130
1131
1132 void
1133 _pspp_sheet_selection_emit_changed (PsppSheetSelection *selection)
1134 {
1135 g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
1136 }
1137
1138 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
1139 */
1140
1141 static gint
1142 pspp_sheet_selection_real_select_node (PsppSheetSelection *selection,
1143 int node,
1144 gboolean select)
1145 {
1146 select = !! select;
1147 if (pspp_sheet_view_node_is_selected (selection->tree_view, node) != select)
1148 {
1149 if (select)
1150 pspp_sheet_view_node_select (selection->tree_view, node);
1151 else
1152 pspp_sheet_view_node_unselect (selection->tree_view, node);
1153
1154 _pspp_sheet_view_queue_draw_node (selection->tree_view, node, NULL);
1155
1156 return TRUE;
1157 }
1158
1159 return FALSE;
1160 }
1161
1162 void
1163 pspp_sheet_selection_unselect_all_columns (PsppSheetSelection *selection)
1164 {
1165 PsppSheetView *sheet_view = selection->tree_view;
1166 gboolean changed;
1167 GList *list;
1168
1169 changed = FALSE;
1170 for (list = sheet_view->priv->columns; list; list = list->next)
1171 {
1172 PsppSheetViewColumn *column = list->data;
1173 if (column->selected)
1174 {
1175 column->selected = FALSE;
1176 changed = TRUE;
1177 }
1178 }
1179 if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
1180 {
1181 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1182 _pspp_sheet_selection_emit_changed (selection);
1183 }
1184 }
1185
1186 GList *
1187 pspp_sheet_selection_get_selected_columns (PsppSheetSelection *selection)
1188 {
1189 PsppSheetView *sheet_view = selection->tree_view;
1190 GList *selected_columns = NULL;
1191 GList *iter;
1192
1193 g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
1194 g_return_val_if_fail (selection->tree_view != NULL, NULL);
1195
1196 if (selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
1197 return NULL;
1198
1199 for (iter = sheet_view->priv->columns; iter; iter = iter->next)
1200 {
1201 PsppSheetViewColumn *column = iter->data;
1202 if (column->selected)
1203 selected_columns = g_list_prepend (selected_columns, column);
1204 }
1205 return g_list_reverse (selected_columns);
1206 }
1207
1208 gint
1209 pspp_sheet_selection_count_selected_columns (PsppSheetSelection *selection)
1210 {
1211 PsppSheetView *sheet_view = selection->tree_view;
1212 GList *list;
1213 gint n;
1214
1215 n = 0;
1216 for (list = sheet_view->priv->columns; list; list = list->next)
1217 {
1218 PsppSheetViewColumn *column = list->data;
1219 if (column->selected)
1220 n++;
1221 }
1222 return n;
1223 }
1224
1225 void
1226 pspp_sheet_selection_select_all_columns (PsppSheetSelection *selection)
1227 {
1228 PsppSheetView *sheet_view = selection->tree_view;
1229 gboolean changed;
1230 GList *list;
1231
1232 changed = FALSE;
1233 for (list = sheet_view->priv->columns; list; list = list->next)
1234 {
1235 PsppSheetViewColumn *column = list->data;
1236 if (!column->selected && column->selectable)
1237 {
1238 /* XXX should use pspp_sheet_view_column_set_selected() here (and
1239 elsewhere) but we want to call
1240 _pspp_sheet_selection_emit_changed() only once for all the
1241 columns. */
1242 column->selected = TRUE;
1243 changed = TRUE;
1244 }
1245 }
1246 if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
1247 {
1248 _pspp_sheet_selection_emit_changed (selection);
1249 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1250 }
1251 }
1252
1253 void
1254 pspp_sheet_selection_select_column (PsppSheetSelection *selection,
1255 PsppSheetViewColumn *column)
1256 {
1257 if (!column->selected && column->selectable)
1258 {
1259 column->selected = TRUE;
1260 if (selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
1261 {
1262 _pspp_sheet_selection_emit_changed (selection);
1263 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1264 }
1265 }
1266 }
1267
1268 void
1269 pspp_sheet_selection_select_column_range (PsppSheetSelection *selection,
1270 PsppSheetViewColumn *first,
1271 PsppSheetViewColumn *last)
1272 {
1273 PsppSheetView *sheet_view = selection->tree_view;
1274 gboolean in_range;
1275 gboolean changed;
1276 GList *list;
1277
1278 in_range = FALSE;
1279 changed = FALSE;
1280 for (list = sheet_view->priv->columns; list; list = list->next)
1281 {
1282 PsppSheetViewColumn *column = list->data;
1283 gboolean c0 = column == first;
1284 gboolean c1 = column == last;
1285
1286 if (in_range || c0 || c1)
1287 {
1288 if (!column->selected && column->selectable)
1289 {
1290 column->selected = TRUE;
1291 changed = TRUE;
1292 }
1293 }
1294
1295 in_range = in_range ^ c0 ^ c1;
1296 }
1297 if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
1298 {
1299 _pspp_sheet_selection_emit_changed (selection);
1300 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1301 }
1302 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeselection.h
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #ifndef __PSPP_SHEET_SELECTION_H__
36 #define __PSPP_SHEET_SELECTION_H__
37
38 #include <gtk/gtk.h>
39
40 G_BEGIN_DECLS
41
42
43 #define PSPP_TYPE_SHEET_SELECTION (pspp_sheet_selection_get_type ())
44 #define PSPP_SHEET_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelection))
45 #define PSPP_SHEET_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelectionClass))
46 #define PSPP_IS_SHEET_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_SELECTION))
47 #define PSPP_IS_SHEET_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_SELECTION))
48 #define PSPP_SHEET_SELECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelectionClass))
49
50 typedef enum
51 {
52 /* Same as GtkSelectionMode. */
53 PSPP_SHEET_SELECTION_NONE = GTK_SELECTION_NONE,
54 PSPP_SHEET_SELECTION_SINGLE = GTK_SELECTION_SINGLE,
55 PSPP_SHEET_SELECTION_BROWSE = GTK_SELECTION_BROWSE,
56 PSPP_SHEET_SELECTION_MULTIPLE = GTK_SELECTION_MULTIPLE,
57
58 /* PsppSheetView extension. */
59 PSPP_SHEET_SELECTION_RECTANGLE = 10
60 }
61 PsppSheetSelectionMode;
62
63 typedef gboolean (* PsppSheetSelectionFunc) (PsppSheetSelection *selection,
64 GtkTreeModel *model,
65 GtkTreePath *path,
66 gboolean path_currently_selected,
67 gpointer data);
68 typedef void (* PsppSheetSelectionForeachFunc) (GtkTreeModel *model,
69 GtkTreePath *path,
70 GtkTreeIter *iter,
71 gpointer data);
72
73 struct _PsppSheetSelection
74 {
75 GObject parent;
76
77 /*< private >*/
78
79 PsppSheetView *GSEAL (tree_view);
80 PsppSheetSelectionMode GSEAL (type);
81 };
82
83 struct _PsppSheetSelectionClass
84 {
85 GObjectClass parent_class;
86
87 void (* changed) (PsppSheetSelection *selection);
88
89 /* Padding for future expansion */
90 void (*_gtk_reserved1) (void);
91 void (*_gtk_reserved2) (void);
92 void (*_gtk_reserved3) (void);
93 void (*_gtk_reserved4) (void);
94 };
95
96
97 GType pspp_sheet_selection_get_type (void) G_GNUC_CONST;
98
99 void pspp_sheet_selection_set_mode (PsppSheetSelection *selection,
100 PsppSheetSelectionMode type);
101 PsppSheetSelectionMode pspp_sheet_selection_get_mode (PsppSheetSelection *selection);
102 void pspp_sheet_selection_set_select_function (PsppSheetSelection *selection,
103 PsppSheetSelectionFunc func,
104 gpointer data,
105 GDestroyNotify destroy);
106 gpointer pspp_sheet_selection_get_user_data (PsppSheetSelection *selection);
107 PsppSheetView* pspp_sheet_selection_get_tree_view (PsppSheetSelection *selection);
108
109 PsppSheetSelectionFunc pspp_sheet_selection_get_select_function (PsppSheetSelection *selection);
110
111 /* Only meaningful if PSPP_SHEET_SELECTION_SINGLE or PSPP_SHEET_SELECTION_BROWSE is set */
112 /* Use selected_foreach or get_selected_rows for
113 PSPP_SHEET_SELECTION_MULTIPLE */
114 gboolean pspp_sheet_selection_get_selected (PsppSheetSelection *selection,
115 GtkTreeModel **model,
116 GtkTreeIter *iter);
117 GList * pspp_sheet_selection_get_selected_rows (PsppSheetSelection *selection,
118 GtkTreeModel **model);
119 gint pspp_sheet_selection_count_selected_rows (PsppSheetSelection *selection);
120 void pspp_sheet_selection_selected_foreach (PsppSheetSelection *selection,
121 PsppSheetSelectionForeachFunc func,
122 gpointer data);
123 void pspp_sheet_selection_select_path (PsppSheetSelection *selection,
124 GtkTreePath *path);
125 void pspp_sheet_selection_unselect_path (PsppSheetSelection *selection,
126 GtkTreePath *path);
127 void pspp_sheet_selection_select_iter (PsppSheetSelection *selection,
128 GtkTreeIter *iter);
129 void pspp_sheet_selection_unselect_iter (PsppSheetSelection *selection,
130 GtkTreeIter *iter);
131 gboolean pspp_sheet_selection_path_is_selected (PsppSheetSelection *selection,
132 GtkTreePath *path);
133 gboolean pspp_sheet_selection_iter_is_selected (PsppSheetSelection *selection,
134 GtkTreeIter *iter);
135 void pspp_sheet_selection_select_all (PsppSheetSelection *selection);
136 void pspp_sheet_selection_unselect_all (PsppSheetSelection *selection);
137 void pspp_sheet_selection_select_range (PsppSheetSelection *selection,
138 GtkTreePath *start_path,
139 GtkTreePath *end_path);
140 void pspp_sheet_selection_unselect_range (PsppSheetSelection *selection,
141 GtkTreePath *start_path,
142 GtkTreePath *end_path);
143 struct range_set *pspp_sheet_selection_get_range_set (PsppSheetSelection *selection);
144
145
146 GList * pspp_sheet_selection_get_selected_columns (PsppSheetSelection *selection);
147 gint pspp_sheet_selection_count_selected_columns (PsppSheetSelection *selection);
148 void pspp_sheet_selection_select_all_columns (PsppSheetSelection *selection);
149 void pspp_sheet_selection_unselect_all_columns (PsppSheetSelection *selection);
150 void pspp_sheet_selection_select_column (PsppSheetSelection *selection,
151 PsppSheetViewColumn *column);
152 void pspp_sheet_selection_select_column_range (PsppSheetSelection *selection,
153 PsppSheetViewColumn *first,
154 PsppSheetViewColumn *last);
155
156 G_END_DECLS
157
158 #endif /* __PSPP_SHEET_SELECTION_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeviewcolumn.c
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #include <config.h>
36
37 #include "ui/gui/pspp-sheet-private.h"
38
39 #include <errno.h>
40 #include <gtk/gtk.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "ui/gui/psppire-marshal.h"
45 #include "ui/gui/pspp-sheet-selection.h"
46 #include "ui/gui/pspp-widget-facade.h"
47
48 #define P_(STRING) STRING
49 #define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
50 #define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
51
52 enum
53 {
54 PROP_0,
55 PROP_VISIBLE,
56 PROP_RESIZABLE,
57 PROP_WIDTH,
58 PROP_SPACING,
59 PROP_FIXED_WIDTH,
60 PROP_MIN_WIDTH,
61 PROP_MAX_WIDTH,
62 PROP_TITLE,
63 PROP_EXPAND,
64 PROP_CLICKABLE,
65 PROP_WIDGET,
66 PROP_ALIGNMENT,
67 PROP_REORDERABLE,
68 PROP_SORT_INDICATOR,
69 PROP_SORT_ORDER,
70 PROP_SORT_COLUMN_ID,
71 PROP_QUICK_EDIT,
72 PROP_SELECTED,
73 PROP_SELECTABLE,
74 PROP_ROW_HEAD
75 };
76
77 enum
78 {
79 CLICKED,
80 QUERY_TOOLTIP,
81 POPUP_MENU,
82 BUTTON_PRESS_EVENT,
83 LAST_SIGNAL
84 };
85
86 typedef struct _PsppSheetViewColumnCellInfo PsppSheetViewColumnCellInfo;
87 struct _PsppSheetViewColumnCellInfo
88 {
89 GtkCellRenderer *cell;
90 GSList *attributes;
91 PsppSheetCellDataFunc func;
92 gpointer func_data;
93 GDestroyNotify destroy;
94 gint requested_width;
95 gint real_width;
96 guint expand : 1;
97 guint pack : 1;
98 guint has_focus : 1;
99 guint in_editing_mode : 1;
100 };
101
102 /* Type methods */
103 static void pspp_sheet_view_column_cell_layout_init (GtkCellLayoutIface *iface);
104
105 /* GObject methods */
106 static void pspp_sheet_view_column_set_property (GObject *object,
107 guint prop_id,
108 const GValue *value,
109 GParamSpec *pspec);
110 static void pspp_sheet_view_column_get_property (GObject *object,
111 guint prop_id,
112 GValue *value,
113 GParamSpec *pspec);
114 static void pspp_sheet_view_column_finalize (GObject *object);
115
116 /* GtkCellLayout implementation */
117 static void pspp_sheet_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
118 GtkCellRenderer *cell,
119 gboolean expand);
120 static void pspp_sheet_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
121 GtkCellRenderer *cell,
122 gboolean expand);
123 static void pspp_sheet_view_column_cell_layout_clear (GtkCellLayout *cell_layout);
124 static void pspp_sheet_view_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
125 GtkCellRenderer *cell,
126 const gchar *attribute,
127 gint column);
128 static void pspp_sheet_view_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
129 GtkCellRenderer *cell,
130 GtkCellLayoutDataFunc func,
131 gpointer func_data,
132 GDestroyNotify destroy);
133 static void pspp_sheet_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
134 GtkCellRenderer *cell);
135 static void pspp_sheet_view_column_cell_layout_reorder (GtkCellLayout *cell_layout,
136 GtkCellRenderer *cell,
137 gint position);
138 static GList *pspp_sheet_view_column_cell_layout_get_cells (GtkCellLayout *cell_layout);
139
140 /* Button handling code */
141 static void pspp_sheet_view_column_create_button (PsppSheetViewColumn *tree_column);
142 void pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column);
143
144 /* Button signal handlers */
145 static gint pspp_sheet_view_column_button_event (GtkWidget *widget,
146 GdkEvent *event,
147 gpointer data);
148 static void pspp_sheet_view_column_button_clicked (GtkWidget *widget,
149 gpointer data);
150 static void pspp_sheet_view_column_button_popup_menu (GtkWidget *widget,
151 gpointer data);
152 static gboolean pspp_sheet_view_column_mnemonic_activate (GtkWidget *widget,
153 gboolean group_cycling,
154 gpointer data);
155 static gboolean on_pspp_sheet_view_column_button_clicked (PsppSheetViewColumn *);
156 static gboolean on_pspp_sheet_view_column_button_press_event (PsppSheetViewColumn *,
157 GdkEventButton *);
158
159 /* Property handlers */
160 static void pspp_sheet_view_model_sort_column_changed (GtkTreeSortable *sortable,
161 PsppSheetViewColumn *tree_column);
162
163 /* Internal functions */
164 static void pspp_sheet_view_column_sort (PsppSheetViewColumn *tree_column,
165 gpointer data);
166 static void pspp_sheet_view_column_setup_sort_column_id_callback (PsppSheetViewColumn *tree_column);
167 static void pspp_sheet_view_column_set_attributesv (PsppSheetViewColumn *tree_column,
168 GtkCellRenderer *cell_renderer,
169 va_list args);
170 static PsppSheetViewColumnCellInfo *pspp_sheet_view_column_get_cell_info (PsppSheetViewColumn *tree_column,
171 GtkCellRenderer *cell_renderer);
172
173 /* cell list manipulation */
174 static GList *pspp_sheet_view_column_cell_first (PsppSheetViewColumn *tree_column);
175 static GList *pspp_sheet_view_column_cell_last (PsppSheetViewColumn *tree_column);
176 static GList *pspp_sheet_view_column_cell_next (PsppSheetViewColumn *tree_column,
177 GList *current);
178 static GList *pspp_sheet_view_column_cell_prev (PsppSheetViewColumn *tree_column,
179 GList *current);
180 static void pspp_sheet_view_column_clear_attributes_by_info (PsppSheetViewColumn *tree_column,
181 PsppSheetViewColumnCellInfo *info);
182 /* GtkBuildable implementation */
183 static void pspp_sheet_view_column_buildable_init (GtkBuildableIface *iface);
184
185 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
186
187 G_DEFINE_TYPE_WITH_CODE (PsppSheetViewColumn, pspp_sheet_view_column, GTK_TYPE_OBJECT,
188 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
189 pspp_sheet_view_column_cell_layout_init)
190 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
191 pspp_sheet_view_column_buildable_init))
192
193
194 static void
195 pspp_sheet_view_column_class_init (PsppSheetViewColumnClass *class)
196 {
197 GObjectClass *object_class;
198
199 object_class = (GObjectClass*) class;
200
201 class->clicked = on_pspp_sheet_view_column_button_clicked;
202 class->button_press_event = on_pspp_sheet_view_column_button_press_event;
203
204 object_class->finalize = pspp_sheet_view_column_finalize;
205 object_class->set_property = pspp_sheet_view_column_set_property;
206 object_class->get_property = pspp_sheet_view_column_get_property;
207
208 tree_column_signals[CLICKED] =
209 g_signal_new ("clicked",
210 G_OBJECT_CLASS_TYPE (object_class),
211 G_SIGNAL_RUN_LAST,
212 G_STRUCT_OFFSET (PsppSheetViewColumnClass, clicked),
213 g_signal_accumulator_true_handled, NULL,
214 psppire_marshal_BOOLEAN__VOID,
215 G_TYPE_BOOLEAN, 0);
216
217 tree_column_signals[POPUP_MENU] =
218 g_signal_new ("popup-menu",
219 G_OBJECT_CLASS_TYPE (object_class),
220 G_SIGNAL_RUN_LAST,
221 0,
222 NULL, NULL,
223 g_cclosure_marshal_VOID__VOID,
224 G_TYPE_NONE, 0);
225
226 tree_column_signals[QUERY_TOOLTIP] =
227 g_signal_new ("query-tooltip",
228 G_OBJECT_CLASS_TYPE (object_class),
229 G_SIGNAL_RUN_LAST,
230 0,
231 g_signal_accumulator_true_handled, NULL,
232 psppire_marshal_BOOLEAN__OBJECT,
233 G_TYPE_BOOLEAN, 1,
234 GTK_TYPE_TOOLTIP);
235
236 tree_column_signals[BUTTON_PRESS_EVENT] =
237 g_signal_new ("button-press-event",
238 G_OBJECT_CLASS_TYPE (object_class),
239 G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
240 G_STRUCT_OFFSET (PsppSheetViewColumnClass, button_press_event),
241 g_signal_accumulator_true_handled, NULL,
242 psppire_marshal_BOOLEAN__BOXED,
243 G_TYPE_BOOLEAN, 1,
244 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
245
246 g_object_class_install_property (object_class,
247 PROP_VISIBLE,
248 g_param_spec_boolean ("visible",
249 P_("Visible"),
250 P_("Whether to display the column"),
251 TRUE,
252 GTK_PARAM_READWRITE));
253
254 g_object_class_install_property (object_class,
255 PROP_RESIZABLE,
256 g_param_spec_boolean ("resizable",
257 P_("Resizable"),
258 P_("Column is user-resizable"),
259 FALSE,
260 GTK_PARAM_READWRITE));
261
262 g_object_class_install_property (object_class,
263 PROP_WIDTH,
264 g_param_spec_int ("width",
265 P_("Width"),
266 P_("Current width of the column"),
267 0,
268 G_MAXINT,
269 0,
270 GTK_PARAM_READABLE));
271 g_object_class_install_property (object_class,
272 PROP_SPACING,
273 g_param_spec_int ("spacing",
274 P_("Spacing"),
275 P_("Space which is inserted between cells"),
276 0,
277 G_MAXINT,
278 0,
279 GTK_PARAM_READWRITE));
280
281 g_object_class_install_property (object_class,
282 PROP_FIXED_WIDTH,
283 g_param_spec_int ("fixed-width",
284 P_("Fixed Width"),
285 P_("Current fixed width of the column"),
286 1,
287 G_MAXINT,
288 100,
289 GTK_PARAM_READWRITE));
290
291 g_object_class_install_property (object_class,
292 PROP_MIN_WIDTH,
293 g_param_spec_int ("min-width",
294 P_("Minimum Width"),
295 P_("Minimum allowed width of the column"),
296 -1,
297 G_MAXINT,
298 -1,
299 GTK_PARAM_READWRITE));
300
301 g_object_class_install_property (object_class,
302 PROP_MAX_WIDTH,
303 g_param_spec_int ("max-width",
304 P_("Maximum Width"),
305 P_("Maximum allowed width of the column"),
306 -1,
307 G_MAXINT,
308 -1,
309 GTK_PARAM_READWRITE));
310
311 g_object_class_install_property (object_class,
312 PROP_TITLE,
313 g_param_spec_string ("title",
314 P_("Title"),
315 P_("Title to appear in column header"),
316 "",
317 GTK_PARAM_READWRITE));
318
319 g_object_class_install_property (object_class,
320 PROP_EXPAND,
321 g_param_spec_boolean ("expand",
322 P_("Expand"),
323 P_("Column gets share of extra width allocated to the widget"),
324 FALSE,
325 GTK_PARAM_READWRITE));
326
327 g_object_class_install_property (object_class,
328 PROP_CLICKABLE,
329 g_param_spec_boolean ("clickable",
330 P_("Clickable"),
331 P_("Whether the header can be clicked"),
332 FALSE,
333 GTK_PARAM_READWRITE));
334
335
336 g_object_class_install_property (object_class,
337 PROP_WIDGET,
338 g_param_spec_object ("widget",
339 P_("Widget"),
340 P_("Widget to put in column header button instead of column title"),
341 GTK_TYPE_WIDGET,
342 GTK_PARAM_READWRITE));
343
344 g_object_class_install_property (object_class,
345 PROP_ALIGNMENT,
346 g_param_spec_float ("alignment",
347 P_("Alignment"),
348 P_("X Alignment of the column header text or widget"),
349 0.0,
350 1.0,
351 0.0,
352 GTK_PARAM_READWRITE));
353
354 g_object_class_install_property (object_class,
355 PROP_REORDERABLE,
356 g_param_spec_boolean ("reorderable",
357 P_("Reorderable"),
358 P_("Whether the column can be reordered around the headers"),
359 FALSE,
360 GTK_PARAM_READWRITE));
361
362 g_object_class_install_property (object_class,
363 PROP_SORT_INDICATOR,
364 g_param_spec_boolean ("sort-indicator",
365 P_("Sort indicator"),
366 P_("Whether to show a sort indicator"),
367 FALSE,
368 GTK_PARAM_READWRITE));
369
370 g_object_class_install_property (object_class,
371 PROP_SORT_ORDER,
372 g_param_spec_enum ("sort-order",
373 P_("Sort order"),
374 P_("Sort direction the sort indicator should indicate"),
375 GTK_TYPE_SORT_TYPE,
376 GTK_SORT_ASCENDING,
377 GTK_PARAM_READWRITE));
378
379 /**
380 * PsppSheetViewColumn:sort-column-id:
381 *
382 * Logical sort column ID this column sorts on when selected for sorting. Setting the sort column ID makes the column header
383 * clickable. Set to %-1 to make the column unsortable.
384 *
385 * Since: 2.18
386 **/
387 g_object_class_install_property (object_class,
388 PROP_SORT_COLUMN_ID,
389 g_param_spec_int ("sort-column-id",
390 P_("Sort column ID"),
391 P_("Logical sort column ID this column sorts on when selected for sorting"),
392 -1,
393 G_MAXINT,
394 -1,
395 GTK_PARAM_READWRITE));
396
397 g_object_class_install_property (object_class,
398 PROP_QUICK_EDIT,
399 g_param_spec_boolean ("quick-edit",
400 P_("Quick edit"),
401 P_("If true, editing starts upon the first click in the column. If false, the first click selects the column and a second click is needed to begin editing. This has no effect on cells that are not editable."),
402 TRUE,
403 GTK_PARAM_READWRITE));
404
405 g_object_class_install_property (object_class,
406 PROP_SELECTED,
407 g_param_spec_boolean ("selected",
408 P_("Selected"),
409 P_("If true, this column is selected as part of a rectangular selection."),
410 FALSE,
411 GTK_PARAM_READWRITE));
412
413 g_object_class_install_property (object_class,
414 PROP_SELECTABLE,
415 g_param_spec_boolean ("selectable",
416 P_("Selectable"),
417 P_("If true, this column may be selected as part of a rectangular selection."),
418 TRUE,
419 GTK_PARAM_READWRITE));
420
421 g_object_class_install_property (object_class,
422 PROP_ROW_HEAD,
423 g_param_spec_boolean ("row-head",
424 P_("Row head"),
425 P_("If true, this column is a \"row head\", equivalent to a column head. If rectangular selection is enabled, then shift+click and control+click in the column select row ranges and toggle row selection, respectively. The column should ordinarily include a button cell; clicking on the button will select the row (and deselect all other rows)."),
426 FALSE,
427 GTK_PARAM_READWRITE));
428 }
429
430 static void
431 pspp_sheet_view_column_buildable_init (GtkBuildableIface *iface)
432 {
433 iface->add_child = _gtk_cell_layout_buildable_add_child;
434 iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
435 iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
436 }
437
438 static void
439 pspp_sheet_view_column_cell_layout_init (GtkCellLayoutIface *iface)
440 {
441 iface->pack_start = pspp_sheet_view_column_cell_layout_pack_start;
442 iface->pack_end = pspp_sheet_view_column_cell_layout_pack_end;
443 iface->clear = pspp_sheet_view_column_cell_layout_clear;
444 iface->add_attribute = pspp_sheet_view_column_cell_layout_add_attribute;
445 iface->set_cell_data_func = pspp_sheet_view_column_cell_layout_set_cell_data_func;
446 iface->clear_attributes = pspp_sheet_view_column_cell_layout_clear_attributes;
447 iface->reorder = pspp_sheet_view_column_cell_layout_reorder;
448 iface->get_cells = pspp_sheet_view_column_cell_layout_get_cells;
449 }
450
451 static void
452 pspp_sheet_view_column_init (PsppSheetViewColumn *tree_column)
453 {
454 tree_column->button = NULL;
455 tree_column->xalign = 0.0;
456 tree_column->width = 0;
457 tree_column->spacing = 0;
458 tree_column->requested_width = -1;
459 tree_column->min_width = -1;
460 tree_column->max_width = -1;
461 tree_column->resized_width = 0;
462 tree_column->visible = TRUE;
463 tree_column->resizable = FALSE;
464 tree_column->expand = FALSE;
465 tree_column->clickable = FALSE;
466 tree_column->dirty = TRUE;
467 tree_column->selected = FALSE;
468 tree_column->selectable = TRUE;
469 tree_column->row_head = FALSE;
470 tree_column->sort_order = GTK_SORT_ASCENDING;
471 tree_column->show_sort_indicator = FALSE;
472 tree_column->property_changed_signal = 0;
473 tree_column->sort_clicked_signal = 0;
474 tree_column->sort_column_changed_signal = 0;
475 tree_column->sort_column_id = -1;
476 tree_column->reorderable = FALSE;
477 tree_column->maybe_reordered = FALSE;
478 tree_column->fixed_width = 1;
479 tree_column->use_resized_width = FALSE;
480 tree_column->title = g_strdup ("");
481 tree_column->quick_edit = TRUE;
482 tree_column->need_button = FALSE;
483 }
484
485 static void
486 pspp_sheet_view_column_finalize (GObject *object)
487 {
488 PsppSheetViewColumn *tree_column = (PsppSheetViewColumn *) object;
489 GList *list;
490
491 for (list = tree_column->cell_list; list; list = list->next)
492 {
493 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
494
495 if (info->destroy)
496 {
497 GDestroyNotify d = info->destroy;
498
499 info->destroy = NULL;
500 d (info->func_data);
501 }
502 pspp_sheet_view_column_clear_attributes_by_info (tree_column, info);
503 g_object_unref (info->cell);
504 g_free (info);
505 }
506
507 g_free (tree_column->title);
508 g_list_free (tree_column->cell_list);
509
510 if (tree_column->child)
511 g_object_unref (tree_column->child);
512
513 G_OBJECT_CLASS (pspp_sheet_view_column_parent_class)->finalize (object);
514 }
515
516 static void
517 pspp_sheet_view_column_set_property (GObject *object,
518 guint prop_id,
519 const GValue *value,
520 GParamSpec *pspec)
521 {
522 PsppSheetViewColumn *tree_column;
523
524 tree_column = PSPP_SHEET_VIEW_COLUMN (object);
525
526 switch (prop_id)
527 {
528 case PROP_VISIBLE:
529 pspp_sheet_view_column_set_visible (tree_column,
530 g_value_get_boolean (value));
531 break;
532
533 case PROP_RESIZABLE:
534 pspp_sheet_view_column_set_resizable (tree_column,
535 g_value_get_boolean (value));
536 break;
537
538 case PROP_FIXED_WIDTH:
539 pspp_sheet_view_column_set_fixed_width (tree_column,
540 g_value_get_int (value));
541 break;
542
543 case PROP_MIN_WIDTH:
544 pspp_sheet_view_column_set_min_width (tree_column,
545 g_value_get_int (value));
546 break;
547
548 case PROP_MAX_WIDTH:
549 pspp_sheet_view_column_set_max_width (tree_column,
550 g_value_get_int (value));
551 break;
552
553 case PROP_SPACING:
554 pspp_sheet_view_column_set_spacing (tree_column,
555 g_value_get_int (value));
556 break;
557
558 case PROP_TITLE:
559 pspp_sheet_view_column_set_title (tree_column,
560 g_value_get_string (value));
561 break;
562
563 case PROP_EXPAND:
564 pspp_sheet_view_column_set_expand (tree_column,
565 g_value_get_boolean (value));
566 break;
567
568 case PROP_CLICKABLE:
569 pspp_sheet_view_column_set_clickable (tree_column,
570 g_value_get_boolean (value));
571 break;
572
573 case PROP_WIDGET:
574 pspp_sheet_view_column_set_widget (tree_column,
575 (GtkWidget*) g_value_get_object (value));
576 break;
577
578 case PROP_ALIGNMENT:
579 pspp_sheet_view_column_set_alignment (tree_column,
580 g_value_get_float (value));
581 break;
582
583 case PROP_REORDERABLE:
584 pspp_sheet_view_column_set_reorderable (tree_column,
585 g_value_get_boolean (value));
586 break;
587
588 case PROP_SORT_INDICATOR:
589 pspp_sheet_view_column_set_sort_indicator (tree_column,
590 g_value_get_boolean (value));
591 break;
592
593 case PROP_SORT_ORDER:
594 pspp_sheet_view_column_set_sort_order (tree_column,
595 g_value_get_enum (value));
596 break;
597
598 case PROP_SORT_COLUMN_ID:
599 pspp_sheet_view_column_set_sort_column_id (tree_column,
600 g_value_get_int (value));
601 break;
602
603 case PROP_QUICK_EDIT:
604 pspp_sheet_view_column_set_quick_edit (tree_column,
605 g_value_get_boolean (value));
606 break;
607
608 case PROP_SELECTED:
609 pspp_sheet_view_column_set_selected (tree_column,
610 g_value_get_boolean (value));
611 break;
612
613 case PROP_SELECTABLE:
614 pspp_sheet_view_column_set_selectable (tree_column,
615 g_value_get_boolean (value));
616 break;
617
618 case PROP_ROW_HEAD:
619 pspp_sheet_view_column_set_row_head (tree_column,
620 g_value_get_boolean (value));
621 break;
622
623 default:
624 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
625 break;
626 }
627 }
628
629 static void
630 pspp_sheet_view_column_get_property (GObject *object,
631 guint prop_id,
632 GValue *value,
633 GParamSpec *pspec)
634 {
635 PsppSheetViewColumn *tree_column;
636
637 tree_column = PSPP_SHEET_VIEW_COLUMN (object);
638
639 switch (prop_id)
640 {
641 case PROP_VISIBLE:
642 g_value_set_boolean (value,
643 pspp_sheet_view_column_get_visible (tree_column));
644 break;
645
646 case PROP_RESIZABLE:
647 g_value_set_boolean (value,
648 pspp_sheet_view_column_get_resizable (tree_column));
649 break;
650
651 case PROP_WIDTH:
652 g_value_set_int (value,
653 pspp_sheet_view_column_get_width (tree_column));
654 break;
655
656 case PROP_SPACING:
657 g_value_set_int (value,
658 pspp_sheet_view_column_get_spacing (tree_column));
659 break;
660
661 case PROP_FIXED_WIDTH:
662 g_value_set_int (value,
663 pspp_sheet_view_column_get_fixed_width (tree_column));
664 break;
665
666 case PROP_MIN_WIDTH:
667 g_value_set_int (value,
668 pspp_sheet_view_column_get_min_width (tree_column));
669 break;
670
671 case PROP_MAX_WIDTH:
672 g_value_set_int (value,
673 pspp_sheet_view_column_get_max_width (tree_column));
674 break;
675
676 case PROP_TITLE:
677 g_value_set_string (value,
678 pspp_sheet_view_column_get_title (tree_column));
679 break;
680
681 case PROP_EXPAND:
682 g_value_set_boolean (value,
683 pspp_sheet_view_column_get_expand (tree_column));
684 break;
685
686 case PROP_CLICKABLE:
687 g_value_set_boolean (value,
688 pspp_sheet_view_column_get_clickable (tree_column));
689 break;
690
691 case PROP_WIDGET:
692 g_value_set_object (value,
693 (GObject*) pspp_sheet_view_column_get_widget (tree_column));
694 break;
695
696 case PROP_ALIGNMENT:
697 g_value_set_float (value,
698 pspp_sheet_view_column_get_alignment (tree_column));
699 break;
700
701 case PROP_REORDERABLE:
702 g_value_set_boolean (value,
703 pspp_sheet_view_column_get_reorderable (tree_column));
704 break;
705
706 case PROP_SORT_INDICATOR:
707 g_value_set_boolean (value,
708 pspp_sheet_view_column_get_sort_indicator (tree_column));
709 break;
710
711 case PROP_SORT_ORDER:
712 g_value_set_enum (value,
713 pspp_sheet_view_column_get_sort_order (tree_column));
714 break;
715
716 case PROP_SORT_COLUMN_ID:
717 g_value_set_int (value,
718 pspp_sheet_view_column_get_sort_column_id (tree_column));
719 break;
720
721 case PROP_QUICK_EDIT:
722 g_value_set_boolean (value,
723 pspp_sheet_view_column_get_quick_edit (tree_column));
724 break;
725
726 case PROP_SELECTED:
727 g_value_set_boolean (value,
728 pspp_sheet_view_column_get_selected (tree_column));
729 break;
730
731 case PROP_SELECTABLE:
732 g_value_set_boolean (value,
733 pspp_sheet_view_column_get_selectable (tree_column));
734 break;
735
736 case PROP_ROW_HEAD:
737 g_value_set_boolean (value,
738 pspp_sheet_view_column_get_row_head (tree_column));
739 break;
740
741 default:
742 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
743 break;
744 }
745 }
746
747 /* Implementation of GtkCellLayout interface
748 */
749
750 static void
751 pspp_sheet_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
752 GtkCellRenderer *cell,
753 gboolean expand)
754 {
755 PsppSheetViewColumn *column;
756 PsppSheetViewColumnCellInfo *cell_info;
757
758 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
759 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
760 g_return_if_fail (! pspp_sheet_view_column_get_cell_info (column, cell));
761
762 g_object_ref_sink (cell);
763
764 cell_info = g_new0 (PsppSheetViewColumnCellInfo, 1);
765 cell_info->cell = cell;
766 cell_info->expand = expand ? TRUE : FALSE;
767 cell_info->pack = GTK_PACK_START;
768 cell_info->has_focus = 0;
769 cell_info->attributes = NULL;
770
771 column->cell_list = g_list_append (column->cell_list, cell_info);
772 }
773
774 static void
775 pspp_sheet_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
776 GtkCellRenderer *cell,
777 gboolean expand)
778 {
779 PsppSheetViewColumn *column;
780 PsppSheetViewColumnCellInfo *cell_info;
781
782 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
783 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
784 g_return_if_fail (! pspp_sheet_view_column_get_cell_info (column, cell));
785
786 g_object_ref_sink (cell);
787
788 cell_info = g_new0 (PsppSheetViewColumnCellInfo, 1);
789 cell_info->cell = cell;
790 cell_info->expand = expand ? TRUE : FALSE;
791 cell_info->pack = GTK_PACK_END;
792 cell_info->has_focus = 0;
793 cell_info->attributes = NULL;
794
795 column->cell_list = g_list_append (column->cell_list, cell_info);
796 }
797
798 static void
799 pspp_sheet_view_column_cell_layout_clear (GtkCellLayout *cell_layout)
800 {
801 PsppSheetViewColumn *column;
802
803 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
804 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
805
806 while (column->cell_list)
807 {
808 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)column->cell_list->data;
809
810 pspp_sheet_view_column_cell_layout_clear_attributes (cell_layout, info->cell);
811 g_object_unref (info->cell);
812 g_free (info);
813 column->cell_list = g_list_delete_link (column->cell_list,
814 column->cell_list);
815 }
816 }
817
818 static void
819 pspp_sheet_view_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
820 GtkCellRenderer *cell,
821 const gchar *attribute,
822 gint column)
823 {
824 PsppSheetViewColumn *tree_column;
825 PsppSheetViewColumnCellInfo *info;
826
827 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
828 tree_column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
829
830 info = pspp_sheet_view_column_get_cell_info (tree_column, cell);
831 g_return_if_fail (info != NULL);
832
833 info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
834 info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
835
836 if (tree_column->tree_view)
837 _pspp_sheet_view_column_cell_set_dirty (tree_column);
838 }
839
840 static void
841 pspp_sheet_view_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
842 GtkCellRenderer *cell,
843 GtkCellLayoutDataFunc func,
844 gpointer func_data,
845 GDestroyNotify destroy)
846 {
847 PsppSheetViewColumn *column;
848 PsppSheetViewColumnCellInfo *info;
849
850 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
851 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
852
853 info = pspp_sheet_view_column_get_cell_info (column, cell);
854 g_return_if_fail (info != NULL);
855
856 if (info->destroy)
857 {
858 GDestroyNotify d = info->destroy;
859
860 info->destroy = NULL;
861 d (info->func_data);
862 }
863
864 info->func = (PsppSheetCellDataFunc)func;
865 info->func_data = func_data;
866 info->destroy = destroy;
867
868 if (column->tree_view)
869 _pspp_sheet_view_column_cell_set_dirty (column);
870 }
871
872 static void
873 pspp_sheet_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
874 GtkCellRenderer *cell_renderer)
875 {
876 PsppSheetViewColumn *column;
877 PsppSheetViewColumnCellInfo *info;
878
879 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
880 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
881
882 info = pspp_sheet_view_column_get_cell_info (column, cell_renderer);
883 if (info)
884 pspp_sheet_view_column_clear_attributes_by_info (column, info);
885 }
886
887 static void
888 pspp_sheet_view_column_cell_layout_reorder (GtkCellLayout *cell_layout,
889 GtkCellRenderer *cell,
890 gint position)
891 {
892 GList *link;
893 PsppSheetViewColumn *column;
894 PsppSheetViewColumnCellInfo *info;
895
896 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
897 column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
898
899 info = pspp_sheet_view_column_get_cell_info (column, cell);
900
901 g_return_if_fail (info != NULL);
902 g_return_if_fail (position >= 0);
903
904 link = g_list_find (column->cell_list, info);
905
906 g_return_if_fail (link != NULL);
907
908 column->cell_list = g_list_delete_link (column->cell_list, link);
909 column->cell_list = g_list_insert (column->cell_list, info, position);
910
911 if (column->tree_view)
912 gtk_widget_queue_draw (column->tree_view);
913 }
914
915 static void
916 pspp_sheet_view_column_clear_attributes_by_info (PsppSheetViewColumn *tree_column,
917 PsppSheetViewColumnCellInfo *info)
918 {
919 GSList *list;
920
921 list = info->attributes;
922
923 while (list && list->next)
924 {
925 g_free (list->data);
926 list = list->next->next;
927 }
928 g_slist_free (info->attributes);
929 info->attributes = NULL;
930
931 if (tree_column->tree_view)
932 _pspp_sheet_view_column_cell_set_dirty (tree_column);
933 }
934
935 static gboolean
936 on_query_tooltip (GtkWidget *widget,
937 gint x,
938 gint y,
939 gboolean keyboard_mode,
940 GtkTooltip *tooltip,
941 gpointer user_data)
942 {
943 PsppSheetViewColumn *tree_column = user_data;
944 gboolean handled;
945
946 g_signal_emit (tree_column, tree_column_signals[QUERY_TOOLTIP], 0,
947 tooltip, &handled);
948 return handled;
949 }
950
951 static gboolean
952 on_button_pressed (GtkWidget *widget, GdkEventButton *event,
953 gpointer user_data)
954 {
955 PsppSheetViewColumn *tree_column = user_data;
956 gboolean handled;
957
958 /* XXX See "Implement GtkWidget::popup_menu" in GTK+ reference manual. */
959 g_signal_emit (tree_column, tree_column_signals[BUTTON_PRESS_EVENT],
960 0, event, &handled);
961 return handled;
962 }
963
964 /* Helper functions
965 */
966
967 /* Button handling code
968 */
969 static void
970 pspp_sheet_view_column_create_button (PsppSheetViewColumn *tree_column)
971 {
972 PsppSheetView *tree_view;
973 GtkWidget *child;
974 GtkWidget *hbox;
975
976 tree_view = (PsppSheetView *) tree_column->tree_view;
977
978 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
979 g_return_if_fail (tree_column->button == NULL);
980
981 gtk_widget_push_composite_child ();
982 tree_column->button = gtk_button_new ();
983 gtk_widget_add_events (tree_column->button, GDK_POINTER_MOTION_MASK);
984 gtk_widget_pop_composite_child ();
985
986 /* make sure we own a reference to it as well. */
987 if (tree_view->priv->header_window)
988 gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
989 gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
990
991 g_signal_connect (tree_column->button, "event",
992 G_CALLBACK (pspp_sheet_view_column_button_event),
993 tree_column);
994 g_signal_connect (tree_column->button, "clicked",
995 G_CALLBACK (pspp_sheet_view_column_button_clicked),
996 tree_column);
997 g_signal_connect (tree_column->button, "popup-menu",
998 G_CALLBACK (pspp_sheet_view_column_button_popup_menu),
999 tree_column);
1000 g_signal_connect (tree_column->button, "button-press-event",
1001 G_CALLBACK (on_button_pressed), tree_column);
1002
1003 g_signal_connect (tree_column->button, "query-tooltip",
1004 G_CALLBACK (on_query_tooltip), tree_column);
1005 g_object_set (tree_column->button, "has-tooltip", TRUE, NULL);
1006
1007 tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
1008
1009 hbox = gtk_hbox_new (FALSE, 2);
1010 tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
1011
1012 if (tree_column->child)
1013 child = tree_column->child;
1014 else
1015 {
1016 child = gtk_label_new (tree_column->title);
1017 gtk_widget_show (child);
1018 }
1019
1020 g_signal_connect (child, "mnemonic-activate",
1021 G_CALLBACK (pspp_sheet_view_column_mnemonic_activate),
1022 tree_column);
1023
1024 if (tree_column->xalign <= 0.5)
1025 gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
1026 else
1027 gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
1028
1029 gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
1030
1031 gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
1032 gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
1033
1034 gtk_widget_show (hbox);
1035 gtk_widget_show (tree_column->alignment);
1036 pspp_sheet_view_column_update_button (tree_column);
1037 }
1038
1039 void
1040 pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column)
1041 {
1042 gint sort_column_id = -1;
1043 GtkWidget *hbox;
1044 GtkWidget *alignment;
1045 GtkWidget *arrow;
1046 GtkWidget *current_child;
1047 GtkArrowType arrow_type = GTK_ARROW_NONE;
1048 GtkTreeModel *model;
1049 gboolean can_focus;
1050
1051 if (tree_column->tree_view)
1052 model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
1053 else
1054 model = NULL;
1055
1056 /* Create a button if necessary */
1057 if (tree_column->need_button &&
1058 tree_column->visible &&
1059 tree_column->button == NULL &&
1060 tree_column->tree_view &&
1061 gtk_widget_get_realized (tree_column->tree_view))
1062 pspp_sheet_view_column_create_button (tree_column);
1063
1064 if (! tree_column->button)
1065 return;
1066
1067 hbox = GTK_BIN (tree_column->button)->child;
1068 alignment = tree_column->alignment;
1069 arrow = tree_column->arrow;
1070 current_child = GTK_BIN (alignment)->child;
1071
1072 /* Set up the actual button */
1073 gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
1074 0.5, 0.0, 0.0);
1075
1076 if (tree_column->child)
1077 {
1078 if (current_child != tree_column->child)
1079 {
1080 gtk_container_remove (GTK_CONTAINER (alignment),
1081 current_child);
1082 gtk_container_add (GTK_CONTAINER (alignment),
1083 tree_column->child);
1084 }
1085 }
1086 else
1087 {
1088 if (current_child == NULL)
1089 {
1090 current_child = gtk_label_new (NULL);
1091 gtk_widget_show (current_child);
1092 gtk_container_add (GTK_CONTAINER (alignment),
1093 current_child);
1094 }
1095
1096 g_return_if_fail (GTK_IS_LABEL (current_child));
1097
1098 if (tree_column->title)
1099 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
1100 tree_column->title);
1101 else
1102 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
1103 "");
1104 }
1105
1106 if (GTK_IS_TREE_SORTABLE (model))
1107 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
1108 &sort_column_id,
1109 NULL);
1110
1111 if (tree_column->show_sort_indicator)
1112 {
1113 gboolean alternative;
1114
1115 g_object_get (gtk_widget_get_settings (tree_column->tree_view),
1116 "gtk-alternative-sort-arrows", &alternative,
1117 NULL);
1118
1119 switch (tree_column->sort_order)
1120 {
1121 case GTK_SORT_ASCENDING:
1122 arrow_type = alternative ? GTK_ARROW_UP : GTK_ARROW_DOWN;
1123 break;
1124
1125 case GTK_SORT_DESCENDING:
1126 arrow_type = alternative ? GTK_ARROW_DOWN : GTK_ARROW_UP;
1127 break;
1128
1129 default:
1130 g_warning (G_STRLOC": bad sort order");
1131 break;
1132 }
1133 }
1134
1135 gtk_arrow_set (GTK_ARROW (arrow),
1136 arrow_type,
1137 GTK_SHADOW_IN);
1138
1139 /* Put arrow on the right if the text is left-or-center justified, and on the
1140 * left otherwise; do this by packing boxes, so flipping text direction will
1141 * reverse things
1142 */
1143 g_object_ref (arrow);
1144 gtk_container_remove (GTK_CONTAINER (hbox), arrow);
1145
1146 if (tree_column->xalign <= 0.5)
1147 {
1148 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1149 }
1150 else
1151 {
1152 gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1153 /* move it to the front */
1154 gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
1155 }
1156 g_object_unref (arrow);
1157
1158 if (tree_column->show_sort_indicator
1159 || (GTK_IS_TREE_SORTABLE (model) && tree_column->sort_column_id >= 0))
1160 gtk_widget_show (arrow);
1161 else
1162 gtk_widget_hide (arrow);
1163
1164 /* It's always safe to hide the button. It isn't always safe to show it, as
1165 * if you show it before it's realized, it'll get the wrong window. */
1166 if (tree_column->button &&
1167 tree_column->tree_view != NULL &&
1168 gtk_widget_get_realized (tree_column->tree_view))
1169 {
1170 if (tree_column->visible)
1171 {
1172 gtk_widget_show_now (tree_column->button);
1173 if (tree_column->window)
1174 {
1175 if (tree_column->resizable)
1176 {
1177 gdk_window_show (tree_column->window);
1178 gdk_window_raise (tree_column->window);
1179 }
1180 else
1181 {
1182 gdk_window_hide (tree_column->window);
1183 }
1184 }
1185 }
1186 else
1187 {
1188 gtk_widget_hide (tree_column->button);
1189 if (tree_column->window)
1190 gdk_window_hide (tree_column->window);
1191 }
1192 }
1193
1194 can_focus = pspp_sheet_view_column_can_focus (tree_column);
1195 gtk_widget_set_can_focus (tree_column->button, can_focus);
1196 if (!can_focus && gtk_widget_has_focus (tree_column->button))
1197 {
1198 GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
1199 if (gtk_widget_is_toplevel (toplevel))
1200 {
1201 gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
1202 }
1203 }
1204
1205 /* Queue a resize on the assumption that we always want to catch all changes
1206 * and columns don't change all that often.
1207 */
1208 if (gtk_widget_get_realized (tree_column->tree_view))
1209 gtk_widget_queue_resize (tree_column->tree_view);
1210
1211 }
1212
1213 /* Button signal handlers
1214 */
1215
1216 static gint
1217 pspp_sheet_view_column_button_event (GtkWidget *widget,
1218 GdkEvent *event,
1219 gpointer data)
1220 {
1221 PsppSheetViewColumn *column = (PsppSheetViewColumn *) data;
1222
1223 g_return_val_if_fail (event != NULL, FALSE);
1224
1225 if (event->type == GDK_BUTTON_PRESS &&
1226 column->reorderable &&
1227 ((GdkEventButton *)event)->button == 1)
1228 {
1229 column->maybe_reordered = TRUE;
1230 gdk_window_get_pointer (GTK_BUTTON (widget)->event_window,
1231 &column->drag_x,
1232 &column->drag_y,
1233 NULL);
1234 gtk_widget_grab_focus (widget);
1235 }
1236
1237 if (event->type == GDK_BUTTON_RELEASE ||
1238 event->type == GDK_LEAVE_NOTIFY)
1239 column->maybe_reordered = FALSE;
1240
1241 if (event->type == GDK_MOTION_NOTIFY &&
1242 column->maybe_reordered &&
1243 (gtk_drag_check_threshold (widget,
1244 column->drag_x,
1245 column->drag_y,
1246 (gint) ((GdkEventMotion *)event)->x,
1247 (gint) ((GdkEventMotion *)event)->y)))
1248 {
1249 column->maybe_reordered = FALSE;
1250 _pspp_sheet_view_column_start_drag (PSPP_SHEET_VIEW (column->tree_view), column);
1251 return TRUE;
1252 }
1253 if (column->clickable == FALSE)
1254 {
1255 switch (event->type)
1256 {
1257 case GDK_MOTION_NOTIFY:
1258 case GDK_BUTTON_RELEASE:
1259 case GDK_ENTER_NOTIFY:
1260 case GDK_LEAVE_NOTIFY:
1261 return TRUE;
1262 default:
1263 return FALSE;
1264 }
1265 }
1266 return FALSE;
1267 }
1268
1269 static gboolean
1270 all_rows_selected (PsppSheetView *sheet_view)
1271 {
1272 PsppSheetSelection *selection = sheet_view->priv->selection;
1273 gint n_rows, n_selected_rows;
1274
1275 n_rows = sheet_view->priv->row_count;
1276 n_selected_rows = pspp_sheet_selection_count_selected_rows (selection);
1277
1278 return n_rows > 0 && n_selected_rows >= n_rows;
1279 }
1280
1281 static gboolean
1282 on_pspp_sheet_view_column_button_press_event (PsppSheetViewColumn *column,
1283 GdkEventButton *event)
1284 {
1285 PsppSheetView *sheet_view = PSPP_SHEET_VIEW (column->tree_view);
1286 PsppSheetSelection *selection;
1287 GSignalInvocationHint *hint;
1288 guint modifiers;
1289
1290 /* We only want to run first, not last, but combining that with return type
1291 `gboolean' makes GObject warn, so just ignore the run_last call. */
1292 hint = g_signal_get_invocation_hint (column);
1293 g_return_val_if_fail (hint != NULL, FALSE);
1294 if (hint->run_type != G_SIGNAL_RUN_FIRST)
1295 return FALSE;
1296
1297 g_return_val_if_fail (sheet_view != NULL, FALSE);
1298
1299 selection = sheet_view->priv->selection;
1300 g_return_val_if_fail (selection != NULL, FALSE);
1301
1302 if (pspp_sheet_selection_get_mode (selection) != PSPP_SHEET_SELECTION_RECTANGLE)
1303 return FALSE;
1304
1305 modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
1306 if (event->type == GDK_BUTTON_PRESS && event->button == 3)
1307 {
1308 if (pspp_sheet_selection_count_selected_columns (selection) <= 1
1309 || !all_rows_selected (sheet_view))
1310 {
1311 pspp_sheet_selection_select_all (selection);
1312 pspp_sheet_selection_unselect_all_columns (selection);
1313 pspp_sheet_selection_select_column (selection, column);
1314 sheet_view->priv->anchor_column = column;
1315 }
1316 return FALSE;
1317 }
1318 else if (event->type == GDK_BUTTON_PRESS && event->button == 1
1319 && modifiers == GDK_CONTROL_MASK)
1320 {
1321 gboolean is_selected;
1322
1323 if (!all_rows_selected (sheet_view))
1324 {
1325 pspp_sheet_selection_select_all (selection);
1326 pspp_sheet_selection_unselect_all_columns (selection);
1327 }
1328 sheet_view->priv->anchor_column = column;
1329
1330 is_selected = pspp_sheet_view_column_get_selected (column);
1331 pspp_sheet_view_column_set_selected (column, !is_selected);
1332
1333 return TRUE;
1334 }
1335 else if (event->type == GDK_BUTTON_PRESS && event->button == 1
1336 && modifiers == GDK_SHIFT_MASK)
1337 {
1338 if (!all_rows_selected (sheet_view))
1339 {
1340 pspp_sheet_selection_select_all (selection);
1341 pspp_sheet_selection_unselect_all_columns (selection);
1342 sheet_view->priv->anchor_column = column;
1343 }
1344 else if (sheet_view->priv->anchor_column == NULL)
1345 sheet_view->priv->anchor_column = column;
1346
1347 pspp_sheet_selection_unselect_all_columns (selection);
1348 pspp_sheet_selection_select_column_range (selection,
1349 sheet_view->priv->anchor_column,
1350 column);
1351 return TRUE;
1352 }
1353
1354 return FALSE;
1355 }
1356
1357 static gboolean
1358 on_pspp_sheet_view_column_button_clicked (PsppSheetViewColumn *column)
1359 {
1360 PsppSheetSelection *selection;
1361 PsppSheetView *sheet_view;
1362
1363 sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view (column));
1364 selection = pspp_sheet_view_get_selection (sheet_view);
1365 if (pspp_sheet_selection_get_mode (selection) == PSPP_SHEET_SELECTION_RECTANGLE)
1366 {
1367 pspp_sheet_selection_select_all (selection);
1368 pspp_sheet_selection_unselect_all_columns (selection);
1369 pspp_sheet_selection_select_column (selection, column);
1370 sheet_view->priv->anchor_column = column;
1371 return TRUE;
1372 }
1373 return FALSE;
1374 }
1375
1376 static void
1377 pspp_sheet_view_column_button_clicked (GtkWidget *widget, gpointer data)
1378 {
1379 PsppSheetViewColumn *column = data;
1380 gboolean handled;
1381
1382 g_signal_emit (column, tree_column_signals[CLICKED], 0, &handled);
1383 }
1384
1385 static void
1386 pspp_sheet_view_column_button_popup_menu (GtkWidget *widget, gpointer data)
1387 {
1388 g_signal_emit_by_name (data, "popup-menu");
1389 }
1390
1391 static gboolean
1392 pspp_sheet_view_column_mnemonic_activate (GtkWidget *widget,
1393 gboolean group_cycling,
1394 gpointer data)
1395 {
1396 PsppSheetViewColumn *column = (PsppSheetViewColumn *)data;
1397
1398 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), FALSE);
1399
1400 PSPP_SHEET_VIEW (column->tree_view)->priv->focus_column = column;
1401 if (column->clickable)
1402 gtk_button_clicked (GTK_BUTTON (column->button));
1403 else if (gtk_widget_get_can_focus (column->button))
1404 gtk_widget_grab_focus (column->button);
1405 else
1406 gtk_widget_grab_focus (column->tree_view);
1407
1408 return TRUE;
1409 }
1410
1411 static void
1412 pspp_sheet_view_model_sort_column_changed (GtkTreeSortable *sortable,
1413 PsppSheetViewColumn *column)
1414 {
1415 gint sort_column_id;
1416 GtkSortType order;
1417
1418 if (gtk_tree_sortable_get_sort_column_id (sortable,
1419 &sort_column_id,
1420 &order))
1421 {
1422 if (sort_column_id == column->sort_column_id)
1423 {
1424 pspp_sheet_view_column_set_sort_indicator (column, TRUE);
1425 pspp_sheet_view_column_set_sort_order (column, order);
1426 }
1427 else
1428 {
1429 pspp_sheet_view_column_set_sort_indicator (column, FALSE);
1430 }
1431 }
1432 else
1433 {
1434 pspp_sheet_view_column_set_sort_indicator (column, FALSE);
1435 }
1436 }
1437
1438 static void
1439 pspp_sheet_view_column_sort (PsppSheetViewColumn *tree_column,
1440 gpointer data)
1441 {
1442 gint sort_column_id;
1443 GtkSortType order;
1444 gboolean has_sort_column;
1445 gboolean has_default_sort_func;
1446
1447 g_return_if_fail (tree_column->tree_view != NULL);
1448
1449 has_sort_column =
1450 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
1451 &sort_column_id,
1452 &order);
1453 has_default_sort_func =
1454 gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model));
1455
1456 if (has_sort_column &&
1457 sort_column_id == tree_column->sort_column_id)
1458 {
1459 if (order == GTK_SORT_ASCENDING)
1460 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
1461 tree_column->sort_column_id,
1462 GTK_SORT_DESCENDING);
1463 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
1464 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
1465 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1466 GTK_SORT_ASCENDING);
1467 else
1468 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
1469 tree_column->sort_column_id,
1470 GTK_SORT_ASCENDING);
1471 }
1472 else
1473 {
1474 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
1475 tree_column->sort_column_id,
1476 GTK_SORT_ASCENDING);
1477 }
1478 }
1479
1480
1481 static void
1482 pspp_sheet_view_column_setup_sort_column_id_callback (PsppSheetViewColumn *tree_column)
1483 {
1484 GtkTreeModel *model;
1485
1486 if (tree_column->tree_view == NULL)
1487 return;
1488
1489 model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
1490
1491 if (model == NULL)
1492 return;
1493
1494 if (GTK_IS_TREE_SORTABLE (model) &&
1495 tree_column->sort_column_id != -1)
1496 {
1497 gint real_sort_column_id;
1498 GtkSortType real_order;
1499
1500 if (tree_column->sort_column_changed_signal == 0)
1501 tree_column->sort_column_changed_signal =
1502 g_signal_connect (model, "sort-column-changed",
1503 G_CALLBACK (pspp_sheet_view_model_sort_column_changed),
1504 tree_column);
1505
1506 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
1507 &real_sort_column_id,
1508 &real_order) &&
1509 (real_sort_column_id == tree_column->sort_column_id))
1510 {
1511 pspp_sheet_view_column_set_sort_indicator (tree_column, TRUE);
1512 pspp_sheet_view_column_set_sort_order (tree_column, real_order);
1513 }
1514 else
1515 {
1516 pspp_sheet_view_column_set_sort_indicator (tree_column, FALSE);
1517 }
1518 }
1519 }
1520
1521
1522 /* Exported Private Functions.
1523 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
1524 */
1525
1526 void
1527 _pspp_sheet_view_column_realize_button (PsppSheetViewColumn *column)
1528 {
1529 PsppSheetView *tree_view;
1530 GdkWindowAttr attr;
1531 guint attributes_mask;
1532 gboolean rtl;
1533
1534 tree_view = (PsppSheetView *)column->tree_view;
1535 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1536
1537 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
1538 g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
1539 g_return_if_fail (tree_view->priv->header_window != NULL);
1540 if (!column->need_button || !column->button)
1541 return;
1542
1543 g_return_if_fail (column->button != NULL);
1544
1545 gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
1546
1547 if (column->visible)
1548 gtk_widget_show (column->button);
1549
1550 attr.window_type = GDK_WINDOW_CHILD;
1551 attr.wclass = GDK_INPUT_ONLY;
1552 attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
1553 attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
1554 attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view)) |
1555 (GDK_BUTTON_PRESS_MASK |
1556 GDK_BUTTON_RELEASE_MASK |
1557 GDK_POINTER_MOTION_MASK |
1558 GDK_POINTER_MOTION_HINT_MASK |
1559 GDK_KEY_PRESS_MASK);
1560 attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
1561 attr.cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (tree_view->priv->header_window),
1562 GDK_SB_H_DOUBLE_ARROW);
1563 attr.y = 0;
1564 attr.width = TREE_VIEW_DRAG_WIDTH;
1565 attr.height = tree_view->priv->header_height;
1566
1567 attr.x = (column->button->allocation.x + (rtl ? 0 : column->button->allocation.width)) - TREE_VIEW_DRAG_WIDTH / 2;
1568 column->window = gdk_window_new (tree_view->priv->header_window,
1569 &attr, attributes_mask);
1570 gdk_window_set_user_data (column->window, tree_view);
1571
1572 pspp_sheet_view_column_update_button (column);
1573
1574 gdk_cursor_unref (attr.cursor);
1575 }
1576
1577 void
1578 _pspp_sheet_view_column_unrealize_button (PsppSheetViewColumn *column)
1579 {
1580 g_return_if_fail (column != NULL);
1581 if (column->window != NULL)
1582 {
1583 gdk_window_set_user_data (column->window, NULL);
1584 gdk_window_destroy (column->window);
1585 column->window = NULL;
1586 }
1587 }
1588
1589 void
1590 _pspp_sheet_view_column_unset_model (PsppSheetViewColumn *column,
1591 GtkTreeModel *old_model)
1592 {
1593 if (column->sort_column_changed_signal)
1594 {
1595 g_signal_handler_disconnect (old_model,
1596 column->sort_column_changed_signal);
1597 column->sort_column_changed_signal = 0;
1598 }
1599 pspp_sheet_view_column_set_sort_indicator (column, FALSE);
1600 }
1601
1602 void
1603 _pspp_sheet_view_column_set_tree_view (PsppSheetViewColumn *column,
1604 PsppSheetView *tree_view)
1605 {
1606 g_assert (column->tree_view == NULL);
1607
1608 column->tree_view = GTK_WIDGET (tree_view);
1609 if (column->need_button)
1610 pspp_sheet_view_column_create_button (column);
1611
1612 column->property_changed_signal =
1613 g_signal_connect_swapped (tree_view,
1614 "notify::model",
1615 G_CALLBACK (pspp_sheet_view_column_setup_sort_column_id_callback),
1616 column);
1617
1618 pspp_sheet_view_column_setup_sort_column_id_callback (column);
1619 }
1620
1621 void
1622 _pspp_sheet_view_column_unset_tree_view (PsppSheetViewColumn *column)
1623 {
1624 if (column->tree_view && column->button)
1625 {
1626 gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
1627 }
1628 if (column->property_changed_signal)
1629 {
1630 g_signal_handler_disconnect (column->tree_view, column->property_changed_signal);
1631 column->property_changed_signal = 0;
1632 }
1633
1634 if (column->sort_column_changed_signal)
1635 {
1636 g_signal_handler_disconnect (pspp_sheet_view_get_model (PSPP_SHEET_VIEW (column->tree_view)),
1637 column->sort_column_changed_signal);
1638 column->sort_column_changed_signal = 0;
1639 }
1640
1641 column->tree_view = NULL;
1642 column->button = NULL;
1643 }
1644
1645 gboolean
1646 _pspp_sheet_view_column_has_editable_cell (PsppSheetViewColumn *column)
1647 {
1648 GList *list;
1649
1650 for (list = column->cell_list; list; list = list->next)
1651 if (((PsppSheetViewColumnCellInfo *)list->data)->cell->mode ==
1652 GTK_CELL_RENDERER_MODE_EDITABLE)
1653 return TRUE;
1654
1655 return FALSE;
1656 }
1657
1658 /* gets cell being edited */
1659 GtkCellRenderer *
1660 _pspp_sheet_view_column_get_edited_cell (PsppSheetViewColumn *column)
1661 {
1662 GList *list;
1663
1664 for (list = column->cell_list; list; list = list->next)
1665 if (((PsppSheetViewColumnCellInfo *)list->data)->in_editing_mode)
1666 return ((PsppSheetViewColumnCellInfo *)list->data)->cell;
1667
1668 return NULL;
1669 }
1670
1671 gint
1672 _pspp_sheet_view_column_count_special_cells (PsppSheetViewColumn *column)
1673 {
1674 gint i = 0;
1675 GList *list;
1676
1677 for (list = column->cell_list; list; list = list->next)
1678 {
1679 PsppSheetViewColumnCellInfo *cellinfo = list->data;
1680
1681 if ((cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
1682 cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE) &&
1683 cellinfo->cell->visible)
1684 i++;
1685 }
1686
1687 return i;
1688 }
1689
1690 GtkCellRenderer *
1691 _pspp_sheet_view_column_get_cell_at_pos (PsppSheetViewColumn *column,
1692 gint x)
1693 {
1694 GList *list;
1695 gint current_x = 0;
1696
1697 list = pspp_sheet_view_column_cell_first (column);
1698 for (; list; list = pspp_sheet_view_column_cell_next (column, list))
1699 {
1700 PsppSheetViewColumnCellInfo *cellinfo = list->data;
1701 if (current_x <= x && x <= current_x + cellinfo->real_width)
1702 return cellinfo->cell;
1703 current_x += cellinfo->real_width;
1704 }
1705
1706 return NULL;
1707 }
1708
1709 /* Public Functions */
1710
1711
1712 /**
1713 * pspp_sheet_view_column_new:
1714 *
1715 * Creates a new #PsppSheetViewColumn.
1716 *
1717 * Return value: A newly created #PsppSheetViewColumn.
1718 **/
1719 PsppSheetViewColumn *
1720 pspp_sheet_view_column_new (void)
1721 {
1722 PsppSheetViewColumn *tree_column;
1723
1724 tree_column = g_object_new (PSPP_TYPE_SHEET_VIEW_COLUMN, NULL);
1725
1726 return tree_column;
1727 }
1728
1729 /**
1730 * pspp_sheet_view_column_new_with_attributes:
1731 * @title: The title to set the header to.
1732 * @cell: The #GtkCellRenderer.
1733 * @Varargs: A %NULL-terminated list of attributes.
1734 *
1735 * Creates a new #PsppSheetViewColumn with a number of default values. This is
1736 * equivalent to calling pspp_sheet_view_column_set_title(),
1737 * pspp_sheet_view_column_pack_start(), and
1738 * pspp_sheet_view_column_set_attributes() on the newly created #PsppSheetViewColumn.
1739 *
1740 * Here's a simple example:
1741 * |[
1742 * enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS };
1743 * ...
1744 * {
1745 * PsppSheetViewColumn *column;
1746 * GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1747 *
1748 * column = pspp_sheet_view_column_new_with_attributes ("Title",
1749 * renderer,
1750 * "text", TEXT_COLUMN,
1751 * "foreground", COLOR_COLUMN,
1752 * NULL);
1753 * }
1754 * ]|
1755 *
1756 * Return value: A newly created #PsppSheetViewColumn.
1757 **/
1758 PsppSheetViewColumn *
1759 pspp_sheet_view_column_new_with_attributes (const gchar *title,
1760 GtkCellRenderer *cell,
1761 ...)
1762 {
1763 PsppSheetViewColumn *retval;
1764 va_list args;
1765
1766 retval = pspp_sheet_view_column_new ();
1767
1768 pspp_sheet_view_column_set_title (retval, title);
1769 pspp_sheet_view_column_pack_start (retval, cell, TRUE);
1770
1771 va_start (args, cell);
1772 pspp_sheet_view_column_set_attributesv (retval, cell, args);
1773 va_end (args);
1774
1775 return retval;
1776 }
1777
1778 static PsppSheetViewColumnCellInfo *
1779 pspp_sheet_view_column_get_cell_info (PsppSheetViewColumn *tree_column,
1780 GtkCellRenderer *cell_renderer)
1781 {
1782 GList *list;
1783 for (list = tree_column->cell_list; list; list = list->next)
1784 if (((PsppSheetViewColumnCellInfo *)list->data)->cell == cell_renderer)
1785 return (PsppSheetViewColumnCellInfo *) list->data;
1786 return NULL;
1787 }
1788
1789
1790 /**
1791 * pspp_sheet_view_column_pack_start:
1792 * @tree_column: A #PsppSheetViewColumn.
1793 * @cell: The #GtkCellRenderer.
1794 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1795 *
1796 * Packs the @cell into the beginning of the column. If @expand is %FALSE, then
1797 * the @cell is allocated no more space than it needs. Any unused space is divided
1798 * evenly between cells for which @expand is %TRUE.
1799 **/
1800 void
1801 pspp_sheet_view_column_pack_start (PsppSheetViewColumn *tree_column,
1802 GtkCellRenderer *cell,
1803 gboolean expand)
1804 {
1805 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tree_column), cell, expand);
1806 }
1807
1808 /**
1809 * pspp_sheet_view_column_pack_end:
1810 * @tree_column: A #PsppSheetViewColumn.
1811 * @cell: The #GtkCellRenderer.
1812 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1813 *
1814 * Adds the @cell to end of the column. If @expand is %FALSE, then the @cell
1815 * is allocated no more space than it needs. Any unused space is divided
1816 * evenly between cells for which @expand is %TRUE.
1817 **/
1818 void
1819 pspp_sheet_view_column_pack_end (PsppSheetViewColumn *tree_column,
1820 GtkCellRenderer *cell,
1821 gboolean expand)
1822 {
1823 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (tree_column), cell, expand);
1824 }
1825
1826 /**
1827 * pspp_sheet_view_column_clear:
1828 * @tree_column: A #PsppSheetViewColumn
1829 *
1830 * Unsets all the mappings on all renderers on the @tree_column.
1831 **/
1832 void
1833 pspp_sheet_view_column_clear (PsppSheetViewColumn *tree_column)
1834 {
1835 gtk_cell_layout_clear (GTK_CELL_LAYOUT (tree_column));
1836 }
1837
1838 static GList *
1839 pspp_sheet_view_column_cell_layout_get_cells (GtkCellLayout *layout)
1840 {
1841 PsppSheetViewColumn *tree_column = PSPP_SHEET_VIEW_COLUMN (layout);
1842 GList *retval = NULL, *list;
1843
1844 g_return_val_if_fail (tree_column != NULL, NULL);
1845
1846 for (list = tree_column->cell_list; list; list = list->next)
1847 {
1848 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)list->data;
1849
1850 retval = g_list_append (retval, info->cell);
1851 }
1852
1853 return retval;
1854 }
1855
1856 /**
1857 * pspp_sheet_view_column_get_cell_renderers:
1858 * @tree_column: A #PsppSheetViewColumn
1859 *
1860 * Returns a newly-allocated #GList of all the cell renderers in the column,
1861 * in no particular order. The list must be freed with g_list_free().
1862 *
1863 * Return value: A list of #GtkCellRenderers
1864 *
1865 * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead.
1866 **/
1867 GList *
1868 pspp_sheet_view_column_get_cell_renderers (PsppSheetViewColumn *tree_column)
1869 {
1870 return pspp_sheet_view_column_cell_layout_get_cells (GTK_CELL_LAYOUT (tree_column));
1871 }
1872
1873 /**
1874 * pspp_sheet_view_column_add_attribute:
1875 * @tree_column: A #PsppSheetViewColumn.
1876 * @cell_renderer: the #GtkCellRenderer to set attributes on
1877 * @attribute: An attribute on the renderer
1878 * @column: The column position on the model to get the attribute from.
1879 *
1880 * Adds an attribute mapping to the list in @tree_column. The @column is the
1881 * column of the model to get a value from, and the @attribute is the
1882 * parameter on @cell_renderer to be set from the value. So for example
1883 * if column 2 of the model contains strings, you could have the
1884 * "text" attribute of a #GtkCellRendererText get its values from
1885 * column 2.
1886 **/
1887 void
1888 pspp_sheet_view_column_add_attribute (PsppSheetViewColumn *tree_column,
1889 GtkCellRenderer *cell_renderer,
1890 const gchar *attribute,
1891 gint column)
1892 {
1893 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tree_column),
1894 cell_renderer, attribute, column);
1895 }
1896
1897 static void
1898 pspp_sheet_view_column_set_attributesv (PsppSheetViewColumn *tree_column,
1899 GtkCellRenderer *cell_renderer,
1900 va_list args)
1901 {
1902 gchar *attribute;
1903 gint column;
1904
1905 attribute = va_arg (args, gchar *);
1906
1907 pspp_sheet_view_column_clear_attributes (tree_column, cell_renderer);
1908
1909 while (attribute != NULL)
1910 {
1911 column = va_arg (args, gint);
1912 pspp_sheet_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1913 attribute = va_arg (args, gchar *);
1914 }
1915 }
1916
1917 /**
1918 * pspp_sheet_view_column_set_attributes:
1919 * @tree_column: A #PsppSheetViewColumn.
1920 * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1921 * @Varargs: A %NULL-terminated list of attributes.
1922 *
1923 * Sets the attributes in the list as the attributes of @tree_column.
1924 * The attributes should be in attribute/column order, as in
1925 * pspp_sheet_view_column_add_attribute(). All existing attributes
1926 * are removed, and replaced with the new attributes.
1927 **/
1928 void
1929 pspp_sheet_view_column_set_attributes (PsppSheetViewColumn *tree_column,
1930 GtkCellRenderer *cell_renderer,
1931 ...)
1932 {
1933 va_list args;
1934
1935 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
1936 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1937 g_return_if_fail (pspp_sheet_view_column_get_cell_info (tree_column, cell_renderer));
1938
1939 va_start (args, cell_renderer);
1940 pspp_sheet_view_column_set_attributesv (tree_column, cell_renderer, args);
1941 va_end (args);
1942 }
1943
1944
1945 /**
1946 * pspp_sheet_view_column_set_cell_data_func:
1947 * @tree_column: A #PsppSheetViewColumn
1948 * @cell_renderer: A #GtkCellRenderer
1949 * @func: The #PsppSheetViewColumnFunc to use.
1950 * @func_data: The user data for @func.
1951 * @destroy: The destroy notification for @func_data
1952 *
1953 * Sets the #PsppSheetViewColumnFunc to use for the column. This
1954 * function is used instead of the standard attributes mapping for
1955 * setting the column value, and should set the value of @tree_column's
1956 * cell renderer as appropriate. @func may be %NULL to remove an
1957 * older one.
1958 **/
1959 void
1960 pspp_sheet_view_column_set_cell_data_func (PsppSheetViewColumn *tree_column,
1961 GtkCellRenderer *cell_renderer,
1962 PsppSheetCellDataFunc func,
1963 gpointer func_data,
1964 GDestroyNotify destroy)
1965 {
1966 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (tree_column),
1967 cell_renderer,
1968 (GtkCellLayoutDataFunc)func,
1969 func_data, destroy);
1970 }
1971
1972
1973 /**
1974 * pspp_sheet_view_column_clear_attributes:
1975 * @tree_column: a #PsppSheetViewColumn
1976 * @cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1977 *
1978 * Clears all existing attributes previously set with
1979 * pspp_sheet_view_column_set_attributes().
1980 **/
1981 void
1982 pspp_sheet_view_column_clear_attributes (PsppSheetViewColumn *tree_column,
1983 GtkCellRenderer *cell_renderer)
1984 {
1985 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (tree_column),
1986 cell_renderer);
1987 }
1988
1989 /**
1990 * pspp_sheet_view_column_set_spacing:
1991 * @tree_column: A #PsppSheetViewColumn.
1992 * @spacing: distance between cell renderers in pixels.
1993 *
1994 * Sets the spacing field of @tree_column, which is the number of pixels to
1995 * place between cell renderers packed into it.
1996 **/
1997 void
1998 pspp_sheet_view_column_set_spacing (PsppSheetViewColumn *tree_column,
1999 gint spacing)
2000 {
2001 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2002 g_return_if_fail (spacing >= 0);
2003
2004 if (tree_column->spacing == spacing)
2005 return;
2006
2007 tree_column->spacing = spacing;
2008 if (tree_column->tree_view)
2009 _pspp_sheet_view_column_cell_set_dirty (tree_column);
2010 }
2011
2012 /**
2013 * pspp_sheet_view_column_get_spacing:
2014 * @tree_column: A #PsppSheetViewColumn.
2015 *
2016 * Returns the spacing of @tree_column.
2017 *
2018 * Return value: the spacing of @tree_column.
2019 **/
2020 gint
2021 pspp_sheet_view_column_get_spacing (PsppSheetViewColumn *tree_column)
2022 {
2023 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
2024
2025 return tree_column->spacing;
2026 }
2027
2028 /* Options for manipulating the columns */
2029
2030 /**
2031 * pspp_sheet_view_column_set_visible:
2032 * @tree_column: A #PsppSheetViewColumn.
2033 * @visible: %TRUE if the @tree_column is visible.
2034 *
2035 * Sets the visibility of @tree_column.
2036 **/
2037 void
2038 pspp_sheet_view_column_set_visible (PsppSheetViewColumn *tree_column,
2039 gboolean visible)
2040 {
2041 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2042
2043 visible = !! visible;
2044
2045 if (tree_column->visible == visible)
2046 return;
2047
2048 tree_column->visible = visible;
2049
2050 if (tree_column->visible)
2051 _pspp_sheet_view_column_cell_set_dirty (tree_column);
2052
2053 pspp_sheet_view_column_update_button (tree_column);
2054 g_object_notify (G_OBJECT (tree_column), "visible");
2055 }
2056
2057 /**
2058 * pspp_sheet_view_column_get_visible:
2059 * @tree_column: A #PsppSheetViewColumn.
2060 *
2061 * Returns %TRUE if @tree_column is visible.
2062 *
2063 * Return value: whether the column is visible or not. If it is visible, then
2064 * the tree will show the column.
2065 **/
2066 gboolean
2067 pspp_sheet_view_column_get_visible (PsppSheetViewColumn *tree_column)
2068 {
2069 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2070
2071 return tree_column->visible;
2072 }
2073
2074 /**
2075 * pspp_sheet_view_column_set_resizable:
2076 * @tree_column: A #PsppSheetViewColumn
2077 * @resizable: %TRUE, if the column can be resized
2078 *
2079 * If @resizable is %TRUE, then the user can explicitly resize the column by
2080 * grabbing the outer edge of the column button.
2081 **/
2082 void
2083 pspp_sheet_view_column_set_resizable (PsppSheetViewColumn *tree_column,
2084 gboolean resizable)
2085 {
2086 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2087
2088 resizable = !! resizable;
2089
2090 if (tree_column->resizable == resizable)
2091 return;
2092
2093 tree_column->resizable = resizable;
2094
2095 pspp_sheet_view_column_update_button (tree_column);
2096
2097 g_object_notify (G_OBJECT (tree_column), "resizable");
2098 }
2099
2100 /**
2101 * pspp_sheet_view_column_get_resizable:
2102 * @tree_column: A #PsppSheetViewColumn
2103 *
2104 * Returns %TRUE if the @tree_column can be resized by the end user.
2105 *
2106 * Return value: %TRUE, if the @tree_column can be resized.
2107 **/
2108 gboolean
2109 pspp_sheet_view_column_get_resizable (PsppSheetViewColumn *tree_column)
2110 {
2111 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2112
2113 return tree_column->resizable;
2114 }
2115
2116
2117 /**
2118 * pspp_sheet_view_column_get_width:
2119 * @tree_column: A #PsppSheetViewColumn.
2120 *
2121 * Returns the current size of @tree_column in pixels.
2122 *
2123 * Return value: The current width of @tree_column.
2124 **/
2125 gint
2126 pspp_sheet_view_column_get_width (PsppSheetViewColumn *tree_column)
2127 {
2128 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
2129
2130 return tree_column->width;
2131 }
2132
2133 /**
2134 * pspp_sheet_view_column_set_fixed_width:
2135 * @tree_column: A #PsppSheetViewColumn.
2136 * @fixed_width: The size to set @tree_column to. Must be greater than 0.
2137 *
2138 * Sets the size of the column in pixels. The size of the column is clamped to
2139 * the min/max width for the column. Please note that the min/max width of the
2140 * column doesn't actually affect the "fixed_width" property of the widget, just
2141 * the actual size when displayed.
2142 **/
2143 void
2144 pspp_sheet_view_column_set_fixed_width (PsppSheetViewColumn *tree_column,
2145 gint fixed_width)
2146 {
2147 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2148 g_return_if_fail (fixed_width > 0);
2149
2150 tree_column->fixed_width = fixed_width;
2151 tree_column->use_resized_width = FALSE;
2152
2153 if (tree_column->tree_view &&
2154 gtk_widget_get_realized (tree_column->tree_view))
2155 {
2156 gtk_widget_queue_resize (tree_column->tree_view);
2157 }
2158
2159 g_object_notify (G_OBJECT (tree_column), "fixed-width");
2160 }
2161
2162 /**
2163 * pspp_sheet_view_column_get_fixed_width:
2164 * @tree_column: a #PsppSheetViewColumn
2165 *
2166 * Gets the fixed width of the column. This value is only meaning may not be
2167 * the actual width of the column on the screen, just what is requested.
2168 *
2169 * Return value: the fixed width of the column
2170 **/
2171 gint
2172 pspp_sheet_view_column_get_fixed_width (PsppSheetViewColumn *tree_column)
2173 {
2174 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
2175
2176 return tree_column->fixed_width;
2177 }
2178
2179 /**
2180 * pspp_sheet_view_column_set_min_width:
2181 * @tree_column: A #PsppSheetViewColumn.
2182 * @min_width: The minimum width of the column in pixels, or -1.
2183 *
2184 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
2185 * minimum width is unset.
2186 **/
2187 void
2188 pspp_sheet_view_column_set_min_width (PsppSheetViewColumn *tree_column,
2189 gint min_width)
2190 {
2191 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2192 g_return_if_fail (min_width >= -1);
2193
2194 if (min_width == tree_column->min_width)
2195 return;
2196
2197 if (tree_column->visible &&
2198 tree_column->tree_view != NULL &&
2199 gtk_widget_get_realized (tree_column->tree_view))
2200 {
2201 if (min_width > tree_column->width)
2202 gtk_widget_queue_resize (tree_column->tree_view);
2203 }
2204
2205 tree_column->min_width = min_width;
2206 g_object_freeze_notify (G_OBJECT (tree_column));
2207 if (tree_column->max_width != -1 && tree_column->max_width < min_width)
2208 {
2209 tree_column->max_width = min_width;
2210 g_object_notify (G_OBJECT (tree_column), "max-width");
2211 }
2212 g_object_notify (G_OBJECT (tree_column), "min-width");
2213 g_object_thaw_notify (G_OBJECT (tree_column));
2214 }
2215
2216 /**
2217 * pspp_sheet_view_column_get_min_width:
2218 * @tree_column: A #PsppSheetViewColumn.
2219 *
2220 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
2221 * width is set.
2222 *
2223 * Return value: The minimum width of the @tree_column.
2224 **/
2225 gint
2226 pspp_sheet_view_column_get_min_width (PsppSheetViewColumn *tree_column)
2227 {
2228 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), -1);
2229
2230 return tree_column->min_width;
2231 }
2232
2233 /**
2234 * pspp_sheet_view_column_set_max_width:
2235 * @tree_column: A #PsppSheetViewColumn.
2236 * @max_width: The maximum width of the column in pixels, or -1.
2237 *
2238 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
2239 * maximum width is unset. Note, the column can actually be wider than max
2240 * width if it's the last column in a view. In this case, the column expands to
2241 * fill any extra space.
2242 **/
2243 void
2244 pspp_sheet_view_column_set_max_width (PsppSheetViewColumn *tree_column,
2245 gint max_width)
2246 {
2247 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2248 g_return_if_fail (max_width >= -1);
2249
2250 if (max_width == tree_column->max_width)
2251 return;
2252
2253 if (tree_column->visible &&
2254 tree_column->tree_view != NULL &&
2255 gtk_widget_get_realized (tree_column->tree_view))
2256 {
2257 if (max_width != -1 && max_width < tree_column->width)
2258 gtk_widget_queue_resize (tree_column->tree_view);
2259 }
2260
2261 tree_column->max_width = max_width;
2262 g_object_freeze_notify (G_OBJECT (tree_column));
2263 if (max_width != -1 && max_width < tree_column->min_width)
2264 {
2265 tree_column->min_width = max_width;
2266 g_object_notify (G_OBJECT (tree_column), "min-width");
2267 }
2268 g_object_notify (G_OBJECT (tree_column), "max-width");
2269 g_object_thaw_notify (G_OBJECT (tree_column));
2270 }
2271
2272 /**
2273 * pspp_sheet_view_column_get_max_width:
2274 * @tree_column: A #PsppSheetViewColumn.
2275 *
2276 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
2277 * width is set.
2278 *
2279 * Return value: The maximum width of the @tree_column.
2280 **/
2281 gint
2282 pspp_sheet_view_column_get_max_width (PsppSheetViewColumn *tree_column)
2283 {
2284 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), -1);
2285
2286 return tree_column->max_width;
2287 }
2288
2289 /**
2290 * pspp_sheet_view_column_clicked:
2291 * @tree_column: a #PsppSheetViewColumn
2292 *
2293 * Emits the "clicked" signal on the column. This function will only work if
2294 * @tree_column is clickable.
2295 **/
2296 void
2297 pspp_sheet_view_column_clicked (PsppSheetViewColumn *tree_column)
2298 {
2299 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2300
2301 if (tree_column->visible &&
2302 tree_column->button &&
2303 tree_column->clickable)
2304 gtk_button_clicked (GTK_BUTTON (tree_column->button));
2305 }
2306
2307 /**
2308 * pspp_sheet_view_column_set_title:
2309 * @tree_column: A #PsppSheetViewColumn.
2310 * @title: The title of the @tree_column.
2311 *
2312 * Sets the title of the @tree_column. If a custom widget has been set, then
2313 * this value is ignored.
2314 **/
2315 void
2316 pspp_sheet_view_column_set_title (PsppSheetViewColumn *tree_column,
2317 const gchar *title)
2318 {
2319 gchar *new_title;
2320
2321 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2322
2323 new_title = g_strdup (title);
2324 g_free (tree_column->title);
2325 tree_column->title = new_title;
2326
2327 pspp_sheet_view_column_update_button (tree_column);
2328 g_object_notify (G_OBJECT (tree_column), "title");
2329 }
2330
2331 /**
2332 * pspp_sheet_view_column_get_title:
2333 * @tree_column: A #PsppSheetViewColumn.
2334 *
2335 * Returns the title of the widget.
2336 *
2337 * Return value: the title of the column. This string should not be
2338 * modified or freed.
2339 **/
2340 G_CONST_RETURN gchar *
2341 pspp_sheet_view_column_get_title (PsppSheetViewColumn *tree_column)
2342 {
2343 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
2344
2345 return tree_column->title;
2346 }
2347
2348 /**
2349 * pspp_sheet_view_column_set_expand:
2350 * @tree_column: A #PsppSheetViewColumn
2351 * @expand: %TRUE if the column should take available extra space, %FALSE if not
2352 *
2353 * Sets the column to take available extra space. This space is shared equally
2354 * amongst all columns that have the expand set to %TRUE. If no column has this
2355 * option set, then the last column gets all extra space. By default, every
2356 * column is created with this %FALSE.
2357 *
2358 * Since: 2.4
2359 **/
2360 void
2361 pspp_sheet_view_column_set_expand (PsppSheetViewColumn *tree_column,
2362 gboolean expand)
2363 {
2364 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2365
2366 expand = expand?TRUE:FALSE;
2367 if (tree_column->expand == expand)
2368 return;
2369 tree_column->expand = expand;
2370
2371 if (tree_column->visible &&
2372 tree_column->tree_view != NULL &&
2373 gtk_widget_get_realized (tree_column->tree_view))
2374 {
2375 /* We want to continue using the original width of the
2376 * column that includes additional space added by the user
2377 * resizing the columns and possibly extra (expanded) space, which
2378 * are not included in the resized width.
2379 */
2380 tree_column->use_resized_width = FALSE;
2381
2382 gtk_widget_queue_resize (tree_column->tree_view);
2383 }
2384
2385 g_object_notify (G_OBJECT (tree_column), "expand");
2386 }
2387
2388 /**
2389 * pspp_sheet_view_column_get_expand:
2390 * @tree_column: a #PsppSheetViewColumn
2391 *
2392 * Return %TRUE if the column expands to take any available space.
2393 *
2394 * Return value: %TRUE, if the column expands
2395 *
2396 * Since: 2.4
2397 **/
2398 gboolean
2399 pspp_sheet_view_column_get_expand (PsppSheetViewColumn *tree_column)
2400 {
2401 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2402
2403 return tree_column->expand;
2404 }
2405
2406 /**
2407 * pspp_sheet_view_column_set_clickable:
2408 * @tree_column: A #PsppSheetViewColumn.
2409 * @clickable: %TRUE if the header is active.
2410 *
2411 * Sets the header to be active if @active is %TRUE. When the header is active,
2412 * then it can take keyboard focus, and can be clicked.
2413 **/
2414 void
2415 pspp_sheet_view_column_set_clickable (PsppSheetViewColumn *tree_column,
2416 gboolean clickable)
2417 {
2418 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2419
2420 clickable = !! clickable;
2421 if (tree_column->clickable == clickable)
2422 return;
2423
2424 tree_column->clickable = clickable;
2425 pspp_sheet_view_column_update_button (tree_column);
2426 g_object_notify (G_OBJECT (tree_column), "clickable");
2427 }
2428
2429 /**
2430 * pspp_sheet_view_column_get_clickable:
2431 * @tree_column: a #PsppSheetViewColumn
2432 *
2433 * Returns %TRUE if the user can click on the header for the column.
2434 *
2435 * Return value: %TRUE if user can click the column header.
2436 **/
2437 gboolean
2438 pspp_sheet_view_column_get_clickable (PsppSheetViewColumn *tree_column)
2439 {
2440 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2441
2442 return tree_column->clickable;
2443 }
2444
2445 /**
2446 * pspp_sheet_view_column_set_widget:
2447 * @tree_column: A #PsppSheetViewColumn.
2448 * @widget: (allow-none): A child #GtkWidget, or %NULL.
2449 *
2450 * Sets the widget in the header to be @widget. If widget is %NULL, then the
2451 * header button is set with a #GtkLabel set to the title of @tree_column.
2452 **/
2453 void
2454 pspp_sheet_view_column_set_widget (PsppSheetViewColumn *tree_column,
2455 GtkWidget *widget)
2456 {
2457 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2458 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
2459
2460 if (widget)
2461 g_object_ref_sink (widget);
2462
2463 if (tree_column->child)
2464 g_object_unref (tree_column->child);
2465
2466 tree_column->child = widget;
2467 pspp_sheet_view_column_update_button (tree_column);
2468 g_object_notify (G_OBJECT (tree_column), "widget");
2469 }
2470
2471 /**
2472 * pspp_sheet_view_column_get_widget:
2473 * @tree_column: A #PsppSheetViewColumn.
2474 *
2475 * Returns the #GtkWidget in the button on the column header. If a custom
2476 * widget has not been set then %NULL is returned.
2477 *
2478 * Return value: The #GtkWidget in the column header, or %NULL
2479 **/
2480 GtkWidget *
2481 pspp_sheet_view_column_get_widget (PsppSheetViewColumn *tree_column)
2482 {
2483 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
2484
2485 return tree_column->child;
2486 }
2487
2488 /**
2489 * pspp_sheet_view_column_set_alignment:
2490 * @tree_column: A #PsppSheetViewColumn.
2491 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
2492 *
2493 * Sets the alignment of the title or custom widget inside the column header.
2494 * The alignment determines its location inside the button -- 0.0 for left, 0.5
2495 * for center, 1.0 for right.
2496 **/
2497 void
2498 pspp_sheet_view_column_set_alignment (PsppSheetViewColumn *tree_column,
2499 gfloat xalign)
2500 {
2501 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2502
2503 xalign = CLAMP (xalign, 0.0, 1.0);
2504
2505 if (tree_column->xalign == xalign)
2506 return;
2507
2508 tree_column->xalign = xalign;
2509 pspp_sheet_view_column_update_button (tree_column);
2510 g_object_notify (G_OBJECT (tree_column), "alignment");
2511 }
2512
2513 /**
2514 * pspp_sheet_view_column_get_alignment:
2515 * @tree_column: A #PsppSheetViewColumn.
2516 *
2517 * Returns the current x alignment of @tree_column. This value can range
2518 * between 0.0 and 1.0.
2519 *
2520 * Return value: The current alignent of @tree_column.
2521 **/
2522 gfloat
2523 pspp_sheet_view_column_get_alignment (PsppSheetViewColumn *tree_column)
2524 {
2525 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0.5);
2526
2527 return tree_column->xalign;
2528 }
2529
2530 /**
2531 * pspp_sheet_view_column_set_reorderable:
2532 * @tree_column: A #PsppSheetViewColumn
2533 * @reorderable: %TRUE, if the column can be reordered.
2534 *
2535 * If @reorderable is %TRUE, then the column can be reordered by the end user
2536 * dragging the header.
2537 **/
2538 void
2539 pspp_sheet_view_column_set_reorderable (PsppSheetViewColumn *tree_column,
2540 gboolean reorderable)
2541 {
2542 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2543
2544 /* if (reorderable)
2545 pspp_sheet_view_column_set_clickable (tree_column, TRUE);*/
2546
2547 if (tree_column->reorderable == (reorderable?TRUE:FALSE))
2548 return;
2549
2550 tree_column->reorderable = (reorderable?TRUE:FALSE);
2551 pspp_sheet_view_column_update_button (tree_column);
2552 g_object_notify (G_OBJECT (tree_column), "reorderable");
2553 }
2554
2555 /**
2556 * pspp_sheet_view_column_get_reorderable:
2557 * @tree_column: A #PsppSheetViewColumn
2558 *
2559 * Returns %TRUE if the @tree_column can be reordered by the user.
2560 *
2561 * Return value: %TRUE if the @tree_column can be reordered by the user.
2562 **/
2563 gboolean
2564 pspp_sheet_view_column_get_reorderable (PsppSheetViewColumn *tree_column)
2565 {
2566 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2567
2568 return tree_column->reorderable;
2569 }
2570
2571 /**
2572 * pspp_sheet_view_column_set_quick_edit:
2573 * @tree_column: A #PsppSheetViewColumn
2574 * @quick_edit: If true, editing starts upon the first click in the column. If
2575 * false, the first click selects the column and a second click is needed to
2576 * begin editing. This has no effect on cells that are not editable.
2577 **/
2578 void
2579 pspp_sheet_view_column_set_quick_edit (PsppSheetViewColumn *tree_column,
2580 gboolean quick_edit)
2581 {
2582 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2583
2584 quick_edit = !!quick_edit;
2585 if (tree_column->quick_edit != quick_edit)
2586 {
2587 tree_column->quick_edit = (quick_edit?TRUE:FALSE);
2588 g_object_notify (G_OBJECT (tree_column), "quick-edit");
2589 }
2590 }
2591
2592 /**
2593 * pspp_sheet_view_column_get_quick_edit:
2594 * @tree_column: A #PsppSheetViewColumn
2595 *
2596 * Returns %TRUE if editing starts upon the first click in the column. Returns
2597 * %FALSE, the first click selects the column and a second click is needed to
2598 * begin editing. This is not meaningful for cells that are not editable.
2599 *
2600 * Return value: %TRUE if editing starts upon the first click.
2601 **/
2602 gboolean
2603 pspp_sheet_view_column_get_quick_edit (PsppSheetViewColumn *tree_column)
2604 {
2605 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2606
2607 return tree_column->quick_edit;
2608 }
2609
2610
2611 /**
2612 * pspp_sheet_view_column_set_selected:
2613 * @tree_column: A #PsppSheetViewColumn
2614 * @selected: If true, the column is selected as part of a rectangular
2615 * selection.
2616 **/
2617 void
2618 pspp_sheet_view_column_set_selected (PsppSheetViewColumn *tree_column,
2619 gboolean selected)
2620 {
2621 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2622
2623 selected = !!selected;
2624 if (tree_column->selected != selected)
2625 {
2626 PsppSheetSelection *selection;
2627 PsppSheetView *sheet_view;
2628
2629 if (tree_column->tree_view != NULL)
2630 gtk_widget_queue_draw (GTK_WIDGET (tree_column->tree_view));
2631 tree_column->selected = (selected?TRUE:FALSE);
2632 g_object_notify (G_OBJECT (tree_column), "selected");
2633
2634 sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view (
2635 tree_column));
2636 selection = pspp_sheet_view_get_selection (sheet_view);
2637 _pspp_sheet_selection_emit_changed (selection);
2638 }
2639 }
2640
2641 /**
2642 * pspp_sheet_view_column_get_selected:
2643 * @tree_column: A #PsppSheetViewColumn
2644 *
2645 * Returns %TRUE if the column is selected as part of a rectangular
2646 * selection.
2647 *
2648 * Return value: %TRUE if the column is selected as part of a rectangular
2649 * selection.
2650 **/
2651 gboolean
2652 pspp_sheet_view_column_get_selected (PsppSheetViewColumn *tree_column)
2653 {
2654 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2655
2656 return tree_column->selected;
2657 }
2658
2659 /**
2660 * pspp_sheet_view_column_set_selectable:
2661 * @tree_column: A #PsppSheetViewColumn
2662 * @selectable: If true, the column may be selected as part of a rectangular
2663 * selection.
2664 **/
2665 void
2666 pspp_sheet_view_column_set_selectable (PsppSheetViewColumn *tree_column,
2667 gboolean selectable)
2668 {
2669 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2670
2671 selectable = !!selectable;
2672 if (tree_column->selectable != selectable)
2673 {
2674 if (tree_column->tree_view != NULL)
2675 gtk_widget_queue_draw (GTK_WIDGET (tree_column->tree_view));
2676 tree_column->selectable = (selectable?TRUE:FALSE);
2677 g_object_notify (G_OBJECT (tree_column), "selectable");
2678 }
2679 }
2680
2681 /**
2682 * pspp_sheet_view_column_get_selectable:
2683 * @tree_column: A #PsppSheetViewColumn
2684 *
2685 * Returns %TRUE if the column may be selected as part of a rectangular
2686 * selection.
2687 *
2688 * Return value: %TRUE if the column may be selected as part of a rectangular
2689 * selection.
2690 **/
2691 gboolean
2692 pspp_sheet_view_column_get_selectable (PsppSheetViewColumn *tree_column)
2693 {
2694 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2695
2696 return tree_column->selectable;
2697 }
2698
2699
2700 /**
2701 * pspp_sheet_view_column_set_row_head:
2702 * @tree_column: A #PsppSheetViewColumn
2703 * @row_head: If true, the column is a "row head", analogous to a column head.
2704 * See the description of the row-head property for more information.
2705 **/
2706 void
2707 pspp_sheet_view_column_set_row_head (PsppSheetViewColumn *tree_column,
2708 gboolean row_head)
2709 {
2710 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2711
2712 row_head = !!row_head;
2713 if (tree_column->row_head != row_head)
2714 {
2715 tree_column->row_head = (row_head?TRUE:FALSE);
2716 g_object_notify (G_OBJECT (tree_column), "row_head");
2717 }
2718 }
2719
2720 /**
2721 * pspp_sheet_view_column_get_row_head:
2722 * @tree_column: A #PsppSheetViewColumn
2723 *
2724 * Returns %TRUE if the column is a row head.
2725 *
2726 * Return value: %TRUE if the column is a row head.
2727 **/
2728 gboolean
2729 pspp_sheet_view_column_get_row_head (PsppSheetViewColumn *tree_column)
2730 {
2731 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2732
2733 return tree_column->row_head;
2734 }
2735
2736
2737 /**
2738 * pspp_sheet_view_column_set_sort_column_id:
2739 * @tree_column: a #PsppSheetViewColumn
2740 * @sort_column_id: The @sort_column_id of the model to sort on.
2741 *
2742 * Sets the logical @sort_column_id that this column sorts on when this column
2743 * is selected for sorting. Doing so makes the column header clickable.
2744 **/
2745 void
2746 pspp_sheet_view_column_set_sort_column_id (PsppSheetViewColumn *tree_column,
2747 gint sort_column_id)
2748 {
2749 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2750 g_return_if_fail (sort_column_id >= -1);
2751
2752 if (tree_column->sort_column_id == sort_column_id)
2753 return;
2754
2755 tree_column->sort_column_id = sort_column_id;
2756
2757 /* Handle unsetting the id */
2758 if (sort_column_id == -1)
2759 {
2760 GtkTreeModel *model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
2761
2762 if (tree_column->sort_clicked_signal)
2763 {
2764 g_signal_handler_disconnect (tree_column, tree_column->sort_clicked_signal);
2765 tree_column->sort_clicked_signal = 0;
2766 }
2767
2768 if (tree_column->sort_column_changed_signal)
2769 {
2770 g_signal_handler_disconnect (model, tree_column->sort_column_changed_signal);
2771 tree_column->sort_column_changed_signal = 0;
2772 }
2773
2774 pspp_sheet_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2775 pspp_sheet_view_column_set_sort_indicator (tree_column, FALSE);
2776 pspp_sheet_view_column_set_clickable (tree_column, FALSE);
2777 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2778 return;
2779 }
2780
2781 pspp_sheet_view_column_set_clickable (tree_column, TRUE);
2782
2783 if (! tree_column->sort_clicked_signal)
2784 tree_column->sort_clicked_signal = g_signal_connect (tree_column,
2785 "clicked",
2786 G_CALLBACK (pspp_sheet_view_column_sort),
2787 NULL);
2788
2789 pspp_sheet_view_column_setup_sort_column_id_callback (tree_column);
2790 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2791 }
2792
2793 /**
2794 * pspp_sheet_view_column_get_sort_column_id:
2795 * @tree_column: a #PsppSheetViewColumn
2796 *
2797 * Gets the logical @sort_column_id that the model sorts on when this
2798 * column is selected for sorting.
2799 * See pspp_sheet_view_column_set_sort_column_id().
2800 *
2801 * Return value: the current @sort_column_id for this column, or -1 if
2802 * this column can't be used for sorting.
2803 **/
2804 gint
2805 pspp_sheet_view_column_get_sort_column_id (PsppSheetViewColumn *tree_column)
2806 {
2807 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
2808
2809 return tree_column->sort_column_id;
2810 }
2811
2812 /**
2813 * pspp_sheet_view_column_set_sort_indicator:
2814 * @tree_column: a #PsppSheetViewColumn
2815 * @setting: %TRUE to display an indicator that the column is sorted
2816 *
2817 * Call this function with a @setting of %TRUE to display an arrow in
2818 * the header button indicating the column is sorted. Call
2819 * pspp_sheet_view_column_set_sort_order() to change the direction of
2820 * the arrow.
2821 *
2822 **/
2823 void
2824 pspp_sheet_view_column_set_sort_indicator (PsppSheetViewColumn *tree_column,
2825 gboolean setting)
2826 {
2827 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2828
2829 setting = setting != FALSE;
2830
2831 if (setting == tree_column->show_sort_indicator)
2832 return;
2833
2834 tree_column->show_sort_indicator = setting;
2835 pspp_sheet_view_column_update_button (tree_column);
2836 g_object_notify (G_OBJECT (tree_column), "sort-indicator");
2837 }
2838
2839 /**
2840 * pspp_sheet_view_column_get_sort_indicator:
2841 * @tree_column: a #PsppSheetViewColumn
2842 *
2843 * Gets the value set by pspp_sheet_view_column_set_sort_indicator().
2844 *
2845 * Return value: whether the sort indicator arrow is displayed
2846 **/
2847 gboolean
2848 pspp_sheet_view_column_get_sort_indicator (PsppSheetViewColumn *tree_column)
2849 {
2850 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
2851
2852 return tree_column->show_sort_indicator;
2853 }
2854
2855 /**
2856 * pspp_sheet_view_column_set_sort_order:
2857 * @tree_column: a #PsppSheetViewColumn
2858 * @order: sort order that the sort indicator should indicate
2859 *
2860 * Changes the appearance of the sort indicator.
2861 *
2862 * This <emphasis>does not</emphasis> actually sort the model. Use
2863 * pspp_sheet_view_column_set_sort_column_id() if you want automatic sorting
2864 * support. This function is primarily for custom sorting behavior, and should
2865 * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2866 * that. For custom models, the mechanism will vary.
2867 *
2868 * The sort indicator changes direction to indicate normal sort or reverse sort.
2869 * Note that you must have the sort indicator enabled to see anything when
2870 * calling this function; see pspp_sheet_view_column_set_sort_indicator().
2871 **/
2872 void
2873 pspp_sheet_view_column_set_sort_order (PsppSheetViewColumn *tree_column,
2874 GtkSortType order)
2875 {
2876 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2877
2878 if (order == tree_column->sort_order)
2879 return;
2880
2881 tree_column->sort_order = order;
2882 pspp_sheet_view_column_update_button (tree_column);
2883 g_object_notify (G_OBJECT (tree_column), "sort-order");
2884 }
2885
2886 /**
2887 * pspp_sheet_view_column_get_sort_order:
2888 * @tree_column: a #PsppSheetViewColumn
2889 *
2890 * Gets the value set by pspp_sheet_view_column_set_sort_order().
2891 *
2892 * Return value: the sort order the sort indicator is indicating
2893 **/
2894 GtkSortType
2895 pspp_sheet_view_column_get_sort_order (PsppSheetViewColumn *tree_column)
2896 {
2897 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
2898
2899 return tree_column->sort_order;
2900 }
2901
2902 /**
2903 * pspp_sheet_view_column_cell_set_cell_data:
2904 * @tree_column: A #PsppSheetViewColumn.
2905 * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2906 * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2907 *
2908 * Sets the cell renderer based on the @tree_model and @iter. That is, for
2909 * every attribute mapping in @tree_column, it will get a value from the set
2910 * column on the @iter, and use that value to set the attribute on the cell
2911 * renderer. This is used primarily by the #PsppSheetView.
2912 **/
2913 void
2914 pspp_sheet_view_column_cell_set_cell_data (PsppSheetViewColumn *tree_column,
2915 GtkTreeModel *tree_model,
2916 GtkTreeIter *iter)
2917 {
2918 GSList *list;
2919 GValue value = { 0, };
2920 GList *cell_list;
2921
2922 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2923
2924 if (tree_model == NULL)
2925 return;
2926
2927 for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2928 {
2929 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) cell_list->data;
2930 GObject *cell = (GObject *) info->cell;
2931
2932 list = info->attributes;
2933
2934 g_object_freeze_notify (cell);
2935
2936 while (list && list->next)
2937 {
2938 gtk_tree_model_get_value (tree_model, iter,
2939 GPOINTER_TO_INT (list->next->data),
2940 &value);
2941 g_object_set_property (cell, (gchar *) list->data, &value);
2942 g_value_unset (&value);
2943 list = list->next->next;
2944 }
2945
2946 if (info->func)
2947 (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2948 g_object_thaw_notify (G_OBJECT (info->cell));
2949 }
2950
2951 }
2952
2953 /**
2954 * pspp_sheet_view_column_cell_get_size:
2955 * @tree_column: A #PsppSheetViewColumn.
2956 * @cell_area: (allow-none): The area a cell in the column will be allocated, or %NULL
2957 * @x_offset: (allow-none): location to return x offset of a cell relative to @cell_area, or %NULL
2958 * @y_offset: (allow-none): location to return y offset of a cell relative to @cell_area, or %NULL
2959 * @width: (allow-none): location to return width needed to render a cell, or %NULL
2960 * @height: (allow-none): location to return height needed to render a cell, or %NULL
2961 *
2962 * Obtains the width and height needed to render the column. This is used
2963 * primarily by the #PsppSheetView.
2964 **/
2965 void
2966 pspp_sheet_view_column_cell_get_size (PsppSheetViewColumn *tree_column,
2967 const GdkRectangle *cell_area,
2968 gint *x_offset,
2969 gint *y_offset,
2970 gint *width,
2971 gint *height)
2972 {
2973 GList *list;
2974 gboolean first_cell = TRUE;
2975 gint focus_line_width;
2976
2977 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
2978
2979 if (height)
2980 * height = 0;
2981 if (width)
2982 * width = 0;
2983
2984 gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
2985
2986 for (list = tree_column->cell_list; list; list = list->next)
2987 {
2988 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
2989 gboolean visible;
2990 gint new_height = 0;
2991 gint new_width = 0;
2992 g_object_get (info->cell, "visible", &visible, NULL);
2993
2994 if (visible == FALSE)
2995 continue;
2996
2997 if (first_cell == FALSE && width)
2998 *width += tree_column->spacing;
2999
3000 gtk_cell_renderer_get_size (info->cell,
3001 tree_column->tree_view,
3002 cell_area,
3003 x_offset,
3004 y_offset,
3005 &new_width,
3006 &new_height);
3007
3008 if (height)
3009 * height = MAX (*height, new_height + focus_line_width * 2);
3010 info->requested_width = MAX (info->requested_width, new_width + focus_line_width * 2);
3011 if (width)
3012 * width += info->requested_width;
3013 first_cell = FALSE;
3014 }
3015 }
3016
3017 /* rendering, event handling and rendering focus are somewhat complicated, and
3018 * quite a bit of code. Rather than duplicate them, we put them together to
3019 * keep the code in one place.
3020 *
3021 * To better understand what's going on, check out
3022 * docs/tree-column-sizing.png
3023 */
3024 enum {
3025 CELL_ACTION_RENDER,
3026 CELL_ACTION_FOCUS,
3027 CELL_ACTION_EVENT
3028 };
3029
3030 static gboolean
3031 pspp_sheet_view_column_cell_process_action (PsppSheetViewColumn *tree_column,
3032 GdkWindow *window,
3033 const GdkRectangle *background_area,
3034 const GdkRectangle *cell_area,
3035 guint flags,
3036 gint action,
3037 const GdkRectangle *expose_area, /* RENDER */
3038 GdkRectangle *focus_rectangle, /* FOCUS */
3039 GtkCellEditable **editable_widget, /* EVENT */
3040 GdkEvent *event, /* EVENT */
3041 gchar *path_string) /* EVENT */
3042 {
3043 GList *list;
3044 GdkRectangle real_cell_area;
3045 GdkRectangle real_background_area;
3046 GdkRectangle real_expose_area = *cell_area;
3047 gint depth = 0;
3048 gint expand_cell_count = 0;
3049 gint full_requested_width = 0;
3050 gint extra_space;
3051 gint min_x, min_y, max_x, max_y;
3052 gint focus_line_width;
3053 gint special_cells;
3054 gint horizontal_separator;
3055 gboolean cursor_row = FALSE;
3056 gboolean first_cell = TRUE;
3057 gboolean rtl;
3058 /* If we have rtl text, we need to transform our areas */
3059 GdkRectangle rtl_cell_area;
3060 GdkRectangle rtl_background_area;
3061
3062 min_x = G_MAXINT;
3063 min_y = G_MAXINT;
3064 max_x = 0;
3065 max_y = 0;
3066
3067 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL);
3068 special_cells = _pspp_sheet_view_column_count_special_cells (tree_column);
3069
3070 if (special_cells > 1 && action == CELL_ACTION_FOCUS)
3071 {
3072 PsppSheetViewColumnCellInfo *info = NULL;
3073 gboolean found_has_focus = FALSE;
3074
3075 /* one should have focus */
3076 for (list = tree_column->cell_list; list; list = list->next)
3077 {
3078 info = list->data;
3079 if (info && info->has_focus)
3080 {
3081 found_has_focus = TRUE;
3082 break;
3083 }
3084 }
3085
3086 if (!found_has_focus)
3087 {
3088 /* give the first one focus */
3089 info = pspp_sheet_view_column_cell_first (tree_column)->data;
3090 info->has_focus = TRUE;
3091 }
3092 }
3093
3094 cursor_row = flags & GTK_CELL_RENDERER_FOCUSED;
3095
3096 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
3097 "focus-line-width", &focus_line_width,
3098 "horizontal-separator", &horizontal_separator,
3099 NULL);
3100
3101 real_cell_area = *cell_area;
3102 real_background_area = *background_area;
3103
3104
3105 real_cell_area.x += focus_line_width;
3106 real_cell_area.y += focus_line_width;
3107 real_cell_area.height -= 2 * focus_line_width;
3108
3109 if (rtl)
3110 depth = real_background_area.width - real_cell_area.width;
3111 else
3112 depth = real_cell_area.x - real_background_area.x;
3113
3114 /* Find out how much extra space we have to allocate */
3115 for (list = tree_column->cell_list; list; list = list->next)
3116 {
3117 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)list->data;
3118
3119 if (! info->cell->visible)
3120 continue;
3121
3122 if (info->expand == TRUE)
3123 expand_cell_count ++;
3124 full_requested_width += info->requested_width;
3125
3126 if (!first_cell)
3127 full_requested_width += tree_column->spacing;
3128
3129 first_cell = FALSE;
3130 }
3131
3132 extra_space = cell_area->width - full_requested_width;
3133 if (extra_space < 0)
3134 extra_space = 0;
3135 else if (extra_space > 0 && expand_cell_count > 0)
3136 extra_space /= expand_cell_count;
3137
3138 /* iterate list for GTK_PACK_START cells */
3139 for (list = tree_column->cell_list; list; list = list->next)
3140 {
3141 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
3142
3143 if (info->pack == GTK_PACK_END)
3144 continue;
3145
3146 if (! info->cell->visible)
3147 continue;
3148
3149 if ((info->has_focus || special_cells == 1) && cursor_row)
3150 flags |= GTK_CELL_RENDERER_FOCUSED;
3151 else
3152 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3153
3154 info->real_width = info->requested_width + (info->expand?extra_space:0);
3155
3156 /* We constrain ourselves to only the width available */
3157 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
3158 {
3159 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
3160 }
3161
3162 if (real_cell_area.x > cell_area->x + cell_area->width)
3163 break;
3164
3165 real_cell_area.width = info->real_width;
3166 real_cell_area.width -= 2 * focus_line_width;
3167
3168 if (list->next)
3169 {
3170 real_background_area.width = info->real_width + depth;
3171 }
3172 else
3173 {
3174 /* fill the rest of background for the last cell */
3175 real_background_area.width = background_area->x + background_area->width - real_background_area.x;
3176 }
3177
3178 rtl_cell_area = real_cell_area;
3179 rtl_background_area = real_background_area;
3180
3181 if (rtl)
3182 {
3183 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
3184 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
3185 }
3186
3187 /* RENDER */
3188 if (action == CELL_ACTION_RENDER)
3189 {
3190 gtk_cell_renderer_render (info->cell,
3191 window,
3192 tree_column->tree_view,
3193 &rtl_background_area,
3194 &rtl_cell_area,
3195 &real_expose_area,
3196 flags);
3197 }
3198 /* FOCUS */
3199 else if (action == CELL_ACTION_FOCUS)
3200 {
3201 gint x_offset, y_offset, width, height;
3202
3203 gtk_cell_renderer_get_size (info->cell,
3204 tree_column->tree_view,
3205 &rtl_cell_area,
3206 &x_offset, &y_offset,
3207 &width, &height);
3208
3209 if (special_cells > 1)
3210 {
3211 if (info->has_focus)
3212 {
3213 min_x = rtl_cell_area.x + x_offset;
3214 max_x = min_x + width;
3215 min_y = rtl_cell_area.y + y_offset;
3216 max_y = min_y + height;
3217 }
3218 }
3219 else
3220 {
3221 if (min_x > (rtl_cell_area.x + x_offset))
3222 min_x = rtl_cell_area.x + x_offset;
3223 if (max_x < rtl_cell_area.x + x_offset + width)
3224 max_x = rtl_cell_area.x + x_offset + width;
3225 if (min_y > (rtl_cell_area.y + y_offset))
3226 min_y = rtl_cell_area.y + y_offset;
3227 if (max_y < rtl_cell_area.y + y_offset + height)
3228 max_y = rtl_cell_area.y + y_offset + height;
3229 }
3230 }
3231 /* EVENT */
3232 else if (action == CELL_ACTION_EVENT)
3233 {
3234 gboolean try_event = FALSE;
3235
3236 if (event)
3237 {
3238 if (special_cells == 1)
3239 {
3240 /* only 1 activatable cell -> whole column can activate */
3241 if (cell_area->x <= ((GdkEventButton *)event)->x &&
3242 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
3243 try_event = TRUE;
3244 }
3245 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
3246 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
3247 /* only activate cell if the user clicked on an individual
3248 * cell
3249 */
3250 try_event = TRUE;
3251 }
3252 else if (special_cells > 1 && info->has_focus)
3253 try_event = TRUE;
3254 else if (special_cells == 1)
3255 try_event = TRUE;
3256
3257 if (try_event)
3258 {
3259 gboolean visible, mode;
3260
3261 g_object_get (info->cell,
3262 "visible", &visible,
3263 "mode", &mode,
3264 NULL);
3265 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
3266 {
3267 if (gtk_cell_renderer_activate (info->cell,
3268 event,
3269 tree_column->tree_view,
3270 path_string,
3271 &rtl_background_area,
3272 &rtl_cell_area,
3273 flags))
3274 {
3275 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3276 return TRUE;
3277 }
3278 }
3279 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
3280 {
3281 *editable_widget =
3282 gtk_cell_renderer_start_editing (info->cell,
3283 event,
3284 tree_column->tree_view,
3285 path_string,
3286 &rtl_background_area,
3287 &rtl_cell_area,
3288 flags);
3289
3290 if (*editable_widget != NULL)
3291 {
3292 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
3293 info->in_editing_mode = TRUE;
3294 pspp_sheet_view_column_focus_cell (tree_column, info->cell);
3295
3296 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3297
3298 return TRUE;
3299 }
3300 }
3301 }
3302 }
3303
3304 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3305
3306 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
3307 real_background_area.x += real_background_area.width + tree_column->spacing;
3308
3309 /* Only needed for first cell */
3310 depth = 0;
3311 }
3312
3313 /* iterate list for PACK_END cells */
3314 for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
3315 {
3316 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
3317
3318 if (info->pack == GTK_PACK_START)
3319 continue;
3320
3321 if (! info->cell->visible)
3322 continue;
3323
3324 if ((info->has_focus || special_cells == 1) && cursor_row)
3325 flags |= GTK_CELL_RENDERER_FOCUSED;
3326 else
3327 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3328
3329 info->real_width = info->requested_width + (info->expand?extra_space:0);
3330
3331 /* We constrain ourselves to only the width available */
3332 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
3333 {
3334 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
3335 }
3336
3337 if (real_cell_area.x > cell_area->x + cell_area->width)
3338 break;
3339
3340 real_cell_area.width = info->real_width;
3341 real_cell_area.width -= 2 * focus_line_width;
3342 real_background_area.width = info->real_width + depth;
3343
3344 rtl_cell_area = real_cell_area;
3345 rtl_background_area = real_background_area;
3346 if (rtl)
3347 {
3348 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
3349 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
3350 }
3351
3352 /* RENDER */
3353 if (action == CELL_ACTION_RENDER)
3354 {
3355 gtk_cell_renderer_render (info->cell,
3356 window,
3357 tree_column->tree_view,
3358 &rtl_background_area,
3359 &rtl_cell_area,
3360 &real_expose_area,
3361 flags);
3362 }
3363 /* FOCUS */
3364 else if (action == CELL_ACTION_FOCUS)
3365 {
3366 gint x_offset, y_offset, width, height;
3367
3368 gtk_cell_renderer_get_size (info->cell,
3369 tree_column->tree_view,
3370 &rtl_cell_area,
3371 &x_offset, &y_offset,
3372 &width, &height);
3373
3374 if (special_cells > 1)
3375 {
3376 if (info->has_focus)
3377 {
3378 min_x = rtl_cell_area.x + x_offset;
3379 max_x = min_x + width;
3380 min_y = rtl_cell_area.y + y_offset;
3381 max_y = min_y + height;
3382 }
3383 }
3384 else
3385 {
3386 if (min_x > (rtl_cell_area.x + x_offset))
3387 min_x = rtl_cell_area.x + x_offset;
3388 if (max_x < rtl_cell_area.x + x_offset + width)
3389 max_x = rtl_cell_area.x + x_offset + width;
3390 if (min_y > (rtl_cell_area.y + y_offset))
3391 min_y = rtl_cell_area.y + y_offset;
3392 if (max_y < rtl_cell_area.y + y_offset + height)
3393 max_y = rtl_cell_area.y + y_offset + height;
3394 }
3395 }
3396 /* EVENT */
3397 else if (action == CELL_ACTION_EVENT)
3398 {
3399 gboolean try_event = FALSE;
3400
3401 if (event)
3402 {
3403 if (special_cells == 1)
3404 {
3405 /* only 1 activatable cell -> whole column can activate */
3406 if (cell_area->x <= ((GdkEventButton *)event)->x &&
3407 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
3408 try_event = TRUE;
3409 }
3410 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
3411 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
3412 /* only activate cell if the user clicked on an individual
3413 * cell
3414 */
3415 try_event = TRUE;
3416 }
3417 else if (special_cells > 1 && info->has_focus)
3418 try_event = TRUE;
3419 else if (special_cells == 1)
3420 try_event = TRUE;
3421
3422 if (try_event)
3423 {
3424 gboolean visible, mode;
3425
3426 g_object_get (info->cell,
3427 "visible", &visible,
3428 "mode", &mode,
3429 NULL);
3430 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
3431 {
3432 if (gtk_cell_renderer_activate (info->cell,
3433 event,
3434 tree_column->tree_view,
3435 path_string,
3436 &rtl_background_area,
3437 &rtl_cell_area,
3438 flags))
3439 {
3440 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3441 return TRUE;
3442 }
3443 }
3444 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
3445 {
3446 *editable_widget =
3447 gtk_cell_renderer_start_editing (info->cell,
3448 event,
3449 tree_column->tree_view,
3450 path_string,
3451 &rtl_background_area,
3452 &rtl_cell_area,
3453 flags);
3454
3455 if (*editable_widget != NULL)
3456 {
3457 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
3458 info->in_editing_mode = TRUE;
3459 pspp_sheet_view_column_focus_cell (tree_column, info->cell);
3460
3461 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3462 return TRUE;
3463 }
3464 }
3465 }
3466 }
3467
3468 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3469
3470 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
3471 real_background_area.x += (real_background_area.width + tree_column->spacing);
3472
3473 /* Only needed for first cell */
3474 depth = 0;
3475 }
3476
3477 /* fill focus_rectangle when required */
3478 if (action == CELL_ACTION_FOCUS)
3479 {
3480 if (min_x >= max_x || min_y >= max_y)
3481 {
3482 *focus_rectangle = *cell_area;
3483 /* don't change the focus_rectangle, just draw it nicely inside
3484 * the cell area */
3485 }
3486 else
3487 {
3488 focus_rectangle->x = min_x - focus_line_width;
3489 focus_rectangle->y = min_y - focus_line_width;
3490 focus_rectangle->width = (max_x - min_x) + 2 * focus_line_width;
3491 focus_rectangle->height = (max_y - min_y) + 2 * focus_line_width;
3492 }
3493 }
3494
3495 return FALSE;
3496 }
3497
3498 /**
3499 * pspp_sheet_view_column_cell_render:
3500 * @tree_column: A #PsppSheetViewColumn.
3501 * @window: a #GdkDrawable to draw to
3502 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
3503 * @cell_area: area normally rendered by a cell renderer
3504 * @expose_area: area that actually needs updating
3505 * @flags: flags that affect rendering
3506 *
3507 * Renders the cell contained by #tree_column. This is used primarily by the
3508 * #PsppSheetView.
3509 **/
3510 void
3511 _pspp_sheet_view_column_cell_render (PsppSheetViewColumn *tree_column,
3512 GdkWindow *window,
3513 const GdkRectangle *background_area,
3514 const GdkRectangle *cell_area,
3515 const GdkRectangle *expose_area,
3516 guint flags)
3517 {
3518 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
3519 g_return_if_fail (background_area != NULL);
3520 g_return_if_fail (cell_area != NULL);
3521 g_return_if_fail (expose_area != NULL);
3522
3523 pspp_sheet_view_column_cell_process_action (tree_column,
3524 window,
3525 background_area,
3526 cell_area,
3527 flags,
3528 CELL_ACTION_RENDER,
3529 expose_area,
3530 NULL, NULL, NULL, NULL);
3531 }
3532
3533 gboolean
3534 _pspp_sheet_view_column_cell_event (PsppSheetViewColumn *tree_column,
3535 GtkCellEditable **editable_widget,
3536 GdkEvent *event,
3537 gchar *path_string,
3538 const GdkRectangle *background_area,
3539 const GdkRectangle *cell_area,
3540 guint flags)
3541 {
3542 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
3543
3544 return pspp_sheet_view_column_cell_process_action (tree_column,
3545 NULL,
3546 background_area,
3547 cell_area,
3548 flags,
3549 CELL_ACTION_EVENT,
3550 NULL, NULL,
3551 editable_widget,
3552 event,
3553 path_string);
3554 }
3555
3556 void
3557 _pspp_sheet_view_column_get_focus_area (PsppSheetViewColumn *tree_column,
3558 const GdkRectangle *background_area,
3559 const GdkRectangle *cell_area,
3560 GdkRectangle *focus_area)
3561 {
3562 pspp_sheet_view_column_cell_process_action (tree_column,
3563 NULL,
3564 background_area,
3565 cell_area,
3566 0,
3567 CELL_ACTION_FOCUS,
3568 NULL,
3569 focus_area,
3570 NULL, NULL, NULL);
3571 }
3572
3573
3574 /* cell list manipulation */
3575 static GList *
3576 pspp_sheet_view_column_cell_first (PsppSheetViewColumn *tree_column)
3577 {
3578 GList *list = tree_column->cell_list;
3579
3580 /* first GTK_PACK_START cell we find */
3581 for ( ; list; list = list->next)
3582 {
3583 PsppSheetViewColumnCellInfo *info = list->data;
3584 if (info->pack == GTK_PACK_START)
3585 return list;
3586 }
3587
3588 /* hmm, else the *last* GTK_PACK_END cell */
3589 list = g_list_last (tree_column->cell_list);
3590
3591 for ( ; list; list = list->prev)
3592 {
3593 PsppSheetViewColumnCellInfo *info = list->data;
3594 if (info->pack == GTK_PACK_END)
3595 return list;
3596 }
3597
3598 return NULL;
3599 }
3600
3601 static GList *
3602 pspp_sheet_view_column_cell_last (PsppSheetViewColumn *tree_column)
3603 {
3604 GList *list = tree_column->cell_list;
3605
3606 /* *first* GTK_PACK_END cell we find */
3607 for ( ; list ; list = list->next)
3608 {
3609 PsppSheetViewColumnCellInfo *info = list->data;
3610 if (info->pack == GTK_PACK_END)
3611 return list;
3612 }
3613
3614 /* hmm, else the last GTK_PACK_START cell */
3615 list = g_list_last (tree_column->cell_list);
3616
3617 for ( ; list; list = list->prev)
3618 {
3619 PsppSheetViewColumnCellInfo *info = list->data;
3620 if (info->pack == GTK_PACK_START)
3621 return list;
3622 }
3623
3624 return NULL;
3625 }
3626
3627 static GList *
3628 pspp_sheet_view_column_cell_next (PsppSheetViewColumn *tree_column,
3629 GList *current)
3630 {
3631 GList *list;
3632 PsppSheetViewColumnCellInfo *info = current->data;
3633
3634 if (info->pack == GTK_PACK_START)
3635 {
3636 for (list = current->next; list; list = list->next)
3637 {
3638 PsppSheetViewColumnCellInfo *inf = list->data;
3639 if (inf->pack == GTK_PACK_START)
3640 return list;
3641 }
3642
3643 /* out of GTK_PACK_START cells, get *last* GTK_PACK_END one */
3644 list = g_list_last (tree_column->cell_list);
3645 for (; list; list = list->prev)
3646 {
3647 PsppSheetViewColumnCellInfo *inf = list->data;
3648 if (inf->pack == GTK_PACK_END)
3649 return list;
3650 }
3651 }
3652
3653 for (list = current->prev; list; list = list->prev)
3654 {
3655 PsppSheetViewColumnCellInfo *inf = list->data;
3656 if (inf->pack == GTK_PACK_END)
3657 return list;
3658 }
3659
3660 return NULL;
3661 }
3662
3663 static GList *
3664 pspp_sheet_view_column_cell_prev (PsppSheetViewColumn *tree_column,
3665 GList *current)
3666 {
3667 GList *list;
3668 PsppSheetViewColumnCellInfo *info = current->data;
3669
3670 if (info->pack == GTK_PACK_END)
3671 {
3672 for (list = current->next; list; list = list->next)
3673 {
3674 PsppSheetViewColumnCellInfo *inf = list->data;
3675 if (inf->pack == GTK_PACK_END)
3676 return list;
3677 }
3678
3679 /* out of GTK_PACK_END, get last GTK_PACK_START one */
3680 list = g_list_last (tree_column->cell_list);
3681 for ( ; list; list = list->prev)
3682 {
3683 PsppSheetViewColumnCellInfo *inf = list->data;
3684 if (inf->pack == GTK_PACK_START)
3685 return list;
3686 }
3687 }
3688
3689 for (list = current->prev; list; list = list->prev)
3690 {
3691 PsppSheetViewColumnCellInfo *inf = list->data;
3692 if (inf->pack == GTK_PACK_START)
3693 return list;
3694 }
3695
3696 return NULL;
3697 }
3698
3699 gboolean
3700 _pspp_sheet_view_column_cell_focus (PsppSheetViewColumn *tree_column,
3701 gint direction,
3702 gboolean left,
3703 gboolean right)
3704 {
3705 gint count;
3706 gboolean rtl;
3707
3708 count = _pspp_sheet_view_column_count_special_cells (tree_column);
3709 rtl = gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL;
3710
3711 /* if we are the current focus column and have multiple editable cells,
3712 * try to select the next one, else move the focus to the next column
3713 */
3714 if (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
3715 {
3716 if (count > 1)
3717 {
3718 GList *next, *prev;
3719 GList *list = tree_column->cell_list;
3720 PsppSheetViewColumnCellInfo *info = NULL;
3721
3722 /* find current focussed cell */
3723 for ( ; list; list = list->next)
3724 {
3725 info = list->data;
3726 if (info->has_focus)
3727 break;
3728 }
3729
3730 /* not a focussed cell in the focus column? */
3731 if (!list || !info || !info->has_focus)
3732 return FALSE;
3733
3734 if (rtl)
3735 {
3736 prev = pspp_sheet_view_column_cell_next (tree_column, list);
3737 next = pspp_sheet_view_column_cell_prev (tree_column, list);
3738 }
3739 else
3740 {
3741 next = pspp_sheet_view_column_cell_next (tree_column, list);
3742 prev = pspp_sheet_view_column_cell_prev (tree_column, list);
3743 }
3744
3745 info->has_focus = FALSE;
3746 if (direction > 0 && next)
3747 {
3748 info = next->data;
3749 info->has_focus = TRUE;
3750 return TRUE;
3751 }
3752 else if (direction > 0 && !next && !right)
3753 {
3754 /* keep focus on last cell */
3755 if (rtl)
3756 info = pspp_sheet_view_column_cell_first (tree_column)->data;
3757 else
3758 info = pspp_sheet_view_column_cell_last (tree_column)->data;
3759
3760 info->has_focus = TRUE;
3761 return TRUE;
3762 }
3763 else if (direction < 0 && prev)
3764 {
3765 info = prev->data;
3766 info->has_focus = TRUE;
3767 return TRUE;
3768 }
3769 else if (direction < 0 && !prev && !left)
3770 {
3771 /* keep focus on first cell */
3772 if (rtl)
3773 info = pspp_sheet_view_column_cell_last (tree_column)->data;
3774 else
3775 info = pspp_sheet_view_column_cell_first (tree_column)->data;
3776
3777 info->has_focus = TRUE;
3778 return TRUE;
3779 }
3780 }
3781 return FALSE;
3782 }
3783
3784 /* we get focus, if we have multiple editable cells, give the correct one
3785 * focus
3786 */
3787 if (count > 1)
3788 {
3789 GList *list = tree_column->cell_list;
3790
3791 /* clear focus first */
3792 for ( ; list ; list = list->next)
3793 {
3794 PsppSheetViewColumnCellInfo *info = list->data;
3795 if (info->has_focus)
3796 info->has_focus = FALSE;
3797 }
3798
3799 list = NULL;
3800 if (rtl)
3801 {
3802 if (direction > 0)
3803 list = pspp_sheet_view_column_cell_last (tree_column);
3804 else if (direction < 0)
3805 list = pspp_sheet_view_column_cell_first (tree_column);
3806 }
3807 else
3808 {
3809 if (direction > 0)
3810 list = pspp_sheet_view_column_cell_first (tree_column);
3811 else if (direction < 0)
3812 list = pspp_sheet_view_column_cell_last (tree_column);
3813 }
3814
3815 if (list)
3816 ((PsppSheetViewColumnCellInfo *) list->data)->has_focus = TRUE;
3817 }
3818
3819 return TRUE;
3820 }
3821
3822 void
3823 _pspp_sheet_view_column_cell_draw_focus (PsppSheetViewColumn *tree_column,
3824 GdkWindow *window,
3825 const GdkRectangle *background_area,
3826 const GdkRectangle *cell_area,
3827 const GdkRectangle *expose_area,
3828 guint flags)
3829 {
3830 gint focus_line_width;
3831 GtkStateType cell_state;
3832
3833 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
3834 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
3835 "focus-line-width", &focus_line_width, NULL);
3836 if (tree_column->editable_widget)
3837 {
3838 /* This function is only called on the editable row when editing.
3839 */
3840 #if 0
3841 gtk_paint_focus (tree_column->tree_view->style,
3842 window,
3843 gtk_widget_get_state (tree_column->tree_view),
3844 NULL,
3845 tree_column->tree_view,
3846 "treeview",
3847 cell_area->x - focus_line_width,
3848 cell_area->y - focus_line_width,
3849 cell_area->width + 2 * focus_line_width,
3850 cell_area->height + 2 * focus_line_width);
3851 #endif
3852 }
3853 else
3854 {
3855 GdkRectangle focus_rectangle;
3856 pspp_sheet_view_column_cell_process_action (tree_column,
3857 window,
3858 background_area,
3859 cell_area,
3860 flags,
3861 CELL_ACTION_FOCUS,
3862 expose_area,
3863 &focus_rectangle,
3864 NULL, NULL, NULL);
3865
3866 cell_state = flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
3867 (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
3868 (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL));
3869 gtk_paint_focus (tree_column->tree_view->style,
3870 window,
3871 cell_state,
3872 cell_area,
3873 tree_column->tree_view,
3874 "treeview",
3875 focus_rectangle.x,
3876 focus_rectangle.y,
3877 focus_rectangle.width,
3878 focus_rectangle.height);
3879 }
3880 }
3881
3882 /**
3883 * pspp_sheet_view_column_cell_is_visible:
3884 * @tree_column: A #PsppSheetViewColumn
3885 *
3886 * Returns %TRUE if any of the cells packed into the @tree_column are visible.
3887 * For this to be meaningful, you must first initialize the cells with
3888 * pspp_sheet_view_column_cell_set_cell_data()
3889 *
3890 * Return value: %TRUE, if any of the cells packed into the @tree_column are currently visible
3891 **/
3892 gboolean
3893 pspp_sheet_view_column_cell_is_visible (PsppSheetViewColumn *tree_column)
3894 {
3895 GList *list;
3896
3897 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
3898
3899 for (list = tree_column->cell_list; list; list = list->next)
3900 {
3901 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
3902
3903 if (info->cell->visible)
3904 return TRUE;
3905 }
3906
3907 return FALSE;
3908 }
3909
3910 /**
3911 * pspp_sheet_view_column_focus_cell:
3912 * @tree_column: A #PsppSheetViewColumn
3913 * @cell: A #GtkCellRenderer
3914 *
3915 * Sets the current keyboard focus to be at @cell, if the column contains
3916 * 2 or more editable and activatable cells.
3917 *
3918 * Since: 2.2
3919 **/
3920 void
3921 pspp_sheet_view_column_focus_cell (PsppSheetViewColumn *tree_column,
3922 GtkCellRenderer *cell)
3923 {
3924 GList *list;
3925 gboolean found_cell = FALSE;
3926
3927 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
3928 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
3929
3930 if (_pspp_sheet_view_column_count_special_cells (tree_column) < 2)
3931 return;
3932
3933 for (list = tree_column->cell_list; list; list = list->next)
3934 {
3935 PsppSheetViewColumnCellInfo *info = list->data;
3936
3937 if (info->cell == cell)
3938 {
3939 info->has_focus = TRUE;
3940 found_cell = TRUE;
3941 break;
3942 }
3943 }
3944
3945 if (found_cell)
3946 {
3947 for (list = tree_column->cell_list; list; list = list->next)
3948 {
3949 PsppSheetViewColumnCellInfo *info = list->data;
3950
3951 if (info->cell != cell)
3952 info->has_focus = FALSE;
3953 }
3954
3955 /* FIXME: redraw? */
3956 }
3957 }
3958
3959 void
3960 _pspp_sheet_view_column_cell_set_dirty (PsppSheetViewColumn *tree_column)
3961 {
3962 GList *list;
3963
3964 for (list = tree_column->cell_list; list; list = list->next)
3965 {
3966 PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
3967
3968 info->requested_width = 0;
3969 }
3970 tree_column->dirty = TRUE;
3971 tree_column->requested_width = -1;
3972 tree_column->width = 0;
3973
3974 if (tree_column->tree_view &&
3975 gtk_widget_get_realized (tree_column->tree_view))
3976 {
3977 _pspp_sheet_view_install_mark_rows_col_dirty (PSPP_SHEET_VIEW (tree_column->tree_view));
3978 gtk_widget_queue_resize (tree_column->tree_view);
3979 }
3980 }
3981
3982 void
3983 _pspp_sheet_view_column_start_editing (PsppSheetViewColumn *tree_column,
3984 GtkCellEditable *cell_editable)
3985 {
3986 g_return_if_fail (tree_column->editable_widget == NULL);
3987
3988 tree_column->editable_widget = cell_editable;
3989 }
3990
3991 void
3992 _pspp_sheet_view_column_stop_editing (PsppSheetViewColumn *tree_column)
3993 {
3994 GList *list;
3995
3996 g_return_if_fail (tree_column->editable_widget != NULL);
3997
3998 tree_column->editable_widget = NULL;
3999 for (list = tree_column->cell_list; list; list = list->next)
4000 ((PsppSheetViewColumnCellInfo *)list->data)->in_editing_mode = FALSE;
4001 }
4002
4003 void
4004 _pspp_sheet_view_column_get_neighbor_sizes (PsppSheetViewColumn *column,
4005 GtkCellRenderer *cell,
4006 gint *left,
4007 gint *right)
4008 {
4009 GList *list;
4010 PsppSheetViewColumnCellInfo *info;
4011 gint l, r;
4012 gboolean rtl;
4013
4014 l = r = 0;
4015
4016 list = pspp_sheet_view_column_cell_first (column);
4017
4018 while (list)
4019 {
4020 info = (PsppSheetViewColumnCellInfo *)list->data;
4021
4022 list = pspp_sheet_view_column_cell_next (column, list);
4023
4024 if (info->cell == cell)
4025 break;
4026
4027 if (info->cell->visible)
4028 l += info->real_width + column->spacing;
4029 }
4030
4031 while (list)
4032 {
4033 info = (PsppSheetViewColumnCellInfo *)list->data;
4034
4035 list = pspp_sheet_view_column_cell_next (column, list);
4036
4037 if (info->cell->visible)
4038 r += info->real_width + column->spacing;
4039 }
4040
4041 rtl = (gtk_widget_get_direction (GTK_WIDGET (column->tree_view)) == GTK_TEXT_DIR_RTL);
4042 if (left)
4043 *left = rtl ? r : l;
4044
4045 if (right)
4046 *right = rtl ? l : r;
4047 }
4048
4049 /**
4050 * pspp_sheet_view_column_cell_get_position:
4051 * @tree_column: a #PsppSheetViewColumn
4052 * @cell_renderer: a #GtkCellRenderer
4053 * @start_pos: return location for the horizontal position of @cell within
4054 * @tree_column, may be %NULL
4055 * @width: return location for the width of @cell, may be %NULL
4056 *
4057 * Obtains the horizontal position and size of a cell in a column. If the
4058 * cell is not found in the column, @start_pos and @width are not changed and
4059 * %FALSE is returned.
4060 *
4061 * Return value: %TRUE if @cell belongs to @tree_column.
4062 */
4063 gboolean
4064 pspp_sheet_view_column_cell_get_position (PsppSheetViewColumn *tree_column,
4065 GtkCellRenderer *cell_renderer,
4066 gint *start_pos,
4067 gint *width)
4068 {
4069 GList *list;
4070 gint current_x = 0;
4071 gboolean found_cell = FALSE;
4072 PsppSheetViewColumnCellInfo *cellinfo = NULL;
4073
4074 list = pspp_sheet_view_column_cell_first (tree_column);
4075 for (; list; list = pspp_sheet_view_column_cell_next (tree_column, list))
4076 {
4077 cellinfo = list->data;
4078 if (cellinfo->cell == cell_renderer)
4079 {
4080 found_cell = TRUE;
4081 break;
4082 }
4083
4084 if (cellinfo->cell->visible)
4085 current_x += cellinfo->real_width;
4086 }
4087
4088 if (found_cell)
4089 {
4090 if (start_pos)
4091 *start_pos = current_x;
4092 if (width)
4093 *width = cellinfo->real_width;
4094 }
4095
4096 return found_cell;
4097 }
4098
4099 /**
4100 * pspp_sheet_view_column_queue_resize:
4101 * @tree_column: A #PsppSheetViewColumn
4102 *
4103 * Flags the column, and the cell renderers added to this column, to have
4104 * their sizes renegotiated.
4105 *
4106 * Since: 2.8
4107 **/
4108 void
4109 pspp_sheet_view_column_queue_resize (PsppSheetViewColumn *tree_column)
4110 {
4111 g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
4112
4113 if (tree_column->tree_view)
4114 _pspp_sheet_view_column_cell_set_dirty (tree_column);
4115 }
4116
4117 /**
4118 * pspp_sheet_view_column_get_tree_view:
4119 * @tree_column: A #PsppSheetViewColumn
4120 *
4121 * Returns the #PsppSheetView wherein @tree_column has been inserted. If
4122 * @column is currently not inserted in any tree view, %NULL is
4123 * returned.
4124 *
4125 * Return value: The tree view wherein @column has been inserted if any,
4126 * %NULL otherwise.
4127 *
4128 * Since: 2.12
4129 */
4130 GtkWidget *
4131 pspp_sheet_view_column_get_tree_view (PsppSheetViewColumn *tree_column)
4132 {
4133 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
4134
4135 return tree_column->tree_view;
4136 }
4137
4138 typedef struct {
4139 GtkCellLayout *cell_layout;
4140 GtkCellRenderer *renderer;
4141 gchar *attr_name;
4142 } AttributesSubParserData;
4143
4144 static void
4145 attributes_start_element (GMarkupParseContext *context,
4146 const gchar *element_name,
4147 const gchar **names,
4148 const gchar **values,
4149 gpointer user_data,
4150 GError **error)
4151 {
4152 AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
4153 guint i;
4154
4155 if (strcmp (element_name, "attribute") == 0)
4156 {
4157 for (i = 0; names[i]; i++)
4158 if (strcmp (names[i], "name") == 0)
4159 parser_data->attr_name = g_strdup (values[i]);
4160 }
4161 else if (strcmp (element_name, "attributes") == 0)
4162 return;
4163 else
4164 g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
4165 }
4166
4167 static void
4168 attributes_text_element (GMarkupParseContext *context,
4169 const gchar *text,
4170 gsize text_len,
4171 gpointer user_data,
4172 GError **error)
4173 {
4174 AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
4175 glong l;
4176 gchar *endptr;
4177 gchar *string;
4178
4179 if (!parser_data->attr_name)
4180 return;
4181
4182 errno = 0;
4183 string = g_strndup (text, text_len);
4184 l = strtol (string, &endptr, 0);
4185 if (errno || endptr == string)
4186 {
4187 g_set_error (error,
4188 GTK_BUILDER_ERROR,
4189 GTK_BUILDER_ERROR_INVALID_VALUE,
4190 "Could not parse integer `%s'",
4191 string);
4192 g_free (string);
4193 return;
4194 }
4195 g_free (string);
4196
4197 gtk_cell_layout_add_attribute (parser_data->cell_layout,
4198 parser_data->renderer,
4199 parser_data->attr_name, l);
4200 g_free (parser_data->attr_name);
4201 parser_data->attr_name = NULL;
4202 }
4203
4204 static const GMarkupParser attributes_parser =
4205 {
4206 attributes_start_element,
4207 NULL,
4208 attributes_text_element,
4209 };
4210
4211 gboolean
4212 _gtk_cell_layout_buildable_custom_tag_start (GtkBuildable *buildable,
4213 GtkBuilder *builder,
4214 GObject *child,
4215 const gchar *tagname,
4216 GMarkupParser *parser,
4217 gpointer *data)
4218 {
4219 AttributesSubParserData *parser_data;
4220
4221 if (!child)
4222 return FALSE;
4223
4224 if (strcmp (tagname, "attributes") == 0)
4225 {
4226 parser_data = g_slice_new0 (AttributesSubParserData);
4227 parser_data->cell_layout = GTK_CELL_LAYOUT (buildable);
4228 parser_data->renderer = GTK_CELL_RENDERER (child);
4229 parser_data->attr_name = NULL;
4230
4231 *parser = attributes_parser;
4232 *data = parser_data;
4233 return TRUE;
4234 }
4235
4236 return FALSE;
4237 }
4238
4239 void
4240 _gtk_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
4241 GtkBuilder *builder,
4242 GObject *child,
4243 const gchar *tagname,
4244 gpointer *data)
4245 {
4246 AttributesSubParserData *parser_data;
4247
4248 parser_data = (AttributesSubParserData*)data;
4249 g_assert (!parser_data->attr_name);
4250 g_slice_free (AttributesSubParserData, parser_data);
4251 }
4252
4253 void
4254 _gtk_cell_layout_buildable_add_child (GtkBuildable *buildable,
4255 GtkBuilder *builder,
4256 GObject *child,
4257 const gchar *type)
4258 {
4259 GtkCellLayoutIface *iface;
4260
4261 g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
4262 g_return_if_fail (GTK_IS_CELL_RENDERER (child));
4263
4264 iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
4265 g_return_if_fail (iface->pack_start != NULL);
4266 iface->pack_start (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);
4267 }
4268
4269 void
4270 pspp_sheet_view_column_size_request (PsppSheetViewColumn *tree_column,
4271 GtkRequisition *request)
4272 {
4273 GtkWidget *base = GTK_WIDGET (tree_column->tree_view);
4274 GtkRequisition label_req;
4275 GtkRequisition align_req;
4276 GtkRequisition arrow_req;
4277 GtkRequisition hbox_req;
4278 GtkStyle **button_style;
4279
4280 if (tree_column->button)
4281 {
4282 gtk_widget_size_request (tree_column->button, request);
4283 return;
4284 }
4285
4286 facade_label_get_size_request (0, 0, base, tree_column->title, &label_req);
4287 facade_alignment_get_size_request (0, 0, 0, 0, 0, &label_req, &align_req);
4288 facade_arrow_get_size_request (0, 0, &arrow_req);
4289
4290 facade_hbox_get_base_size_request (0, 2, 2, &hbox_req);
4291 facade_hbox_add_child_size_request (0, &arrow_req, 0, &hbox_req);
4292 facade_hbox_add_child_size_request (0, &align_req, 0, &hbox_req);
4293
4294 button_style = &PSPP_SHEET_VIEW (tree_column->tree_view)->priv->button_style;
4295 if (*button_style == NULL)
4296 {
4297 *button_style = facade_get_style (base, GTK_TYPE_BUTTON, 0);
4298 g_object_ref (*button_style);
4299 }
4300 facade_button_get_size_request (0, base, *button_style, &hbox_req, request);
4301 }
4302
4303 void
4304 pspp_sheet_view_column_size_allocate (PsppSheetViewColumn *tree_column,
4305 GtkAllocation *allocation)
4306 {
4307 tree_column->allocation = *allocation;
4308 if (tree_column->button)
4309 gtk_widget_size_allocate (tree_column->button, allocation);
4310 }
4311
4312 gboolean
4313 pspp_sheet_view_column_can_focus (PsppSheetViewColumn *tree_column)
4314 {
4315 return tree_column->reorderable || tree_column->clickable;
4316 }
4317
4318 void
4319 pspp_sheet_view_column_set_need_button (PsppSheetViewColumn *tree_column,
4320 gboolean need_button)
4321 {
4322 if (tree_column->need_button != need_button)
4323 {
4324 tree_column->need_button = need_button;
4325 pspp_sheet_view_column_update_button (tree_column);
4326 _pspp_sheet_view_column_realize_button (tree_column);
4327 }
4328 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeviewcolumn.h
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #ifndef __PSPP_SHEET_VIEW_COLUMN_H__
36 #define __PSPP_SHEET_VIEW_COLUMN_H__
37
38 #include <gtk/gtk.h>
39
40 G_BEGIN_DECLS
41
42 #define PSPP_TYPE_SHEET_VIEW_COLUMN (pspp_sheet_view_column_get_type ())
43 #define PSPP_SHEET_VIEW_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumn))
44 #define PSPP_SHEET_VIEW_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumnClass))
45 #define PSPP_IS_SHEET_VIEW_COLUMN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN))
46 #define PSPP_IS_SHEET_VIEW_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_VIEW_COLUMN))
47 #define PSPP_SHEET_VIEW_COLUMN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumnClass))
48
49 typedef struct _PsppSheetViewColumn PsppSheetViewColumn;
50 typedef struct _PsppSheetViewColumnClass PsppSheetViewColumnClass;
51
52 typedef void (* PsppSheetCellDataFunc) (PsppSheetViewColumn *tree_column,
53 GtkCellRenderer *cell,
54 GtkTreeModel *tree_model,
55 GtkTreeIter *iter,
56 gpointer data);
57
58
59 struct _PsppSheetViewColumn
60 {
61 GtkObject parent;
62
63 GtkWidget *GSEAL (tree_view);
64 GtkWidget *GSEAL (button);
65 GtkWidget *GSEAL (child);
66 GtkWidget *GSEAL (arrow);
67 GtkWidget *GSEAL (alignment);
68 GdkWindow *GSEAL (window);
69 GtkCellEditable *GSEAL (editable_widget);
70 gfloat GSEAL (xalign);
71 guint GSEAL (property_changed_signal);
72 gint GSEAL (spacing);
73 GtkAllocation GSEAL (allocation);
74
75 /* Sizing fields */
76 /* see gtk+/doc/tree-column-sizing.txt for more information on them */
77 gint GSEAL (requested_width);
78 gint GSEAL (button_request);
79 gint GSEAL (resized_width);
80 gint GSEAL (width);
81 gint GSEAL (fixed_width);
82 gint GSEAL (min_width);
83 gint GSEAL (max_width);
84
85 /* dragging columns */
86 gint GSEAL (drag_x);
87 gint GSEAL (drag_y);
88
89 gchar *GSEAL (title);
90 GList *GSEAL (cell_list);
91
92 /* Sorting */
93 guint GSEAL (sort_clicked_signal);
94 guint GSEAL (sort_column_changed_signal);
95 gint GSEAL (sort_column_id);
96 GtkSortType GSEAL (sort_order);
97
98 /* Flags */
99 guint GSEAL (visible) : 1;
100 guint GSEAL (resizable) : 1;
101 guint GSEAL (clickable) : 1;
102 guint GSEAL (dirty) : 1;
103 guint GSEAL (show_sort_indicator) : 1;
104 guint GSEAL (maybe_reordered) : 1;
105 guint GSEAL (reorderable) : 1;
106 guint GSEAL (use_resized_width) : 1;
107 guint GSEAL (expand) : 1;
108 guint GSEAL (quick_edit) : 1;
109 guint GSEAL (selected) : 1;
110 guint GSEAL (selectable) : 1;
111 guint GSEAL (row_head) : 1;
112 guint GSEAL (need_button) : 1;
113 };
114
115 struct _PsppSheetViewColumnClass
116 {
117 GtkObjectClass parent_class;
118
119 gboolean (*clicked) (PsppSheetViewColumn *tree_column);
120 gboolean (*button_press_event) (PsppSheetViewColumn *,
121 GdkEventButton *);
122
123 /* Padding for future expansion */
124 void (*_gtk_reserved1) (void);
125 void (*_gtk_reserved2) (void);
126 void (*_gtk_reserved3) (void);
127 void (*_gtk_reserved4) (void);
128 };
129
130 GType pspp_sheet_view_column_get_type (void) G_GNUC_CONST;
131 PsppSheetViewColumn *pspp_sheet_view_column_new (void);
132 PsppSheetViewColumn *pspp_sheet_view_column_new_with_attributes (const gchar *title,
133 GtkCellRenderer *cell,
134 ...) G_GNUC_NULL_TERMINATED;
135 void pspp_sheet_view_column_pack_start (PsppSheetViewColumn *tree_column,
136 GtkCellRenderer *cell,
137 gboolean expand);
138 void pspp_sheet_view_column_pack_end (PsppSheetViewColumn *tree_column,
139 GtkCellRenderer *cell,
140 gboolean expand);
141 void pspp_sheet_view_column_clear (PsppSheetViewColumn *tree_column);
142 #ifndef GTK_DISABLE_DEPRECATED
143 GList *pspp_sheet_view_column_get_cell_renderers (PsppSheetViewColumn *tree_column);
144 #endif
145 void pspp_sheet_view_column_add_attribute (PsppSheetViewColumn *tree_column,
146 GtkCellRenderer *cell_renderer,
147 const gchar *attribute,
148 gint column);
149 void pspp_sheet_view_column_set_attributes (PsppSheetViewColumn *tree_column,
150 GtkCellRenderer *cell_renderer,
151 ...) G_GNUC_NULL_TERMINATED;
152 void pspp_sheet_view_column_set_cell_data_func (PsppSheetViewColumn *tree_column,
153 GtkCellRenderer *cell_renderer,
154 PsppSheetCellDataFunc func,
155 gpointer func_data,
156 GDestroyNotify destroy);
157 void pspp_sheet_view_column_clear_attributes (PsppSheetViewColumn *tree_column,
158 GtkCellRenderer *cell_renderer);
159 void pspp_sheet_view_column_set_spacing (PsppSheetViewColumn *tree_column,
160 gint spacing);
161 gint pspp_sheet_view_column_get_spacing (PsppSheetViewColumn *tree_column);
162 void pspp_sheet_view_column_set_visible (PsppSheetViewColumn *tree_column,
163 gboolean visible);
164 gboolean pspp_sheet_view_column_get_visible (PsppSheetViewColumn *tree_column);
165 void pspp_sheet_view_column_set_resizable (PsppSheetViewColumn *tree_column,
166 gboolean resizable);
167 gboolean pspp_sheet_view_column_get_resizable (PsppSheetViewColumn *tree_column);
168 gint pspp_sheet_view_column_get_width (PsppSheetViewColumn *tree_column);
169 gint pspp_sheet_view_column_get_fixed_width (PsppSheetViewColumn *tree_column);
170 void pspp_sheet_view_column_set_fixed_width (PsppSheetViewColumn *tree_column,
171 gint fixed_width);
172 void pspp_sheet_view_column_set_min_width (PsppSheetViewColumn *tree_column,
173 gint min_width);
174 gint pspp_sheet_view_column_get_min_width (PsppSheetViewColumn *tree_column);
175 void pspp_sheet_view_column_set_max_width (PsppSheetViewColumn *tree_column,
176 gint max_width);
177 gint pspp_sheet_view_column_get_max_width (PsppSheetViewColumn *tree_column);
178 void pspp_sheet_view_column_clicked (PsppSheetViewColumn *tree_column);
179
180
181
182 /* Options for manipulating the column headers
183 */
184 void pspp_sheet_view_column_set_title (PsppSheetViewColumn *tree_column,
185 const gchar *title);
186 G_CONST_RETURN gchar *pspp_sheet_view_column_get_title (PsppSheetViewColumn *tree_column);
187 void pspp_sheet_view_column_set_expand (PsppSheetViewColumn *tree_column,
188 gboolean expand);
189 gboolean pspp_sheet_view_column_get_expand (PsppSheetViewColumn *tree_column);
190 void pspp_sheet_view_column_set_clickable (PsppSheetViewColumn *tree_column,
191 gboolean clickable);
192 gboolean pspp_sheet_view_column_get_clickable (PsppSheetViewColumn *tree_column);
193 void pspp_sheet_view_column_set_widget (PsppSheetViewColumn *tree_column,
194 GtkWidget *widget);
195 GtkWidget *pspp_sheet_view_column_get_widget (PsppSheetViewColumn *tree_column);
196 void pspp_sheet_view_column_set_alignment (PsppSheetViewColumn *tree_column,
197 gfloat xalign);
198 gfloat pspp_sheet_view_column_get_alignment (PsppSheetViewColumn *tree_column);
199 void pspp_sheet_view_column_set_reorderable (PsppSheetViewColumn *tree_column,
200 gboolean reorderable);
201 gboolean pspp_sheet_view_column_get_reorderable (PsppSheetViewColumn *tree_column);
202
203 void pspp_sheet_view_column_set_quick_edit (PsppSheetViewColumn *tree_column,
204 gboolean quick_edit);
205 gboolean pspp_sheet_view_column_get_quick_edit (PsppSheetViewColumn *tree_column);
206 void pspp_sheet_view_column_set_selected (PsppSheetViewColumn *tree_column,
207 gboolean selected);
208 gboolean pspp_sheet_view_column_get_selected (PsppSheetViewColumn *tree_column);
209
210 void pspp_sheet_view_column_set_selectable (PsppSheetViewColumn *tree_column,
211 gboolean selectable);
212 gboolean pspp_sheet_view_column_get_selectable (PsppSheetViewColumn *tree_column);
213 void pspp_sheet_view_column_set_row_head (PsppSheetViewColumn *tree_column,
214 gboolean row_head);
215 gboolean pspp_sheet_view_column_get_row_head (PsppSheetViewColumn *tree_column);
216
217
218
219 /* You probably only want to use pspp_sheet_view_column_set_sort_column_id. The
220 * other sorting functions exist primarily to let others do their own custom sorting.
221 */
222 void pspp_sheet_view_column_set_sort_column_id (PsppSheetViewColumn *tree_column,
223 gint sort_column_id);
224 gint pspp_sheet_view_column_get_sort_column_id (PsppSheetViewColumn *tree_column);
225 void pspp_sheet_view_column_set_sort_indicator (PsppSheetViewColumn *tree_column,
226 gboolean setting);
227 gboolean pspp_sheet_view_column_get_sort_indicator (PsppSheetViewColumn *tree_column);
228 void pspp_sheet_view_column_set_sort_order (PsppSheetViewColumn *tree_column,
229 GtkSortType order);
230 GtkSortType pspp_sheet_view_column_get_sort_order (PsppSheetViewColumn *tree_column);
231
232
233 /* These functions are meant primarily for interaction between the PsppSheetView and the column.
234 */
235 void pspp_sheet_view_column_cell_set_cell_data (PsppSheetViewColumn *tree_column,
236 GtkTreeModel *tree_model,
237 GtkTreeIter *iter);
238 void pspp_sheet_view_column_cell_get_size (PsppSheetViewColumn *tree_column,
239 const GdkRectangle *cell_area,
240 gint *x_offset,
241 gint *y_offset,
242 gint *width,
243 gint *height);
244 gboolean pspp_sheet_view_column_cell_is_visible (PsppSheetViewColumn *tree_column);
245 void pspp_sheet_view_column_focus_cell (PsppSheetViewColumn *tree_column,
246 GtkCellRenderer *cell);
247 gboolean pspp_sheet_view_column_cell_get_position (PsppSheetViewColumn *tree_column,
248 GtkCellRenderer *cell_renderer,
249 gint *start_pos,
250 gint *width);
251 void pspp_sheet_view_column_queue_resize (PsppSheetViewColumn *tree_column);
252 GtkWidget *pspp_sheet_view_column_get_tree_view (PsppSheetViewColumn *tree_column);
253
254 void pspp_sheet_view_column_size_request (PsppSheetViewColumn *tree_column,
255 GtkRequisition *requisition);
256
257 void pspp_sheet_view_column_size_allocate (PsppSheetViewColumn *tree_column,
258 GtkAllocation *allocation);
259 gboolean pspp_sheet_view_column_can_focus (PsppSheetViewColumn *tree_column);
260 void pspp_sheet_view_column_set_need_button (PsppSheetViewColumn *tree_column,
261 gboolean need_button);
262
263 G_END_DECLS
264
265
266 #endif /* __PSPP_SHEET_VIEW_COLUMN_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeview.c
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #include <config.h>
36
37 #include "ui/gui/pspp-sheet-private.h"
38
39 #include <gtk/gtk.h>
40 #include <gdk/gdk.h>
41 #include <gdk/gdkkeysyms.h>
42 #include <string.h>
43
44 #include "ui/gui/psppire-marshal.h"
45 #include "ui/gui/pspp-sheet-selection.h"
46
47 #define P_(STRING) STRING
48 #define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
49 #define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
50
51 /* Many keyboard shortcuts for Mac are the same as for X
52 * except they use Command key instead of Control (e.g. Cut,
53 * Copy, Paste). This symbol is for those simple cases. */
54 #ifndef GDK_WINDOWING_QUARTZ
55 #define GTK_DEFAULT_ACCEL_MOD_MASK GDK_CONTROL_MASK
56 #else
57 #define GTK_DEFAULT_ACCEL_MOD_MASK GDK_META_MASK
58 #endif
59
60 #define PSPP_SHEET_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
61 #define PSPP_SHEET_VIEW_PRIORITY_SCROLL_SYNC (PSPP_SHEET_VIEW_PRIORITY_VALIDATE + 2)
62 #define PSPP_SHEET_VIEW_TIME_MS_PER_IDLE 30
63 #define SCROLL_EDGE_SIZE 15
64 #define EXPANDER_EXTRA_PADDING 4
65 #define PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT 5000
66
67 /* The "background" areas of all rows/cells add up to cover the entire tree.
68 * The background includes all inter-row and inter-cell spacing.
69 * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
70 * i.e. just the cells, no spacing.
71 */
72
73 #define BACKGROUND_HEIGHT(tree_view) (tree_view->priv->fixed_height)
74 #define CELL_HEIGHT(tree_view, separator) ((BACKGROUND_HEIGHT (tree_view)) - (separator))
75
76 /* Translate from bin_window coordinates to rbtree (tree coordinates) and
77 * vice versa.
78 */
79 #define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) + tree_view->priv->dy)
80 #define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) - tree_view->priv->dy)
81
82 /* This is in bin_window coordinates */
83 #define BACKGROUND_FIRST_PIXEL(tree_view,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, pspp_sheet_view_node_find_offset (tree_view, (node))))
84 #define CELL_FIRST_PIXEL(tree_view,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,node) + separator/2)
85
86 #define ROW_HEIGHT(tree_view) \
87 ((tree_view->priv->fixed_height > 0) ? (tree_view->priv->fixed_height) : (tree_view)->priv->expander_size)
88
89
90 typedef struct _PsppSheetViewChild PsppSheetViewChild;
91 struct _PsppSheetViewChild
92 {
93 GtkWidget *widget;
94 gint x;
95 gint y;
96 gint width;
97 gint height;
98 };
99
100
101 typedef struct _TreeViewDragInfo TreeViewDragInfo;
102 struct _TreeViewDragInfo
103 {
104 GdkModifierType start_button_mask;
105 GtkTargetList *_unused_source_target_list;
106 GdkDragAction source_actions;
107
108 GtkTargetList *_unused_dest_target_list;
109
110 guint source_set : 1;
111 guint dest_set : 1;
112 };
113
114
115 /* Signals */
116 enum
117 {
118 ROW_ACTIVATED,
119 COLUMNS_CHANGED,
120 CURSOR_CHANGED,
121 MOVE_CURSOR,
122 SELECT_ALL,
123 UNSELECT_ALL,
124 SELECT_CURSOR_ROW,
125 TOGGLE_CURSOR_ROW,
126 START_INTERACTIVE_SEARCH,
127 LAST_SIGNAL
128 };
129
130 /* Properties */
131 enum {
132 PROP_0,
133 PROP_MODEL,
134 PROP_HADJUSTMENT,
135 PROP_VADJUSTMENT,
136 PROP_HEADERS_VISIBLE,
137 PROP_HEADERS_CLICKABLE,
138 PROP_REORDERABLE,
139 PROP_RULES_HINT,
140 PROP_ENABLE_SEARCH,
141 PROP_SEARCH_COLUMN,
142 PROP_HOVER_SELECTION,
143 PROP_RUBBER_BANDING,
144 PROP_ENABLE_GRID_LINES,
145 PROP_TOOLTIP_COLUMN,
146 PROP_SPECIAL_CELLS,
147 PROP_FIXED_HEIGHT,
148 PROP_FIXED_HEIGHT_SET
149 };
150
151 /* object signals */
152 static void pspp_sheet_view_finalize (GObject *object);
153 static void pspp_sheet_view_set_property (GObject *object,
154 guint prop_id,
155 const GValue *value,
156 GParamSpec *pspec);
157 static void pspp_sheet_view_get_property (GObject *object,
158 guint prop_id,
159 GValue *value,
160 GParamSpec *pspec);
161
162 /* gtkobject signals */
163 static void pspp_sheet_view_destroy (GtkObject *object);
164
165 /* gtkwidget signals */
166 static void pspp_sheet_view_realize (GtkWidget *widget);
167 static void pspp_sheet_view_unrealize (GtkWidget *widget);
168 static void pspp_sheet_view_map (GtkWidget *widget);
169 static void pspp_sheet_view_size_request (GtkWidget *widget,
170 GtkRequisition *requisition);
171 static void pspp_sheet_view_size_allocate (GtkWidget *widget,
172 GtkAllocation *allocation);
173 static gboolean pspp_sheet_view_expose (GtkWidget *widget,
174 GdkEventExpose *event);
175 static gboolean pspp_sheet_view_key_press (GtkWidget *widget,
176 GdkEventKey *event);
177 static gboolean pspp_sheet_view_key_release (GtkWidget *widget,
178 GdkEventKey *event);
179 static gboolean pspp_sheet_view_motion (GtkWidget *widget,
180 GdkEventMotion *event);
181 static gboolean pspp_sheet_view_enter_notify (GtkWidget *widget,
182 GdkEventCrossing *event);
183 static gboolean pspp_sheet_view_leave_notify (GtkWidget *widget,
184 GdkEventCrossing *event);
185 static gboolean pspp_sheet_view_button_press (GtkWidget *widget,
186 GdkEventButton *event);
187 static gboolean pspp_sheet_view_button_release (GtkWidget *widget,
188 GdkEventButton *event);
189 static gboolean pspp_sheet_view_grab_broken (GtkWidget *widget,
190 GdkEventGrabBroken *event);
191
192 static void pspp_sheet_view_set_focus_child (GtkContainer *container,
193 GtkWidget *child);
194 static gint pspp_sheet_view_focus_out (GtkWidget *widget,
195 GdkEventFocus *event);
196 static gint pspp_sheet_view_focus (GtkWidget *widget,
197 GtkDirectionType direction);
198 static void pspp_sheet_view_grab_focus (GtkWidget *widget);
199 static void pspp_sheet_view_style_set (GtkWidget *widget,
200 GtkStyle *previous_style);
201 static void pspp_sheet_view_grab_notify (GtkWidget *widget,
202 gboolean was_grabbed);
203 static void pspp_sheet_view_state_changed (GtkWidget *widget,
204 GtkStateType previous_state);
205
206 /* container signals */
207 static void pspp_sheet_view_remove (GtkContainer *container,
208 GtkWidget *widget);
209 static void pspp_sheet_view_forall (GtkContainer *container,
210 gboolean include_internals,
211 GtkCallback callback,
212 gpointer callback_data);
213
214 /* Source side drag signals */
215 static void pspp_sheet_view_drag_begin (GtkWidget *widget,
216 GdkDragContext *context);
217 static void pspp_sheet_view_drag_end (GtkWidget *widget,
218 GdkDragContext *context);
219 static void pspp_sheet_view_drag_data_get (GtkWidget *widget,
220 GdkDragContext *context,
221 GtkSelectionData *selection_data,
222 guint info,
223 guint time);
224 static void pspp_sheet_view_drag_data_delete (GtkWidget *widget,
225 GdkDragContext *context);
226
227 /* Target side drag signals */
228 static void pspp_sheet_view_drag_leave (GtkWidget *widget,
229 GdkDragContext *context,
230 guint time);
231 static gboolean pspp_sheet_view_drag_motion (GtkWidget *widget,
232 GdkDragContext *context,
233 gint x,
234 gint y,
235 guint time);
236 static gboolean pspp_sheet_view_drag_drop (GtkWidget *widget,
237 GdkDragContext *context,
238 gint x,
239 gint y,
240 guint time);
241 static void pspp_sheet_view_drag_data_received (GtkWidget *widget,
242 GdkDragContext *context,
243 gint x,
244 gint y,
245 GtkSelectionData *selection_data,
246 guint info,
247 guint time);
248
249 /* tree_model signals */
250 static void pspp_sheet_view_set_adjustments (PsppSheetView *tree_view,
251 GtkAdjustment *hadj,
252 GtkAdjustment *vadj);
253 static gboolean pspp_sheet_view_real_move_cursor (PsppSheetView *tree_view,
254 GtkMovementStep step,
255 gint count);
256 static gboolean pspp_sheet_view_real_select_all (PsppSheetView *tree_view);
257 static gboolean pspp_sheet_view_real_unselect_all (PsppSheetView *tree_view);
258 static gboolean pspp_sheet_view_real_select_cursor_row (PsppSheetView *tree_view,
259 gboolean start_editing);
260 static gboolean pspp_sheet_view_real_toggle_cursor_row (PsppSheetView *tree_view);
261 static void pspp_sheet_view_row_changed (GtkTreeModel *model,
262 GtkTreePath *path,
263 GtkTreeIter *iter,
264 gpointer data);
265 static void pspp_sheet_view_row_inserted (GtkTreeModel *model,
266 GtkTreePath *path,
267 GtkTreeIter *iter,
268 gpointer data);
269 static void pspp_sheet_view_row_deleted (GtkTreeModel *model,
270 GtkTreePath *path,
271 gpointer data);
272 static void pspp_sheet_view_rows_reordered (GtkTreeModel *model,
273 GtkTreePath *parent,
274 GtkTreeIter *iter,
275 gint *new_order,
276 gpointer data);
277
278 /* Incremental reflow */
279 static gint validate_row (PsppSheetView *tree_view,
280 int node,
281 GtkTreeIter *iter,
282 GtkTreePath *path);
283 static void validate_visible_area (PsppSheetView *tree_view);
284 static gboolean validate_rows_handler (PsppSheetView *tree_view);
285 static gboolean presize_handler_callback (gpointer data);
286 static void install_presize_handler (PsppSheetView *tree_view);
287 static void install_scroll_sync_handler (PsppSheetView *tree_view);
288 static void pspp_sheet_view_set_top_row (PsppSheetView *tree_view,
289 GtkTreePath *path,
290 gint offset);
291 static void pspp_sheet_view_dy_to_top_row (PsppSheetView *tree_view);
292 static void pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view);
293 static void invalidate_empty_focus (PsppSheetView *tree_view);
294
295 /* Internal functions */
296 static void pspp_sheet_view_add_move_binding (GtkBindingSet *binding_set,
297 guint keyval,
298 guint modmask,
299 gboolean add_shifted_binding,
300 GtkMovementStep step,
301 gint count);
302 static void pspp_sheet_view_queue_draw_path (PsppSheetView *tree_view,
303 GtkTreePath *path,
304 const GdkRectangle *clip_rect);
305 static gint pspp_sheet_view_new_column_width (PsppSheetView *tree_view,
306 gint i,
307 gint *x);
308 static void pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment,
309 PsppSheetView *tree_view);
310 static void pspp_sheet_view_clamp_node_visible (PsppSheetView *tree_view,
311 int node);
312 static void pspp_sheet_view_clamp_column_visible (PsppSheetView *tree_view,
313 PsppSheetViewColumn *column,
314 gboolean focus_to_cell);
315 static gboolean pspp_sheet_view_maybe_begin_dragging_row (PsppSheetView *tree_view,
316 GdkEventMotion *event);
317 static void pspp_sheet_view_focus_to_cursor (PsppSheetView *tree_view);
318 static void pspp_sheet_view_move_cursor_up_down (PsppSheetView *tree_view,
319 gint count);
320 static void pspp_sheet_view_move_cursor_page_up_down (PsppSheetView *tree_view,
321 gint count);
322 static void pspp_sheet_view_move_cursor_left_right (PsppSheetView *tree_view,
323 gint count);
324 static void pspp_sheet_view_move_cursor_start_end (PsppSheetView *tree_view,
325 gint count);
326 static void pspp_sheet_view_real_set_cursor (PsppSheetView *tree_view,
327 GtkTreePath *path,
328 gboolean clear_and_select,
329 gboolean clamp_node);
330 static gboolean pspp_sheet_view_has_special_cell (PsppSheetView *tree_view);
331 static void pspp_sheet_view_stop_rubber_band (PsppSheetView *tree_view);
332 static void update_prelight (PsppSheetView *tree_view,
333 int x,
334 int y);
335 static void initialize_fixed_height_mode (PsppSheetView *tree_view);
336
337 /* interactive search */
338 static void pspp_sheet_view_ensure_interactive_directory (PsppSheetView *tree_view);
339 static void pspp_sheet_view_search_dialog_hide (GtkWidget *search_dialog,
340 PsppSheetView *tree_view);
341 static void pspp_sheet_view_search_position_func (PsppSheetView *tree_view,
342 GtkWidget *search_dialog,
343 gpointer user_data);
344 static void pspp_sheet_view_search_disable_popdown (GtkEntry *entry,
345 GtkMenu *menu,
346 gpointer data);
347 static void pspp_sheet_view_search_preedit_changed (GtkIMContext *im_context,
348 PsppSheetView *tree_view);
349 static void pspp_sheet_view_search_activate (GtkEntry *entry,
350 PsppSheetView *tree_view);
351 static gboolean pspp_sheet_view_real_search_enable_popdown(gpointer data);
352 static void pspp_sheet_view_search_enable_popdown (GtkWidget *widget,
353 gpointer data);
354 static gboolean pspp_sheet_view_search_delete_event (GtkWidget *widget,
355 GdkEventAny *event,
356 PsppSheetView *tree_view);
357 static gboolean pspp_sheet_view_search_button_press_event (GtkWidget *widget,
358 GdkEventButton *event,
359 PsppSheetView *tree_view);
360 static gboolean pspp_sheet_view_search_scroll_event (GtkWidget *entry,
361 GdkEventScroll *event,
362 PsppSheetView *tree_view);
363 static gboolean pspp_sheet_view_search_key_press_event (GtkWidget *entry,
364 GdkEventKey *event,
365 PsppSheetView *tree_view);
366 static gboolean pspp_sheet_view_search_move (GtkWidget *window,
367 PsppSheetView *tree_view,
368 gboolean up);
369 static gboolean pspp_sheet_view_search_equal_func (GtkTreeModel *model,
370 gint column,
371 const gchar *key,
372 GtkTreeIter *iter,
373 gpointer search_data);
374 static gboolean pspp_sheet_view_search_iter (GtkTreeModel *model,
375 PsppSheetSelection *selection,
376 GtkTreeIter *iter,
377 const gchar *text,
378 gint *count,
379 gint n);
380 static void pspp_sheet_view_search_init (GtkWidget *entry,
381 PsppSheetView *tree_view);
382 static void pspp_sheet_view_put (PsppSheetView *tree_view,
383 GtkWidget *child_widget,
384 gint x,
385 gint y,
386 gint width,
387 gint height);
388 static gboolean pspp_sheet_view_start_editing (PsppSheetView *tree_view,
389 GtkTreePath *cursor_path);
390 static gboolean pspp_sheet_view_editable_button_press_event (GtkWidget *,
391 GdkEventButton *,
392 PsppSheetView *);
393 static void pspp_sheet_view_editable_clicked (GtkButton *, PsppSheetView *);
394 static void pspp_sheet_view_real_start_editing (PsppSheetView *tree_view,
395 PsppSheetViewColumn *column,
396 GtkTreePath *path,
397 GtkCellEditable *cell_editable,
398 GdkRectangle *cell_area,
399 GdkEvent *event,
400 guint flags);
401 static gboolean pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view,
402 gboolean keybinding);
403 static gboolean pspp_sheet_view_start_interactive_search (PsppSheetView *tree_view);
404 static PsppSheetViewColumn *pspp_sheet_view_get_drop_column (PsppSheetView *tree_view,
405 PsppSheetViewColumn *column,
406 gint drop_position);
407 static void
408 pspp_sheet_view_adjust_cell_area (PsppSheetView *tree_view,
409 PsppSheetViewColumn *column,
410 const GdkRectangle *background_area,
411 gboolean subtract_focus_rect,
412 GdkRectangle *cell_area);
413 static gint pspp_sheet_view_find_offset (PsppSheetView *tree_view,
414 gint height,
415 int *new_node);
416
417 /* GtkBuildable */
418 static void pspp_sheet_view_buildable_add_child (GtkBuildable *tree_view,
419 GtkBuilder *builder,
420 GObject *child,
421 const gchar *type);
422 static void pspp_sheet_view_buildable_init (GtkBuildableIface *iface);
423
424
425 static gboolean scroll_row_timeout (gpointer data);
426 static void add_scroll_timeout (PsppSheetView *tree_view);
427 static void remove_scroll_timeout (PsppSheetView *tree_view);
428
429 static guint tree_view_signals [LAST_SIGNAL] = { 0 };
430
431
432
433 /* GType Methods
434 */
435
436 G_DEFINE_TYPE_WITH_CODE (PsppSheetView, pspp_sheet_view, GTK_TYPE_CONTAINER,
437 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
438 pspp_sheet_view_buildable_init))
439
440 static void
441 pspp_sheet_view_class_init (PsppSheetViewClass *class)
442 {
443 GObjectClass *o_class;
444 GtkObjectClass *object_class;
445 GtkWidgetClass *widget_class;
446 GtkContainerClass *container_class;
447 GtkBindingSet *binding_set;
448
449 binding_set = gtk_binding_set_by_class (class);
450
451 o_class = (GObjectClass *) class;
452 object_class = (GtkObjectClass *) class;
453 widget_class = (GtkWidgetClass *) class;
454 container_class = (GtkContainerClass *) class;
455
456 /* GObject signals */
457 o_class->set_property = pspp_sheet_view_set_property;
458 o_class->get_property = pspp_sheet_view_get_property;
459 o_class->finalize = pspp_sheet_view_finalize;
460
461 /* GtkObject signals */
462 object_class->destroy = pspp_sheet_view_destroy;
463
464 /* GtkWidget signals */
465 widget_class->map = pspp_sheet_view_map;
466 widget_class->realize = pspp_sheet_view_realize;
467 widget_class->unrealize = pspp_sheet_view_unrealize;
468 widget_class->size_request = pspp_sheet_view_size_request;
469 widget_class->size_allocate = pspp_sheet_view_size_allocate;
470 widget_class->button_press_event = pspp_sheet_view_button_press;
471 widget_class->button_release_event = pspp_sheet_view_button_release;
472 widget_class->grab_broken_event = pspp_sheet_view_grab_broken;
473 /*widget_class->configure_event = pspp_sheet_view_configure;*/
474 widget_class->motion_notify_event = pspp_sheet_view_motion;
475 widget_class->expose_event = pspp_sheet_view_expose;
476 widget_class->key_press_event = pspp_sheet_view_key_press;
477 widget_class->key_release_event = pspp_sheet_view_key_release;
478 widget_class->enter_notify_event = pspp_sheet_view_enter_notify;
479 widget_class->leave_notify_event = pspp_sheet_view_leave_notify;
480 widget_class->focus_out_event = pspp_sheet_view_focus_out;
481 widget_class->drag_begin = pspp_sheet_view_drag_begin;
482 widget_class->drag_end = pspp_sheet_view_drag_end;
483 widget_class->drag_data_get = pspp_sheet_view_drag_data_get;
484 widget_class->drag_data_delete = pspp_sheet_view_drag_data_delete;
485 widget_class->drag_leave = pspp_sheet_view_drag_leave;
486 widget_class->drag_motion = pspp_sheet_view_drag_motion;
487 widget_class->drag_drop = pspp_sheet_view_drag_drop;
488 widget_class->drag_data_received = pspp_sheet_view_drag_data_received;
489 widget_class->focus = pspp_sheet_view_focus;
490 widget_class->grab_focus = pspp_sheet_view_grab_focus;
491 widget_class->style_set = pspp_sheet_view_style_set;
492 widget_class->grab_notify = pspp_sheet_view_grab_notify;
493 widget_class->state_changed = pspp_sheet_view_state_changed;
494
495 /* GtkContainer signals */
496 container_class->remove = pspp_sheet_view_remove;
497 container_class->forall = pspp_sheet_view_forall;
498 container_class->set_focus_child = pspp_sheet_view_set_focus_child;
499
500 class->set_scroll_adjustments = pspp_sheet_view_set_adjustments;
501 class->move_cursor = pspp_sheet_view_real_move_cursor;
502 class->select_all = pspp_sheet_view_real_select_all;
503 class->unselect_all = pspp_sheet_view_real_unselect_all;
504 class->select_cursor_row = pspp_sheet_view_real_select_cursor_row;
505 class->toggle_cursor_row = pspp_sheet_view_real_toggle_cursor_row;
506 class->start_interactive_search = pspp_sheet_view_start_interactive_search;
507
508 /* Properties */
509
510 g_object_class_install_property (o_class,
511 PROP_MODEL,
512 g_param_spec_object ("model",
513 P_("TreeView Model"),
514 P_("The model for the tree view"),
515 GTK_TYPE_TREE_MODEL,
516 GTK_PARAM_READWRITE));
517
518 g_object_class_install_property (o_class,
519 PROP_HADJUSTMENT,
520 g_param_spec_object ("hadjustment",
521 P_("Horizontal Adjustment"),
522 P_("Horizontal Adjustment for the widget"),
523 GTK_TYPE_ADJUSTMENT,
524 GTK_PARAM_READWRITE));
525
526 g_object_class_install_property (o_class,
527 PROP_VADJUSTMENT,
528 g_param_spec_object ("vadjustment",
529 P_("Vertical Adjustment"),
530 P_("Vertical Adjustment for the widget"),
531 GTK_TYPE_ADJUSTMENT,
532 GTK_PARAM_READWRITE));
533
534 g_object_class_install_property (o_class,
535 PROP_HEADERS_VISIBLE,
536 g_param_spec_boolean ("headers-visible",
537 P_("Headers Visible"),
538 P_("Show the column header buttons"),
539 TRUE,
540 GTK_PARAM_READWRITE));
541
542 g_object_class_install_property (o_class,
543 PROP_HEADERS_CLICKABLE,
544 g_param_spec_boolean ("headers-clickable",
545 P_("Headers Clickable"),
546 P_("Column headers respond to click events"),
547 TRUE,
548 GTK_PARAM_READWRITE));
549
550 g_object_class_install_property (o_class,
551 PROP_REORDERABLE,
552 g_param_spec_boolean ("reorderable",
553 P_("Reorderable"),
554 P_("View is reorderable"),
555 FALSE,
556 GTK_PARAM_READWRITE));
557
558 g_object_class_install_property (o_class,
559 PROP_RULES_HINT,
560 g_param_spec_boolean ("rules-hint",
561 P_("Rules Hint"),
562 P_("Set a hint to the theme engine to draw rows in alternating colors"),
563 FALSE,
564 GTK_PARAM_READWRITE));
565
566 g_object_class_install_property (o_class,
567 PROP_ENABLE_SEARCH,
568 g_param_spec_boolean ("enable-search",
569 P_("Enable Search"),
570 P_("View allows user to search through columns interactively"),
571 TRUE,
572 GTK_PARAM_READWRITE));
573
574 g_object_class_install_property (o_class,
575 PROP_SEARCH_COLUMN,
576 g_param_spec_int ("search-column",
577 P_("Search Column"),
578 P_("Model column to search through during interactive search"),
579 -1,
580 G_MAXINT,
581 -1,
582 GTK_PARAM_READWRITE));
583
584 /**
585 * PsppSheetView:hover-selection:
586 *
587 * Enables of disables the hover selection mode of @tree_view.
588 * Hover selection makes the selected row follow the pointer.
589 * Currently, this works only for the selection modes
590 * %PSPP_SHEET_SELECTION_SINGLE and %PSPP_SHEET_SELECTION_BROWSE.
591 *
592 * This mode is primarily intended for treeviews in popups, e.g.
593 * in #GtkComboBox or #GtkEntryCompletion.
594 *
595 * Since: 2.6
596 */
597 g_object_class_install_property (o_class,
598 PROP_HOVER_SELECTION,
599 g_param_spec_boolean ("hover-selection",
600 P_("Hover Selection"),
601 P_("Whether the selection should follow the pointer"),
602 FALSE,
603 GTK_PARAM_READWRITE));
604
605 g_object_class_install_property (o_class,
606 PROP_RUBBER_BANDING,
607 g_param_spec_boolean ("rubber-banding",
608 P_("Rubber Banding"),
609 P_("Whether to enable selection of multiple items by dragging the mouse pointer"),
610 FALSE,
611 GTK_PARAM_READWRITE));
612
613 g_object_class_install_property (o_class,
614 PROP_ENABLE_GRID_LINES,
615 g_param_spec_enum ("enable-grid-lines",
616 P_("Enable Grid Lines"),
617 P_("Whether grid lines should be drawn in the tree view"),
618 PSPP_TYPE_SHEET_VIEW_GRID_LINES,
619 PSPP_SHEET_VIEW_GRID_LINES_NONE,
620 GTK_PARAM_READWRITE));
621
622 g_object_class_install_property (o_class,
623 PROP_TOOLTIP_COLUMN,
624 g_param_spec_int ("tooltip-column",
625 P_("Tooltip Column"),
626 P_("The column in the model containing the tooltip texts for the rows"),
627 -1,
628 G_MAXINT,
629 -1,
630 GTK_PARAM_READWRITE));
631
632 g_object_class_install_property (o_class,
633 PROP_SPECIAL_CELLS,
634 g_param_spec_enum ("special-cells",
635 P_("Special Cells"),
636 P_("Whether rows have special cells."),
637 PSPP_TYPE_SHEET_VIEW_SPECIAL_CELLS,
638 PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT,
639 GTK_PARAM_READWRITE));
640
641 g_object_class_install_property (o_class,
642 PROP_FIXED_HEIGHT,
643 g_param_spec_int ("fixed-height",
644 P_("Fixed Height"),
645 P_("Height of a single row. Normally the height of a row is determined automatically. Writing this property sets fixed-height-set to true, preventing this property's value from changing."),
646 -1,
647 G_MAXINT,
648 -1,
649 GTK_PARAM_READWRITE));
650
651 g_object_class_install_property (o_class,
652 PROP_FIXED_HEIGHT_SET,
653 g_param_spec_boolean ("fixed-height-set",
654 P_("Fixed Height Set"),
655 P_("Whether fixed-height was set externally."),
656 FALSE,
657 GTK_PARAM_READWRITE));
658
659 /* Style properties */
660 #define _TREE_VIEW_EXPANDER_SIZE 12
661 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
662 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
663
664 gtk_widget_class_install_style_property (widget_class,
665 g_param_spec_int ("expander-size",
666 P_("Expander Size"),
667 P_("Size of the expander arrow"),
668 0,
669 G_MAXINT,
670 _TREE_VIEW_EXPANDER_SIZE,
671 GTK_PARAM_READABLE));
672
673 gtk_widget_class_install_style_property (widget_class,
674 g_param_spec_int ("vertical-separator",
675 P_("Vertical Separator Width"),
676 P_("Vertical space between cells. Must be an even number"),
677 0,
678 G_MAXINT,
679 _TREE_VIEW_VERTICAL_SEPARATOR,
680 GTK_PARAM_READABLE));
681
682 gtk_widget_class_install_style_property (widget_class,
683 g_param_spec_int ("horizontal-separator",
684 P_("Horizontal Separator Width"),
685 P_("Horizontal space between cells. Must be an even number"),
686 0,
687 G_MAXINT,
688 _TREE_VIEW_HORIZONTAL_SEPARATOR,
689 GTK_PARAM_READABLE));
690
691 gtk_widget_class_install_style_property (widget_class,
692 g_param_spec_boolean ("allow-rules",
693 P_("Allow Rules"),
694 P_("Allow drawing of alternating color rows"),
695 TRUE,
696 GTK_PARAM_READABLE));
697
698 gtk_widget_class_install_style_property (widget_class,
699 g_param_spec_boxed ("even-row-color",
700 P_("Even Row Color"),
701 P_("Color to use for even rows"),
702 GDK_TYPE_COLOR,
703 GTK_PARAM_READABLE));
704
705 gtk_widget_class_install_style_property (widget_class,
706 g_param_spec_boxed ("odd-row-color",
707 P_("Odd Row Color"),
708 P_("Color to use for odd rows"),
709 GDK_TYPE_COLOR,
710 GTK_PARAM_READABLE));
711
712 gtk_widget_class_install_style_property (widget_class,
713 g_param_spec_boolean ("row-ending-details",
714 P_("Row Ending details"),
715 P_("Enable extended row background theming"),
716 FALSE,
717 GTK_PARAM_READABLE));
718
719 gtk_widget_class_install_style_property (widget_class,
720 g_param_spec_int ("grid-line-width",
721 P_("Grid line width"),
722 P_("Width, in pixels, of the tree view grid lines"),
723 0, G_MAXINT, 1,
724 GTK_PARAM_READABLE));
725
726 gtk_widget_class_install_style_property (widget_class,
727 g_param_spec_int ("tree-line-width",
728 P_("Tree line width"),
729 P_("Width, in pixels, of the tree view lines"),
730 0, G_MAXINT, 1,
731 GTK_PARAM_READABLE));
732
733 gtk_widget_class_install_style_property (widget_class,
734 g_param_spec_string ("tree-line-pattern",
735 P_("Tree line pattern"),
736 P_("Dash pattern used to draw the tree view lines"),
737 "\1\1",
738 GTK_PARAM_READABLE));
739
740 /* Signals */
741 /**
742 * PsppSheetView::set-scroll-adjustments
743 * @horizontal: the horizontal #GtkAdjustment
744 * @vertical: the vertical #GtkAdjustment
745 *
746 * Set the scroll adjustments for the tree view. Usually scrolled containers
747 * like #GtkScrolledWindow will emit this signal to connect two instances
748 * of #GtkScrollbar to the scroll directions of the #PsppSheetView.
749 */
750 widget_class->set_scroll_adjustments_signal =
751 g_signal_new ("set-scroll-adjustments",
752 G_TYPE_FROM_CLASS (o_class),
753 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
754 G_STRUCT_OFFSET (PsppSheetViewClass, set_scroll_adjustments),
755 NULL, NULL,
756 psppire_marshal_VOID__OBJECT_OBJECT,
757 G_TYPE_NONE, 2,
758 GTK_TYPE_ADJUSTMENT,
759 GTK_TYPE_ADJUSTMENT);
760
761 /**
762 * PsppSheetView::row-activated:
763 * @tree_view: the object on which the signal is emitted
764 * @path: the #GtkTreePath for the activated row
765 * @column: the #PsppSheetViewColumn in which the activation occurred
766 *
767 * The "row-activated" signal is emitted when the method
768 * pspp_sheet_view_row_activated() is called or the user double clicks
769 * a treeview row. It is also emitted when a non-editable row is
770 * selected and one of the keys: Space, Shift+Space, Return or
771 * Enter is pressed.
772 *
773 * For selection handling refer to the <link linkend="TreeWidget">tree
774 * widget conceptual overview</link> as well as #PsppSheetSelection.
775 */
776 tree_view_signals[ROW_ACTIVATED] =
777 g_signal_new ("row-activated",
778 G_TYPE_FROM_CLASS (o_class),
779 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
780 G_STRUCT_OFFSET (PsppSheetViewClass, row_activated),
781 NULL, NULL,
782 psppire_marshal_VOID__BOXED_OBJECT,
783 G_TYPE_NONE, 2,
784 GTK_TYPE_TREE_PATH,
785 PSPP_TYPE_SHEET_VIEW_COLUMN);
786
787 /**
788 * PsppSheetView::columns-changed:
789 * @tree_view: the object on which the signal is emitted
790 *
791 * The number of columns of the treeview has changed.
792 */
793 tree_view_signals[COLUMNS_CHANGED] =
794 g_signal_new ("columns-changed",
795 G_TYPE_FROM_CLASS (o_class),
796 G_SIGNAL_RUN_LAST,
797 G_STRUCT_OFFSET (PsppSheetViewClass, columns_changed),
798 NULL, NULL,
799 g_cclosure_marshal_VOID__VOID,
800 G_TYPE_NONE, 0);
801
802 /**
803 * PsppSheetView::cursor-changed:
804 * @tree_view: the object on which the signal is emitted
805 *
806 * The position of the cursor (focused cell) has changed.
807 */
808 tree_view_signals[CURSOR_CHANGED] =
809 g_signal_new ("cursor-changed",
810 G_TYPE_FROM_CLASS (o_class),
811 G_SIGNAL_RUN_LAST,
812 G_STRUCT_OFFSET (PsppSheetViewClass, cursor_changed),
813 NULL, NULL,
814 g_cclosure_marshal_VOID__VOID,
815 G_TYPE_NONE, 0);
816
817 tree_view_signals[MOVE_CURSOR] =
818 g_signal_new ("move-cursor",
819 G_TYPE_FROM_CLASS (object_class),
820 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
821 G_STRUCT_OFFSET (PsppSheetViewClass, move_cursor),
822 NULL, NULL,
823 psppire_marshal_BOOLEAN__ENUM_INT,
824 G_TYPE_BOOLEAN, 2,
825 GTK_TYPE_MOVEMENT_STEP,
826 G_TYPE_INT);
827
828 tree_view_signals[SELECT_ALL] =
829 g_signal_new ("select-all",
830 G_TYPE_FROM_CLASS (object_class),
831 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
832 G_STRUCT_OFFSET (PsppSheetViewClass, select_all),
833 NULL, NULL,
834 psppire_marshal_BOOLEAN__VOID,
835 G_TYPE_BOOLEAN, 0);
836
837 tree_view_signals[UNSELECT_ALL] =
838 g_signal_new ("unselect-all",
839 G_TYPE_FROM_CLASS (object_class),
840 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
841 G_STRUCT_OFFSET (PsppSheetViewClass, unselect_all),
842 NULL, NULL,
843 psppire_marshal_BOOLEAN__VOID,
844 G_TYPE_BOOLEAN, 0);
845
846 tree_view_signals[SELECT_CURSOR_ROW] =
847 g_signal_new ("select-cursor-row",
848 G_TYPE_FROM_CLASS (object_class),
849 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
850 G_STRUCT_OFFSET (PsppSheetViewClass, select_cursor_row),
851 NULL, NULL,
852 psppire_marshal_BOOLEAN__BOOLEAN,
853 G_TYPE_BOOLEAN, 1,
854 G_TYPE_BOOLEAN);
855
856 tree_view_signals[TOGGLE_CURSOR_ROW] =
857 g_signal_new ("toggle-cursor-row",
858 G_TYPE_FROM_CLASS (object_class),
859 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
860 G_STRUCT_OFFSET (PsppSheetViewClass, toggle_cursor_row),
861 NULL, NULL,
862 psppire_marshal_BOOLEAN__VOID,
863 G_TYPE_BOOLEAN, 0);
864
865 tree_view_signals[START_INTERACTIVE_SEARCH] =
866 g_signal_new ("start-interactive-search",
867 G_TYPE_FROM_CLASS (object_class),
868 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
869 G_STRUCT_OFFSET (PsppSheetViewClass, start_interactive_search),
870 NULL, NULL,
871 psppire_marshal_BOOLEAN__VOID,
872 G_TYPE_BOOLEAN, 0);
873
874 /* Key bindings */
875 pspp_sheet_view_add_move_binding (binding_set, GDK_Up, 0, TRUE,
876 GTK_MOVEMENT_DISPLAY_LINES, -1);
877 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Up, 0, TRUE,
878 GTK_MOVEMENT_DISPLAY_LINES, -1);
879
880 pspp_sheet_view_add_move_binding (binding_set, GDK_Down, 0, TRUE,
881 GTK_MOVEMENT_DISPLAY_LINES, 1);
882 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Down, 0, TRUE,
883 GTK_MOVEMENT_DISPLAY_LINES, 1);
884
885 pspp_sheet_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK, FALSE,
886 GTK_MOVEMENT_DISPLAY_LINES, -1);
887
888 pspp_sheet_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK, FALSE,
889 GTK_MOVEMENT_DISPLAY_LINES, 1);
890
891 pspp_sheet_view_add_move_binding (binding_set, GDK_Home, 0, TRUE,
892 GTK_MOVEMENT_BUFFER_ENDS, -1);
893 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Home, 0, TRUE,
894 GTK_MOVEMENT_BUFFER_ENDS, -1);
895
896 pspp_sheet_view_add_move_binding (binding_set, GDK_End, 0, TRUE,
897 GTK_MOVEMENT_BUFFER_ENDS, 1);
898 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_End, 0, TRUE,
899 GTK_MOVEMENT_BUFFER_ENDS, 1);
900
901 pspp_sheet_view_add_move_binding (binding_set, GDK_Page_Up, 0, TRUE,
902 GTK_MOVEMENT_PAGES, -1);
903 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0, TRUE,
904 GTK_MOVEMENT_PAGES, -1);
905
906 pspp_sheet_view_add_move_binding (binding_set, GDK_Page_Down, 0, TRUE,
907 GTK_MOVEMENT_PAGES, 1);
908 pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0, TRUE,
909 GTK_MOVEMENT_PAGES, 1);
910
911
912 gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move-cursor", 2,
913 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
914 G_TYPE_INT, 1);
915
916 gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move-cursor", 2,
917 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
918 G_TYPE_INT, -1);
919
920 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, "move-cursor", 2,
921 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
922 G_TYPE_INT, 1);
923
924 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move-cursor", 2,
925 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
926 G_TYPE_INT, -1);
927
928 gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK,
929 "move-cursor", 2,
930 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
931 G_TYPE_INT, 1);
932
933 gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK,
934 "move-cursor", 2,
935 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
936 G_TYPE_INT, -1);
937
938 gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_CONTROL_MASK,
939 "move-cursor", 2,
940 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
941 G_TYPE_INT, 1);
942
943 gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_CONTROL_MASK,
944 "move-cursor", 2,
945 G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
946 G_TYPE_INT, -1);
947
948 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
949 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
950
951 gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select-all", 0);
952 gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select-all", 0);
953
954 gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
955 gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
956
957 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
958 G_TYPE_BOOLEAN, TRUE);
959 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
960 G_TYPE_BOOLEAN, TRUE);
961
962 gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select-cursor-row", 1,
963 G_TYPE_BOOLEAN, TRUE);
964 gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0, "select-cursor-row", 1,
965 G_TYPE_BOOLEAN, TRUE);
966 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select-cursor-row", 1,
967 G_TYPE_BOOLEAN, TRUE);
968 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select-cursor-row", 1,
969 G_TYPE_BOOLEAN, TRUE);
970 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select-cursor-row", 1,
971 G_TYPE_BOOLEAN, TRUE);
972
973 gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select-cursor-parent", 0);
974 gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
975
976 gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
977
978 gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
979
980 g_type_class_add_private (o_class, sizeof (PsppSheetViewPrivate));
981 }
982
983 static void
984 pspp_sheet_view_buildable_init (GtkBuildableIface *iface)
985 {
986 iface->add_child = pspp_sheet_view_buildable_add_child;
987 }
988
989 static void
990 pspp_sheet_view_init (PsppSheetView *tree_view)
991 {
992 tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, PSPP_TYPE_SHEET_VIEW, PsppSheetViewPrivate);
993
994 gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
995 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
996
997 tree_view->priv->flags = PSPP_SHEET_VIEW_DRAW_KEYFOCUS
998 | PSPP_SHEET_VIEW_HEADERS_VISIBLE;
999
1000 /* We need some padding */
1001 tree_view->priv->selected = range_tower_create ();
1002 tree_view->priv->dy = 0;
1003 tree_view->priv->cursor_offset = 0;
1004 tree_view->priv->n_columns = 0;
1005 tree_view->priv->header_height = 1;
1006 tree_view->priv->x_drag = 0;
1007 tree_view->priv->drag_pos = -1;
1008 tree_view->priv->header_has_focus = FALSE;
1009 tree_view->priv->pressed_button = -1;
1010 tree_view->priv->press_start_x = -1;
1011 tree_view->priv->press_start_y = -1;
1012 tree_view->priv->reorderable = FALSE;
1013 tree_view->priv->presize_handler_timer = 0;
1014 tree_view->priv->scroll_sync_timer = 0;
1015 tree_view->priv->fixed_height = -1;
1016 tree_view->priv->fixed_height_set = FALSE;
1017 pspp_sheet_view_set_adjustments (tree_view, NULL, NULL);
1018 tree_view->priv->selection = _pspp_sheet_selection_new_with_tree_view (tree_view);
1019 tree_view->priv->enable_search = TRUE;
1020 tree_view->priv->search_column = -1;
1021 tree_view->priv->search_position_func = pspp_sheet_view_search_position_func;
1022 tree_view->priv->search_equal_func = pspp_sheet_view_search_equal_func;
1023 tree_view->priv->search_custom_entry_set = FALSE;
1024 tree_view->priv->typeselect_flush_timeout = 0;
1025 tree_view->priv->init_hadjust_value = TRUE;
1026 tree_view->priv->width = 0;
1027
1028 tree_view->priv->hover_selection = FALSE;
1029
1030 tree_view->priv->rubber_banding_enable = FALSE;
1031
1032 tree_view->priv->grid_lines = PSPP_SHEET_VIEW_GRID_LINES_NONE;
1033
1034 tree_view->priv->tooltip_column = -1;
1035
1036 tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT;
1037
1038 tree_view->priv->post_validation_flag = FALSE;
1039
1040 tree_view->priv->last_button_x = -1;
1041 tree_view->priv->last_button_y = -1;
1042
1043 tree_view->priv->event_last_x = -10000;
1044 tree_view->priv->event_last_y = -10000;
1045
1046 tree_view->priv->prelight_node = -1;
1047 tree_view->priv->rubber_band_start_node = -1;
1048 tree_view->priv->rubber_band_end_node = -1;
1049
1050 tree_view->priv->anchor_column = NULL;
1051
1052 tree_view->priv->button_style = NULL;
1053 }
1054
1055
1056
1057 /* GObject Methods
1058 */
1059
1060 static void
1061 pspp_sheet_view_set_property (GObject *object,
1062 guint prop_id,
1063 const GValue *value,
1064 GParamSpec *pspec)
1065 {
1066 PsppSheetView *tree_view;
1067
1068 tree_view = PSPP_SHEET_VIEW (object);
1069
1070 switch (prop_id)
1071 {
1072 case PROP_MODEL:
1073 pspp_sheet_view_set_model (tree_view, g_value_get_object (value));
1074 break;
1075 case PROP_HADJUSTMENT:
1076 pspp_sheet_view_set_hadjustment (tree_view, g_value_get_object (value));
1077 break;
1078 case PROP_VADJUSTMENT:
1079 pspp_sheet_view_set_vadjustment (tree_view, g_value_get_object (value));
1080 break;
1081 case PROP_HEADERS_VISIBLE:
1082 pspp_sheet_view_set_headers_visible (tree_view, g_value_get_boolean (value));
1083 break;
1084 case PROP_HEADERS_CLICKABLE:
1085 pspp_sheet_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
1086 break;
1087 case PROP_REORDERABLE:
1088 pspp_sheet_view_set_reorderable (tree_view, g_value_get_boolean (value));
1089 break;
1090 case PROP_RULES_HINT:
1091 pspp_sheet_view_set_rules_hint (tree_view, g_value_get_boolean (value));
1092 break;
1093 case PROP_ENABLE_SEARCH:
1094 pspp_sheet_view_set_enable_search (tree_view, g_value_get_boolean (value));
1095 break;
1096 case PROP_SEARCH_COLUMN:
1097 pspp_sheet_view_set_search_column (tree_view, g_value_get_int (value));
1098 break;
1099 case PROP_HOVER_SELECTION:
1100 tree_view->priv->hover_selection = g_value_get_boolean (value);
1101 break;
1102 case PROP_RUBBER_BANDING:
1103 tree_view->priv->rubber_banding_enable = g_value_get_boolean (value);
1104 break;
1105 case PROP_ENABLE_GRID_LINES:
1106 pspp_sheet_view_set_grid_lines (tree_view, g_value_get_enum (value));
1107 break;
1108 case PROP_TOOLTIP_COLUMN:
1109 pspp_sheet_view_set_tooltip_column (tree_view, g_value_get_int (value));
1110 break;
1111 case PROP_SPECIAL_CELLS:
1112 pspp_sheet_view_set_special_cells (tree_view, g_value_get_enum (value));
1113 break;
1114 case PROP_FIXED_HEIGHT:
1115 pspp_sheet_view_set_fixed_height (tree_view, g_value_get_int (value));
1116 break;
1117 case PROP_FIXED_HEIGHT_SET:
1118 if (g_value_get_boolean (value))
1119 {
1120 if (!tree_view->priv->fixed_height_set
1121 && tree_view->priv->fixed_height >= 0)
1122 {
1123 tree_view->priv->fixed_height_set = true;
1124 g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
1125 }
1126 }
1127 else
1128 {
1129 if (tree_view->priv->fixed_height_set)
1130 {
1131 tree_view->priv->fixed_height_set = false;
1132 g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
1133 install_presize_handler (tree_view);
1134 }
1135 }
1136 break;
1137 default:
1138 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1139 break;
1140 }
1141 }
1142
1143 static void
1144 pspp_sheet_view_get_property (GObject *object,
1145 guint prop_id,
1146 GValue *value,
1147 GParamSpec *pspec)
1148 {
1149 PsppSheetView *tree_view;
1150
1151 tree_view = PSPP_SHEET_VIEW (object);
1152
1153 switch (prop_id)
1154 {
1155 case PROP_MODEL:
1156 g_value_set_object (value, tree_view->priv->model);
1157 break;
1158 case PROP_HADJUSTMENT:
1159 g_value_set_object (value, tree_view->priv->hadjustment);
1160 break;
1161 case PROP_VADJUSTMENT:
1162 g_value_set_object (value, tree_view->priv->vadjustment);
1163 break;
1164 case PROP_HEADERS_VISIBLE:
1165 g_value_set_boolean (value, pspp_sheet_view_get_headers_visible (tree_view));
1166 break;
1167 case PROP_HEADERS_CLICKABLE:
1168 g_value_set_boolean (value, pspp_sheet_view_get_headers_clickable (tree_view));
1169 break;
1170 case PROP_REORDERABLE:
1171 g_value_set_boolean (value, tree_view->priv->reorderable);
1172 break;
1173 case PROP_RULES_HINT:
1174 g_value_set_boolean (value, tree_view->priv->has_rules);
1175 break;
1176 case PROP_ENABLE_SEARCH:
1177 g_value_set_boolean (value, tree_view->priv->enable_search);
1178 break;
1179 case PROP_SEARCH_COLUMN:
1180 g_value_set_int (value, tree_view->priv->search_column);
1181 break;
1182 case PROP_HOVER_SELECTION:
1183 g_value_set_boolean (value, tree_view->priv->hover_selection);
1184 break;
1185 case PROP_RUBBER_BANDING:
1186 g_value_set_boolean (value, tree_view->priv->rubber_banding_enable);
1187 break;
1188 case PROP_ENABLE_GRID_LINES:
1189 g_value_set_enum (value, tree_view->priv->grid_lines);
1190 break;
1191 case PROP_TOOLTIP_COLUMN:
1192 g_value_set_int (value, tree_view->priv->tooltip_column);
1193 break;
1194 case PROP_SPECIAL_CELLS:
1195 g_value_set_enum (value, tree_view->priv->special_cells);
1196 break;
1197 case PROP_FIXED_HEIGHT:
1198 g_value_set_int (value, pspp_sheet_view_get_fixed_height (tree_view));
1199 break;
1200 case PROP_FIXED_HEIGHT_SET:
1201 g_value_set_boolean (value, tree_view->priv->fixed_height_set);
1202 break;
1203 default:
1204 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1205 break;
1206 }
1207 }
1208
1209 static void
1210 pspp_sheet_view_finalize (GObject *object)
1211 {
1212 G_OBJECT_CLASS (pspp_sheet_view_parent_class)->finalize (object);
1213 }
1214
1215
1216
1217 static void
1218 pspp_sheet_view_buildable_add_child (GtkBuildable *tree_view,
1219 GtkBuilder *builder,
1220 GObject *child,
1221 const gchar *type)
1222 {
1223 pspp_sheet_view_append_column (PSPP_SHEET_VIEW (tree_view), PSPP_SHEET_VIEW_COLUMN (child));
1224 }
1225
1226 /* GtkObject Methods
1227 */
1228
1229 static void
1230 pspp_sheet_view_destroy (GtkObject *object)
1231 {
1232 PsppSheetView *tree_view = PSPP_SHEET_VIEW (object);
1233 GList *list;
1234
1235 pspp_sheet_view_stop_editing (tree_view, TRUE);
1236
1237 if (tree_view->priv->selected != NULL)
1238 {
1239 range_tower_destroy (tree_view->priv->selected);
1240 tree_view->priv->selected = NULL;
1241 }
1242
1243 if (tree_view->priv->columns != NULL)
1244 {
1245 list = tree_view->priv->columns;
1246 while (list)
1247 {
1248 PsppSheetViewColumn *column;
1249 column = PSPP_SHEET_VIEW_COLUMN (list->data);
1250 list = list->next;
1251 pspp_sheet_view_remove_column (tree_view, column);
1252 }
1253 tree_view->priv->columns = NULL;
1254 }
1255
1256 tree_view->priv->prelight_node = -1;
1257
1258 if (tree_view->priv->selection != NULL)
1259 {
1260 _pspp_sheet_selection_set_tree_view (tree_view->priv->selection, NULL);
1261 g_object_unref (tree_view->priv->selection);
1262 tree_view->priv->selection = NULL;
1263 }
1264
1265 if (tree_view->priv->scroll_to_path != NULL)
1266 {
1267 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
1268 tree_view->priv->scroll_to_path = NULL;
1269 }
1270
1271 if (tree_view->priv->drag_dest_row != NULL)
1272 {
1273 gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
1274 tree_view->priv->drag_dest_row = NULL;
1275 }
1276
1277 if (tree_view->priv->top_row != NULL)
1278 {
1279 gtk_tree_row_reference_free (tree_view->priv->top_row);
1280 tree_view->priv->top_row = NULL;
1281 }
1282
1283 if (tree_view->priv->column_drop_func_data &&
1284 tree_view->priv->column_drop_func_data_destroy)
1285 {
1286 tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
1287 tree_view->priv->column_drop_func_data = NULL;
1288 }
1289
1290 if (tree_view->priv->destroy_count_destroy &&
1291 tree_view->priv->destroy_count_data)
1292 {
1293 tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
1294 tree_view->priv->destroy_count_data = NULL;
1295 }
1296
1297 gtk_tree_row_reference_free (tree_view->priv->cursor);
1298 tree_view->priv->cursor = NULL;
1299
1300 gtk_tree_row_reference_free (tree_view->priv->anchor);
1301 tree_view->priv->anchor = NULL;
1302
1303 /* destroy interactive search dialog */
1304 if (tree_view->priv->search_window)
1305 {
1306 gtk_widget_destroy (tree_view->priv->search_window);
1307 tree_view->priv->search_window = NULL;
1308 tree_view->priv->search_entry = NULL;
1309 if (tree_view->priv->typeselect_flush_timeout)
1310 {
1311 g_source_remove (tree_view->priv->typeselect_flush_timeout);
1312 tree_view->priv->typeselect_flush_timeout = 0;
1313 }
1314 }
1315
1316 if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
1317 {
1318 tree_view->priv->search_destroy (tree_view->priv->search_user_data);
1319 tree_view->priv->search_user_data = NULL;
1320 }
1321
1322 if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
1323 {
1324 tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
1325 tree_view->priv->search_position_user_data = NULL;
1326 }
1327
1328 pspp_sheet_view_set_model (tree_view, NULL);
1329
1330 if (tree_view->priv->hadjustment)
1331 {
1332 g_object_unref (tree_view->priv->hadjustment);
1333 tree_view->priv->hadjustment = NULL;
1334 }
1335 if (tree_view->priv->vadjustment)
1336 {
1337 g_object_unref (tree_view->priv->vadjustment);
1338 tree_view->priv->vadjustment = NULL;
1339 }
1340
1341 if (tree_view->priv->button_style)
1342 {
1343 g_object_unref (tree_view->priv->button_style);
1344 tree_view->priv->button_style = NULL;
1345 }
1346
1347 GTK_OBJECT_CLASS (pspp_sheet_view_parent_class)->destroy (object);
1348 }
1349
1350
1351
1352 /* GtkWidget Methods
1353 */
1354
1355 /* GtkWidget::map helper */
1356 static void
1357 pspp_sheet_view_map_buttons (PsppSheetView *tree_view)
1358 {
1359 GList *list;
1360
1361 g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (tree_view)));
1362
1363 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
1364 {
1365 PsppSheetViewColumn *column;
1366
1367 for (list = tree_view->priv->columns; list; list = list->next)
1368 {
1369 column = list->data;
1370 if (column->button != NULL &&
1371 gtk_widget_get_visible (column->button) &&
1372 !gtk_widget_get_mapped (column->button))
1373 gtk_widget_map (column->button);
1374 }
1375 for (list = tree_view->priv->columns; list; list = list->next)
1376 {
1377 column = list->data;
1378 if (column->visible == FALSE || column->window == NULL)
1379 continue;
1380 if (column->resizable)
1381 {
1382 gdk_window_raise (column->window);
1383 gdk_window_show (column->window);
1384 }
1385 else
1386 gdk_window_hide (column->window);
1387 }
1388 gdk_window_show (tree_view->priv->header_window);
1389 }
1390 }
1391
1392 static void
1393 pspp_sheet_view_map (GtkWidget *widget)
1394 {
1395 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
1396 GList *tmp_list;
1397
1398 gtk_widget_set_mapped (widget, TRUE);
1399
1400 tmp_list = tree_view->priv->children;
1401 while (tmp_list)
1402 {
1403 PsppSheetViewChild *child = tmp_list->data;
1404 tmp_list = tmp_list->next;
1405
1406 if (gtk_widget_get_visible (child->widget))
1407 {
1408 if (!gtk_widget_get_mapped (child->widget))
1409 gtk_widget_map (child->widget);
1410 }
1411 }
1412 gdk_window_show (tree_view->priv->bin_window);
1413
1414 pspp_sheet_view_map_buttons (tree_view);
1415
1416 gdk_window_show (widget->window);
1417 }
1418
1419 static void
1420 pspp_sheet_view_realize (GtkWidget *widget)
1421 {
1422 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
1423 GList *tmp_list;
1424 GdkWindowAttr attributes;
1425 gint attributes_mask;
1426
1427 gtk_widget_set_realized (widget, TRUE);
1428
1429 /* Make the main, clipping window */
1430 attributes.window_type = GDK_WINDOW_CHILD;
1431 attributes.x = widget->allocation.x;
1432 attributes.y = widget->allocation.y;
1433 attributes.width = widget->allocation.width;
1434 attributes.height = widget->allocation.height;
1435 attributes.wclass = GDK_INPUT_OUTPUT;
1436 attributes.visual = gtk_widget_get_visual (widget);
1437 attributes.colormap = gtk_widget_get_colormap (widget);
1438 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
1439
1440 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1441
1442 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
1443 &attributes, attributes_mask);
1444 gdk_window_set_user_data (widget->window, widget);
1445
1446 /* Make the window for the tree */
1447 attributes.x = 0;
1448 attributes.y = TREE_VIEW_HEADER_HEIGHT (tree_view);
1449 attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
1450 attributes.height = widget->allocation.height;
1451 attributes.event_mask = (GDK_EXPOSURE_MASK |
1452 GDK_SCROLL_MASK |
1453 GDK_POINTER_MOTION_MASK |
1454 GDK_ENTER_NOTIFY_MASK |
1455 GDK_LEAVE_NOTIFY_MASK |
1456 GDK_BUTTON_PRESS_MASK |
1457 GDK_BUTTON_RELEASE_MASK |
1458 gtk_widget_get_events (widget));
1459
1460 tree_view->priv->bin_window = gdk_window_new (widget->window,
1461 &attributes, attributes_mask);
1462 gdk_window_set_user_data (tree_view->priv->bin_window, widget);
1463
1464 /* Make the column header window */
1465 attributes.x = 0;
1466 attributes.y = 0;
1467 attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
1468 attributes.height = tree_view->priv->header_height;
1469 attributes.event_mask = (GDK_EXPOSURE_MASK |
1470 GDK_SCROLL_MASK |
1471 GDK_BUTTON_PRESS_MASK |
1472 GDK_BUTTON_RELEASE_MASK |
1473 GDK_KEY_PRESS_MASK |
1474 GDK_KEY_RELEASE_MASK |
1475 gtk_widget_get_events (widget));
1476
1477 tree_view->priv->header_window = gdk_window_new (widget->window,
1478 &attributes, attributes_mask);
1479 gdk_window_set_user_data (tree_view->priv->header_window, widget);
1480
1481 /* Add them all up. */
1482 widget->style = gtk_style_attach (widget->style, widget->window);
1483 gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
1484 gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
1485 gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
1486
1487 tmp_list = tree_view->priv->children;
1488 while (tmp_list)
1489 {
1490 PsppSheetViewChild *child = tmp_list->data;
1491 tmp_list = tmp_list->next;
1492
1493 gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
1494 }
1495
1496 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1497 _pspp_sheet_view_column_realize_button (PSPP_SHEET_VIEW_COLUMN (tmp_list->data));
1498
1499 /* Need to call those here, since they create GCs */
1500 pspp_sheet_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
1501
1502 install_presize_handler (tree_view);
1503 }
1504
1505 static void
1506 pspp_sheet_view_unrealize (GtkWidget *widget)
1507 {
1508 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
1509 PsppSheetViewPrivate *priv = tree_view->priv;
1510 GList *list;
1511
1512 if (priv->scroll_timeout != 0)
1513 {
1514 g_source_remove (priv->scroll_timeout);
1515 priv->scroll_timeout = 0;
1516 }
1517
1518 if (priv->open_dest_timeout != 0)
1519 {
1520 g_source_remove (priv->open_dest_timeout);
1521 priv->open_dest_timeout = 0;
1522 }
1523
1524 if (priv->presize_handler_timer != 0)
1525 {
1526 g_source_remove (priv->presize_handler_timer);
1527 priv->presize_handler_timer = 0;
1528 }
1529
1530 if (priv->validate_rows_timer != 0)
1531 {
1532 g_source_remove (priv->validate_rows_timer);
1533 priv->validate_rows_timer = 0;
1534 }
1535
1536 if (priv->scroll_sync_timer != 0)
1537 {
1538 g_source_remove (priv->scroll_sync_timer);
1539 priv->scroll_sync_timer = 0;
1540 }
1541
1542 if (priv->typeselect_flush_timeout)
1543 {
1544 g_source_remove (priv->typeselect_flush_timeout);
1545 priv->typeselect_flush_timeout = 0;
1546 }
1547
1548 for (list = priv->columns; list; list = list->next)
1549 _pspp_sheet_view_column_unrealize_button (PSPP_SHEET_VIEW_COLUMN (list->data));
1550
1551 gdk_window_set_user_data (priv->bin_window, NULL);
1552 gdk_window_destroy (priv->bin_window);
1553 priv->bin_window = NULL;
1554
1555 gdk_window_set_user_data (priv->header_window, NULL);
1556 gdk_window_destroy (priv->header_window);
1557 priv->header_window = NULL;
1558
1559 if (priv->drag_window)
1560 {
1561 gdk_window_set_user_data (priv->drag_window, NULL);
1562 gdk_window_destroy (priv->drag_window);
1563 priv->drag_window = NULL;
1564 }
1565
1566 if (priv->drag_highlight_window)
1567 {
1568 gdk_window_set_user_data (priv->drag_highlight_window, NULL);
1569 gdk_window_destroy (priv->drag_highlight_window);
1570 priv->drag_highlight_window = NULL;
1571 }
1572
1573 if (priv->grid_line_gc)
1574 {
1575 g_object_unref (priv->grid_line_gc);
1576 priv->grid_line_gc = NULL;
1577 }
1578
1579 GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->unrealize (widget);
1580 }
1581
1582 /* GtkWidget::size_request helper */
1583 static void
1584 pspp_sheet_view_size_request_columns (PsppSheetView *tree_view)
1585 {
1586 GList *list;
1587
1588 tree_view->priv->header_height = 0;
1589
1590 if (tree_view->priv->model)
1591 {
1592 for (list = tree_view->priv->columns; list; list = list->next)
1593 {
1594 GtkRequisition requisition;
1595 PsppSheetViewColumn *column = list->data;
1596
1597 pspp_sheet_view_column_size_request (column, &requisition);
1598 column->button_request = requisition.width;
1599 tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
1600 }
1601 }
1602 }
1603
1604
1605 /* Called only by ::size_request */
1606 static void
1607 pspp_sheet_view_update_size (PsppSheetView *tree_view)
1608 {
1609 GList *list;
1610 PsppSheetViewColumn *column;
1611 gint i;
1612
1613 if (tree_view->priv->model == NULL)
1614 {
1615 tree_view->priv->width = 0;
1616 tree_view->priv->prev_width = 0;
1617 tree_view->priv->height = 0;
1618 return;
1619 }
1620
1621 tree_view->priv->prev_width = tree_view->priv->width;
1622 tree_view->priv->width = 0;
1623
1624 /* keep this in sync with size_allocate below */
1625 for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
1626 {
1627 gint real_requested_width = 0;
1628 column = list->data;
1629 if (!column->visible)
1630 continue;
1631
1632 if (column->use_resized_width)
1633 {
1634 real_requested_width = column->resized_width;
1635 }
1636 else
1637 {
1638 real_requested_width = column->fixed_width;
1639 }
1640
1641 if (column->min_width != -1)
1642 real_requested_width = MAX (real_requested_width, column->min_width);
1643 if (column->max_width != -1)
1644 real_requested_width = MIN (real_requested_width, column->max_width);
1645
1646 tree_view->priv->width += real_requested_width;
1647 }
1648
1649 tree_view->priv->height = tree_view->priv->fixed_height * tree_view->priv->row_count;
1650 }
1651
1652 static void
1653 pspp_sheet_view_size_request (GtkWidget *widget,
1654 GtkRequisition *requisition)
1655 {
1656 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
1657 GList *tmp_list;
1658
1659 /* we validate some rows initially just to make sure we have some size.
1660 * In practice, with a lot of static lists, this should get a good width.
1661 */
1662 initialize_fixed_height_mode (tree_view);
1663 pspp_sheet_view_size_request_columns (tree_view);
1664 pspp_sheet_view_update_size (PSPP_SHEET_VIEW (widget));
1665
1666 requisition->width = tree_view->priv->width;
1667 requisition->height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
1668
1669 tmp_list = tree_view->priv->children;
1670
1671 while (tmp_list)
1672 {
1673 PsppSheetViewChild *child = tmp_list->data;
1674 GtkRequisition child_requisition;
1675
1676 tmp_list = tmp_list->next;
1677
1678 if (gtk_widget_get_visible (child->widget))
1679 gtk_widget_size_request (child->widget, &child_requisition);
1680 }
1681 }
1682
1683 static void
1684 invalidate_column (PsppSheetView *tree_view,
1685 PsppSheetViewColumn *column)
1686 {
1687 gint column_offset = 0;
1688 GList *list;
1689 GtkWidget *widget = GTK_WIDGET (tree_view);
1690 gboolean rtl;
1691
1692 if (!gtk_widget_get_realized (widget))
1693 return;
1694
1695 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1696 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
1697 list;
1698 list = (rtl ? list->prev : list->next))
1699 {
1700 PsppSheetViewColumn *tmpcolumn = list->data;
1701 if (tmpcolumn == column)
1702 {
1703 GdkRectangle invalid_rect;
1704
1705 invalid_rect.x = column_offset;
1706 invalid_rect.y = 0;
1707 invalid_rect.width = column->width;
1708 invalid_rect.height = widget->allocation.height;
1709
1710 gdk_window_invalidate_rect (widget->window, &invalid_rect, TRUE);
1711 break;
1712 }
1713
1714 column_offset += tmpcolumn->width;
1715 }
1716 }
1717
1718 static void
1719 invalidate_last_column (PsppSheetView *tree_view)
1720 {
1721 GList *last_column;
1722 gboolean rtl;
1723
1724 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1725
1726 for (last_column = (rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns));
1727 last_column;
1728 last_column = (rtl ? last_column->next : last_column->prev))
1729 {
1730 if (PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible)
1731 {
1732 invalidate_column (tree_view, last_column->data);
1733 return;
1734 }
1735 }
1736 }
1737
1738 static gint
1739 pspp_sheet_view_get_real_requested_width_from_column (PsppSheetView *tree_view,
1740 PsppSheetViewColumn *column)
1741 {
1742 gint real_requested_width;
1743
1744 if (column->use_resized_width)
1745 {
1746 real_requested_width = column->resized_width;
1747 }
1748 else
1749 {
1750 real_requested_width = column->fixed_width;
1751 }
1752
1753 if (column->min_width != -1)
1754 real_requested_width = MAX (real_requested_width, column->min_width);
1755 if (column->max_width != -1)
1756 real_requested_width = MIN (real_requested_width, column->max_width);
1757
1758 return real_requested_width;
1759 }
1760
1761 static gboolean
1762 span_intersects (int a0, int a_width,
1763 int b0, int b_width)
1764 {
1765 int a1 = a0 + a_width;
1766 int b1 = b0 + b_width;
1767 return (a0 >= b0 && a0 < b1) || (b0 >= a0 && b0 < a1);
1768 }
1769
1770 /* GtkWidget::size_allocate helper */
1771 static void
1772 pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
1773 gboolean *width_changed)
1774 {
1775 PsppSheetView *tree_view;
1776 GList *list, *first_column, *last_column;
1777 PsppSheetViewColumn *column;
1778 GtkAllocation allocation;
1779 gint width = 0;
1780 gint extra, extra_per_column;
1781 gint full_requested_width = 0;
1782 gint number_of_expand_columns = 0;
1783 gboolean column_changed = FALSE;
1784 gboolean rtl;
1785
1786 tree_view = PSPP_SHEET_VIEW (widget);
1787
1788 for (last_column = g_list_last (tree_view->priv->columns);
1789 last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
1790 last_column = last_column->prev)
1791 ;
1792 if (last_column == NULL)
1793 return;
1794
1795 for (first_column = g_list_first (tree_view->priv->columns);
1796 first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
1797 first_column = first_column->next)
1798 ;
1799
1800 allocation.y = 0;
1801 allocation.height = tree_view->priv->header_height;
1802
1803 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1804
1805 /* find out how many extra space and expandable columns we have */
1806 for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
1807 {
1808 column = (PsppSheetViewColumn *)list->data;
1809
1810 if (!column->visible)
1811 continue;
1812
1813 full_requested_width += pspp_sheet_view_get_real_requested_width_from_column (tree_view, column);
1814
1815 if (column->expand)
1816 number_of_expand_columns++;
1817 }
1818
1819 extra = MAX (widget->allocation.width - full_requested_width, 0);
1820 if (number_of_expand_columns > 0)
1821 extra_per_column = extra/number_of_expand_columns;
1822 else
1823 extra_per_column = 0;
1824
1825 for (list = (rtl ? last_column : first_column);
1826 list != (rtl ? first_column->prev : last_column->next);
1827 list = (rtl ? list->prev : list->next))
1828 {
1829 gint real_requested_width = 0;
1830 gint old_width;
1831
1832 column = list->data;
1833 old_width = column->width;
1834
1835 if (!column->visible)
1836 continue;
1837
1838 /* We need to handle the dragged button specially.
1839 */
1840 if (column == tree_view->priv->drag_column)
1841 {
1842 GtkAllocation drag_allocation;
1843 gdk_drawable_get_size (tree_view->priv->drag_window,
1844 &(drag_allocation.width),
1845 &(drag_allocation.height));
1846 drag_allocation.x = 0;
1847 drag_allocation.y = 0;
1848 pspp_sheet_view_column_size_allocate (tree_view->priv->drag_column,
1849 &drag_allocation);
1850 width += drag_allocation.width;
1851 continue;
1852 }
1853
1854 real_requested_width = pspp_sheet_view_get_real_requested_width_from_column (tree_view, column);
1855
1856 allocation.x = width;
1857 column->width = real_requested_width;
1858
1859 if (column->expand)
1860 {
1861 if (number_of_expand_columns == 1)
1862 {
1863 /* We add the remander to the last column as
1864 * */
1865 column->width += extra;
1866 }
1867 else
1868 {
1869 column->width += extra_per_column;
1870 extra -= extra_per_column;
1871 number_of_expand_columns --;
1872 }
1873 }
1874
1875 if (column->width != old_width)
1876 g_object_notify (G_OBJECT (column), "width");
1877
1878 allocation.width = column->width;
1879 width += column->width;
1880
1881 if (column->width > old_width)
1882 column_changed = TRUE;
1883
1884 pspp_sheet_view_column_size_allocate (column, &allocation);
1885
1886 if (span_intersects (allocation.x, allocation.width,
1887 tree_view->priv->hadjustment->value,
1888 widget->allocation.width)
1889 && gtk_widget_get_realized (widget))
1890 pspp_sheet_view_column_set_need_button (column, TRUE);
1891
1892 if (column->window)
1893 gdk_window_move_resize (column->window,
1894 allocation.x + (rtl ? 0 : allocation.width) - TREE_VIEW_DRAG_WIDTH/2,
1895 allocation.y,
1896 TREE_VIEW_DRAG_WIDTH, allocation.height);
1897 }
1898
1899 /* We change the width here. The user might have been resizing columns,
1900 * so the total width of the tree view changes.
1901 */
1902 tree_view->priv->width = width;
1903 if (width_changed)
1904 *width_changed = TRUE;
1905
1906 if (column_changed)
1907 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
1908 }
1909
1910
1911 static void
1912 pspp_sheet_view_size_allocate (GtkWidget *widget,
1913 GtkAllocation *allocation)
1914 {
1915 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
1916 GList *tmp_list;
1917 gboolean width_changed = FALSE;
1918 gint old_width = widget->allocation.width;
1919
1920 if (allocation->width != widget->allocation.width)
1921 width_changed = TRUE;
1922
1923 widget->allocation = *allocation;
1924
1925 tmp_list = tree_view->priv->children;
1926
1927 while (tmp_list)
1928 {
1929 GtkAllocation allocation;
1930
1931 PsppSheetViewChild *child = tmp_list->data;
1932 tmp_list = tmp_list->next;
1933
1934 /* totally ignore our child's requisition */
1935 allocation.x = child->x;
1936 allocation.y = child->y;
1937 allocation.width = child->width;
1938 allocation.height = child->height;
1939 gtk_widget_size_allocate (child->widget, &allocation);
1940 }
1941
1942 /* We size-allocate the columns first because the width of the
1943 * tree view (used in updating the adjustments below) might change.
1944 */
1945 pspp_sheet_view_size_allocate_columns (widget, &width_changed);
1946
1947 tree_view->priv->hadjustment->page_size = allocation->width;
1948 tree_view->priv->hadjustment->page_increment = allocation->width * 0.9;
1949 tree_view->priv->hadjustment->step_increment = allocation->width * 0.1;
1950 tree_view->priv->hadjustment->lower = 0;
1951 tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->page_size, tree_view->priv->width);
1952
1953 if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)
1954 {
1955 if (allocation->width < tree_view->priv->width)
1956 {
1957 if (tree_view->priv->init_hadjust_value)
1958 {
1959 tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
1960 tree_view->priv->init_hadjust_value = FALSE;
1961 }
1962 else if (allocation->width != old_width)
1963 {
1964 tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->hadjustment->value - allocation->width + old_width, 0, tree_view->priv->width - allocation->width);
1965 }
1966 else
1967 tree_view->priv->hadjustment->value = CLAMP (tree_view->priv->width - (tree_view->priv->prev_width - tree_view->priv->hadjustment->value), 0, tree_view->priv->width - allocation->width);
1968 }
1969 else
1970 {
1971 tree_view->priv->hadjustment->value = 0;
1972 tree_view->priv->init_hadjust_value = TRUE;
1973 }
1974 }
1975 else
1976 if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
1977 tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
1978
1979 gtk_adjustment_changed (tree_view->priv->hadjustment);
1980
1981 tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
1982 tree_view->priv->vadjustment->step_increment = tree_view->priv->vadjustment->page_size * 0.1;
1983 tree_view->priv->vadjustment->page_increment = tree_view->priv->vadjustment->page_size * 0.9;
1984 tree_view->priv->vadjustment->lower = 0;
1985 tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->page_size, tree_view->priv->height);
1986
1987 gtk_adjustment_changed (tree_view->priv->vadjustment);
1988
1989 /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
1990 if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
1991 gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
1992 else if (tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
1993 gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
1994 tree_view->priv->height - tree_view->priv->vadjustment->page_size);
1995 else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
1996 pspp_sheet_view_top_row_to_dy (tree_view);
1997 else
1998 pspp_sheet_view_dy_to_top_row (tree_view);
1999
2000 if (gtk_widget_get_realized (widget))
2001 {
2002 gdk_window_move_resize (widget->window,
2003 allocation->x, allocation->y,
2004 allocation->width, allocation->height);
2005 gdk_window_move_resize (tree_view->priv->header_window,
2006 - (gint) tree_view->priv->hadjustment->value,
2007 0,
2008 MAX (tree_view->priv->width, allocation->width),
2009 tree_view->priv->header_height);
2010 gdk_window_move_resize (tree_view->priv->bin_window,
2011 - (gint) tree_view->priv->hadjustment->value,
2012 TREE_VIEW_HEADER_HEIGHT (tree_view),
2013 MAX (tree_view->priv->width, allocation->width),
2014 allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
2015 }
2016
2017 if (tree_view->priv->row_count == 0)
2018 invalidate_empty_focus (tree_view);
2019
2020 if (gtk_widget_get_realized (widget))
2021 {
2022 gboolean has_expand_column = FALSE;
2023 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
2024 {
2025 if (pspp_sheet_view_column_get_expand (PSPP_SHEET_VIEW_COLUMN (tmp_list->data)))
2026 {
2027 has_expand_column = TRUE;
2028 break;
2029 }
2030 }
2031
2032 /* This little hack only works if we have an LTR locale, and no column has the */
2033 if (width_changed)
2034 {
2035 if (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_LTR &&
2036 ! has_expand_column)
2037 invalidate_last_column (tree_view);
2038 else
2039 gtk_widget_queue_draw (widget);
2040 }
2041 }
2042 }
2043
2044 /* Grabs the focus and unsets the PSPP_SHEET_VIEW_DRAW_KEYFOCUS flag */
2045 static void
2046 grab_focus_and_unset_draw_keyfocus (PsppSheetView *tree_view)
2047 {
2048 GtkWidget *widget = GTK_WIDGET (tree_view);
2049
2050 if (gtk_widget_get_can_focus (widget) && !gtk_widget_has_focus (widget))
2051 gtk_widget_grab_focus (widget);
2052 PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
2053 }
2054
2055 gboolean
2056 pspp_sheet_view_node_is_selected (PsppSheetView *tree_view,
2057 int node)
2058 {
2059 return node >= 0 && range_tower_contains (tree_view->priv->selected, node);
2060 }
2061
2062 void
2063 pspp_sheet_view_node_select (PsppSheetView *tree_view,
2064 int node)
2065 {
2066 range_tower_set1 (tree_view->priv->selected, node, 1);
2067 }
2068
2069 void
2070 pspp_sheet_view_node_unselect (PsppSheetView *tree_view,
2071 int node)
2072 {
2073 range_tower_set0 (tree_view->priv->selected, node, 1);
2074 }
2075
2076 gint
2077 pspp_sheet_view_node_next (PsppSheetView *tree_view,
2078 gint node)
2079 {
2080 return node + 1 < tree_view->priv->row_count ? node + 1 : -1;
2081 }
2082
2083 gint
2084 pspp_sheet_view_node_prev (PsppSheetView *tree_view,
2085 gint node)
2086 {
2087 return node > 0 ? node - 1 : -1;
2088 }
2089
2090 static gboolean
2091 all_columns_selected (PsppSheetView *tree_view)
2092 {
2093 GList *list;
2094
2095 for (list = tree_view->priv->columns; list; list = list->next)
2096 {
2097 PsppSheetViewColumn *column = list->data;
2098 if (column->selectable && !column->selected)
2099 return FALSE;
2100 }
2101
2102 return TRUE;
2103 }
2104
2105 static gboolean
2106 pspp_sheet_view_row_head_clicked (PsppSheetView *tree_view,
2107 gint node,
2108 PsppSheetViewColumn *column,
2109 GdkEventButton *event)
2110 {
2111 PsppSheetSelection *selection;
2112 PsppSheetSelectionMode mode;
2113 GtkTreePath *path;
2114 gboolean update_anchor;
2115 gboolean handled;
2116 guint modifiers;
2117
2118 g_return_val_if_fail (tree_view != NULL, FALSE);
2119 g_return_val_if_fail (column != NULL, FALSE);
2120
2121 selection = tree_view->priv->selection;
2122 mode = pspp_sheet_selection_get_mode (selection);
2123 if (mode != PSPP_SHEET_SELECTION_RECTANGLE)
2124 return FALSE;
2125
2126 if (!column->row_head)
2127 return FALSE;
2128
2129 if (event)
2130 {
2131 modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
2132 if (event->type != GDK_BUTTON_PRESS
2133 || (modifiers != GDK_CONTROL_MASK && modifiers != GDK_SHIFT_MASK))
2134 return FALSE;
2135 }
2136 else
2137 modifiers = 0;
2138
2139 path = gtk_tree_path_new_from_indices (node, -1);
2140 if (event == NULL)
2141 {
2142 pspp_sheet_selection_unselect_all (selection);
2143 pspp_sheet_selection_select_path (selection, path);
2144 pspp_sheet_selection_select_all_columns (selection);
2145 update_anchor = TRUE;
2146 handled = TRUE;
2147 }
2148 else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
2149 {
2150 if (pspp_sheet_selection_count_selected_rows (selection) <= 1
2151 || !all_columns_selected (tree_view))
2152 {
2153 pspp_sheet_selection_unselect_all (selection);
2154 pspp_sheet_selection_select_path (selection, path);
2155 pspp_sheet_selection_select_all_columns (selection);
2156 update_anchor = TRUE;
2157 handled = FALSE;
2158 }
2159 else
2160 update_anchor = handled = FALSE;
2161 }
2162 else if (event->type == GDK_BUTTON_PRESS && event->button == 1
2163 && modifiers == GDK_CONTROL_MASK)
2164 {
2165 if (!all_columns_selected (tree_view))
2166 {
2167 pspp_sheet_selection_unselect_all (selection);
2168 pspp_sheet_selection_select_all_columns (selection);
2169 }
2170
2171 if (pspp_sheet_selection_path_is_selected (selection, path))
2172 pspp_sheet_selection_unselect_path (selection, path);
2173 else
2174 pspp_sheet_selection_select_path (selection, path);
2175 update_anchor = TRUE;
2176 handled = TRUE;
2177 }
2178 else if (event->type == GDK_BUTTON_PRESS && event->button == 1
2179 && modifiers == GDK_SHIFT_MASK)
2180 {
2181 GtkTreeRowReference *anchor = tree_view->priv->anchor;
2182 GtkTreePath *anchor_path;
2183
2184 if (all_columns_selected (tree_view)
2185 && gtk_tree_row_reference_valid (anchor))
2186 {
2187 update_anchor = FALSE;
2188 anchor_path = gtk_tree_row_reference_get_path (anchor);
2189 }
2190 else
2191 {
2192 update_anchor = TRUE;
2193 anchor_path = gtk_tree_path_copy (path);
2194 }
2195
2196 pspp_sheet_selection_unselect_all (selection);
2197 pspp_sheet_selection_select_range (selection, anchor_path, path);
2198 pspp_sheet_selection_select_all_columns (selection);
2199
2200 gtk_tree_path_free (anchor_path);
2201
2202 handled = TRUE;
2203 }
2204 else
2205 update_anchor = handled = FALSE;
2206
2207 if (update_anchor)
2208 {
2209 if (tree_view->priv->anchor)
2210 gtk_tree_row_reference_free (tree_view->priv->anchor);
2211 tree_view->priv->anchor =
2212 gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
2213 tree_view->priv->model,
2214 path);
2215 }
2216
2217 gtk_tree_path_free (path);
2218 return handled;
2219 }
2220
2221 static gboolean
2222 find_click (PsppSheetView *tree_view,
2223 gint x, gint y,
2224 gint *node,
2225 PsppSheetViewColumn **column,
2226 GdkRectangle *background_area,
2227 GdkRectangle *cell_area)
2228 {
2229 gint y_offset;
2230 gboolean rtl;
2231 GList *list;
2232 gint new_y;
2233
2234 /* find the node that was clicked */
2235 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, y);
2236 if (new_y < 0)
2237 new_y = 0;
2238 y_offset = -pspp_sheet_view_find_offset (tree_view, new_y, node);
2239
2240 if (*node < 0)
2241 return FALSE;
2242
2243 background_area->y = y_offset + y;
2244 background_area->height = ROW_HEIGHT (tree_view);
2245 background_area->x = 0;
2246
2247 /* Let the column have a chance at selecting it. */
2248 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
2249 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
2250 list; list = (rtl ? list->prev : list->next))
2251 {
2252 PsppSheetViewColumn *candidate = list->data;
2253
2254 if (!candidate->visible)
2255 continue;
2256
2257 background_area->width = candidate->width;
2258 if ((background_area->x > x) ||
2259 (background_area->x + background_area->width <= x))
2260 {
2261 background_area->x += background_area->width;
2262 continue;
2263 }
2264
2265 /* we found the focus column */
2266
2267 pspp_sheet_view_adjust_cell_area (tree_view, candidate, background_area,
2268 TRUE, cell_area);
2269 *column = candidate;
2270 return TRUE;
2271 }
2272
2273 return FALSE;
2274 }
2275
2276 static gboolean
2277 pspp_sheet_view_button_press (GtkWidget *widget,
2278 GdkEventButton *event)
2279 {
2280 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
2281 GList *list;
2282 PsppSheetViewColumn *column = NULL;
2283 gint i;
2284 GdkRectangle background_area;
2285 GdkRectangle cell_area;
2286 gboolean rtl;
2287
2288 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2289 pspp_sheet_view_stop_editing (tree_view, FALSE);
2290
2291
2292 /* Because grab_focus can cause reentrancy, we delay grab_focus until after
2293 * we're done handling the button press.
2294 */
2295
2296 if (event->window == tree_view->priv->bin_window)
2297 {
2298 int node;
2299 GtkTreePath *path;
2300 gint dval;
2301 gint pre_val, aft_val;
2302 PsppSheetViewColumn *column = NULL;
2303 GtkCellRenderer *focus_cell = NULL;
2304 gboolean row_double_click = FALSE;
2305 gboolean node_selected;
2306
2307 /* Empty tree? */
2308 if (tree_view->priv->row_count == 0)
2309 {
2310 grab_focus_and_unset_draw_keyfocus (tree_view);
2311 return TRUE;
2312 }
2313
2314 if (!find_click (tree_view, event->x, event->y, &node, &column,
2315 &background_area, &cell_area))
2316 {
2317 grab_focus_and_unset_draw_keyfocus (tree_view);
2318 return FALSE;
2319 }
2320
2321 tree_view->priv->focus_column = column;
2322
2323 if (pspp_sheet_view_row_head_clicked (tree_view, node, column, event))
2324 return TRUE;
2325
2326 /* select */
2327 node_selected = pspp_sheet_view_node_is_selected (tree_view, node);
2328 pre_val = tree_view->priv->vadjustment->value;
2329
2330 path = _pspp_sheet_view_find_path (tree_view, node);
2331
2332 /* we only handle selection modifications on the first button press
2333 */
2334 if (event->type == GDK_BUTTON_PRESS)
2335 {
2336 if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
2337 tree_view->priv->ctrl_pressed = TRUE;
2338 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
2339 tree_view->priv->shift_pressed = TRUE;
2340
2341 focus_cell = _pspp_sheet_view_column_get_cell_at_pos (column, event->x - background_area.x);
2342 if (focus_cell)
2343 pspp_sheet_view_column_focus_cell (column, focus_cell);
2344
2345 if (event->state & GDK_CONTROL_MASK)
2346 {
2347 pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE);
2348 pspp_sheet_view_real_toggle_cursor_row (tree_view);
2349 }
2350 else if (event->state & GDK_SHIFT_MASK)
2351 {
2352 pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE);
2353 pspp_sheet_view_real_select_cursor_row (tree_view, FALSE);
2354 }
2355 else
2356 {
2357 pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE);
2358 }
2359
2360 if (tree_view->priv->anchor_column == NULL ||
2361 !(event->state & GDK_SHIFT_MASK))
2362 tree_view->priv->anchor_column = column;
2363 pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
2364 pspp_sheet_selection_select_column_range (tree_view->priv->selection,
2365 tree_view->priv->anchor_column,
2366 column);
2367
2368 tree_view->priv->ctrl_pressed = FALSE;
2369 tree_view->priv->shift_pressed = FALSE;
2370 }
2371
2372 /* the treeview may have been scrolled because of _set_cursor,
2373 * correct here
2374 */
2375
2376 aft_val = tree_view->priv->vadjustment->value;
2377 dval = pre_val - aft_val;
2378
2379 cell_area.y += dval;
2380 background_area.y += dval;
2381
2382 /* Save press to possibly begin a drag
2383 */
2384 if (!tree_view->priv->in_grab &&
2385 tree_view->priv->pressed_button < 0)
2386 {
2387 tree_view->priv->pressed_button = event->button;
2388 tree_view->priv->press_start_x = event->x;
2389 tree_view->priv->press_start_y = event->y;
2390 tree_view->priv->press_start_node = node;
2391
2392 if (tree_view->priv->rubber_banding_enable
2393 //&& !node_selected
2394 && (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
2395 tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE))
2396 {
2397 tree_view->priv->press_start_y += tree_view->priv->dy;
2398 tree_view->priv->rubber_band_x = event->x;
2399 tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
2400 tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
2401
2402 if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
2403 tree_view->priv->rubber_band_ctrl = TRUE;
2404 if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
2405 tree_view->priv->rubber_band_shift = TRUE;
2406
2407 }
2408 }
2409
2410 /* Test if a double click happened on the same row. */
2411 if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
2412 {
2413 int double_click_time, double_click_distance;
2414
2415 g_object_get (gtk_settings_get_for_screen (
2416 gtk_widget_get_screen (widget)),
2417 "gtk-double-click-time", &double_click_time,
2418 "gtk-double-click-distance", &double_click_distance,
2419 NULL);
2420
2421 /* Same conditions as _gdk_event_button_generate */
2422 if (tree_view->priv->last_button_x != -1 &&
2423 (event->time < tree_view->priv->last_button_time + double_click_time) &&
2424 (ABS (event->x - tree_view->priv->last_button_x) <= double_click_distance) &&
2425 (ABS (event->y - tree_view->priv->last_button_y) <= double_click_distance))
2426 {
2427 /* We do no longer compare paths of this row and the
2428 * row clicked previously. We use the double click
2429 * distance to decide whether this is a valid click,
2430 * allowing the mouse to slightly move over another row.
2431 */
2432 row_double_click = TRUE;
2433
2434 tree_view->priv->last_button_time = 0;
2435 tree_view->priv->last_button_x = -1;
2436 tree_view->priv->last_button_y = -1;
2437 }
2438 else
2439 {
2440 tree_view->priv->last_button_time = event->time;
2441 tree_view->priv->last_button_x = event->x;
2442 tree_view->priv->last_button_y = event->y;
2443 }
2444 }
2445
2446 if (row_double_click)
2447 {
2448 gtk_grab_remove (widget);
2449 pspp_sheet_view_row_activated (tree_view, path, column);
2450
2451 if (tree_view->priv->pressed_button == event->button)
2452 tree_view->priv->pressed_button = -1;
2453 }
2454
2455 gtk_tree_path_free (path);
2456
2457 /* If we activated the row through a double click we don't want to grab
2458 * focus back, as moving focus to another widget is pretty common.
2459 */
2460 if (!row_double_click)
2461 grab_focus_and_unset_draw_keyfocus (tree_view);
2462
2463 return TRUE;
2464 }
2465
2466 /* We didn't click in the window. Let's check to see if we clicked on a column resize window.
2467 */
2468 for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
2469 {
2470 column = list->data;
2471 if (event->window == column->window &&
2472 column->resizable &&
2473 column->window)
2474 {
2475 gpointer drag_data;
2476
2477 if (gdk_pointer_grab (column->window, FALSE,
2478 GDK_POINTER_MOTION_HINT_MASK |
2479 GDK_BUTTON1_MOTION_MASK |
2480 GDK_BUTTON_RELEASE_MASK,
2481 NULL, NULL, event->time))
2482 return FALSE;
2483
2484 gtk_grab_add (widget);
2485 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE);
2486 column->resized_width = column->width;
2487
2488 /* block attached dnd signal handler */
2489 drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
2490 if (drag_data)
2491 g_signal_handlers_block_matched (widget,
2492 G_SIGNAL_MATCH_DATA,
2493 0, 0, NULL, NULL,
2494 drag_data);
2495
2496 tree_view->priv->drag_pos = i;
2497 tree_view->priv->x_drag = column->allocation.x + (rtl ? 0 : column->allocation.width);
2498
2499 if (!gtk_widget_has_focus (widget))
2500 gtk_widget_grab_focus (widget);
2501
2502 return TRUE;
2503 }
2504 }
2505 return FALSE;
2506 }
2507
2508 /* GtkWidget::button_release_event helper */
2509 static gboolean
2510 pspp_sheet_view_button_release_drag_column (GtkWidget *widget,
2511 GdkEventButton *event)
2512 {
2513 PsppSheetView *tree_view;
2514 GList *l;
2515 gboolean rtl;
2516
2517 tree_view = PSPP_SHEET_VIEW (widget);
2518
2519 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
2520 gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
2521 gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
2522
2523 /* Move the button back */
2524 g_return_val_if_fail (tree_view->priv->drag_column->button, FALSE);
2525
2526 g_object_ref (tree_view->priv->drag_column->button);
2527 gtk_container_remove (GTK_CONTAINER (tree_view), tree_view->priv->drag_column->button);
2528 gtk_widget_set_parent_window (tree_view->priv->drag_column->button, tree_view->priv->header_window);
2529 gtk_widget_set_parent (tree_view->priv->drag_column->button, GTK_WIDGET (tree_view));
2530 g_object_unref (tree_view->priv->drag_column->button);
2531 gtk_widget_queue_resize (widget);
2532 if (tree_view->priv->drag_column->resizable)
2533 {
2534 gdk_window_raise (tree_view->priv->drag_column->window);
2535 gdk_window_show (tree_view->priv->drag_column->window);
2536 }
2537 else
2538 gdk_window_hide (tree_view->priv->drag_column->window);
2539
2540 gtk_widget_grab_focus (tree_view->priv->drag_column->button);
2541
2542 if (rtl)
2543 {
2544 if (tree_view->priv->cur_reorder &&
2545 tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
2546 pspp_sheet_view_move_column_after (tree_view, tree_view->priv->drag_column,
2547 tree_view->priv->cur_reorder->right_column);
2548 }
2549 else
2550 {
2551 if (tree_view->priv->cur_reorder &&
2552 tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
2553 pspp_sheet_view_move_column_after (tree_view, tree_view->priv->drag_column,
2554 tree_view->priv->cur_reorder->left_column);
2555 }
2556 tree_view->priv->drag_column = NULL;
2557 gdk_window_hide (tree_view->priv->drag_window);
2558
2559 for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next)
2560 g_slice_free (PsppSheetViewColumnReorder, l->data);
2561 g_list_free (tree_view->priv->column_drag_info);
2562 tree_view->priv->column_drag_info = NULL;
2563 tree_view->priv->cur_reorder = NULL;
2564
2565 if (tree_view->priv->drag_highlight_window)
2566 gdk_window_hide (tree_view->priv->drag_highlight_window);
2567
2568 /* Reset our flags */
2569 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
2570 PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG);
2571
2572 return TRUE;
2573 }
2574
2575 /* GtkWidget::button_release_event helper */
2576 static gboolean
2577 pspp_sheet_view_button_release_column_resize (GtkWidget *widget,
2578 GdkEventButton *event)
2579 {
2580 PsppSheetView *tree_view;
2581 gpointer drag_data;
2582
2583 tree_view = PSPP_SHEET_VIEW (widget);
2584
2585 tree_view->priv->drag_pos = -1;
2586
2587 /* unblock attached dnd signal handler */
2588 drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
2589 if (drag_data)
2590 g_signal_handlers_unblock_matched (widget,
2591 G_SIGNAL_MATCH_DATA,
2592 0, 0, NULL, NULL,
2593 drag_data);
2594
2595 PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE);
2596 gtk_grab_remove (widget);
2597 gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window),
2598 event->time);
2599 return TRUE;
2600 }
2601
2602 static gboolean
2603 pspp_sheet_view_button_release_edit (PsppSheetView *tree_view,
2604 GdkEventButton *event)
2605 {
2606 GtkCellEditable *cell_editable;
2607 gchar *path_string;
2608 GtkTreePath *path;
2609 gint left, right;
2610 GtkTreeIter iter;
2611 PsppSheetViewColumn *column;
2612 GdkRectangle background_area;
2613 GdkRectangle cell_area;
2614 GdkRectangle area;
2615 guint modifiers;
2616 guint flags;
2617 int node;
2618
2619 if (event->window != tree_view->priv->bin_window)
2620 return FALSE;
2621
2622 if (!find_click (tree_view, event->x, event->y, &node, &column, &background_area,
2623 &cell_area))
2624 return FALSE;
2625
2626 /* decide if we edit */
2627 path = _pspp_sheet_view_find_path (tree_view, node);
2628 modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
2629 if (event->button != 1 || modifiers)
2630 return FALSE;
2631
2632 gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
2633 pspp_sheet_view_column_cell_set_cell_data (column,
2634 tree_view->priv->model,
2635 &iter);
2636
2637 if (!pspp_sheet_view_column_get_quick_edit (column)
2638 && _pspp_sheet_view_column_has_editable_cell (column))
2639 return FALSE;
2640
2641 flags = 0; /* FIXME: get the right flags */
2642 path_string = gtk_tree_path_to_string (path);
2643
2644 if (!_pspp_sheet_view_column_cell_event (column,
2645 &cell_editable,
2646 (GdkEvent *)event,
2647 path_string,
2648 &background_area,
2649 &cell_area, flags))
2650 return FALSE;
2651
2652 if (cell_editable == NULL)
2653 return FALSE;
2654
2655 pspp_sheet_view_real_set_cursor (tree_view, path,
2656 TRUE, TRUE);
2657 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2658
2659 area = cell_area;
2660 _pspp_sheet_view_column_get_neighbor_sizes (
2661 column, _pspp_sheet_view_column_get_edited_cell (column), &left, &right);
2662
2663 area.x += left;
2664 area.width -= right + left;
2665
2666 pspp_sheet_view_real_start_editing (tree_view,
2667 column,
2668 path,
2669 cell_editable,
2670 &area,
2671 (GdkEvent *)event,
2672 flags);
2673 g_free (path_string);
2674 gtk_tree_path_free (path);
2675 return TRUE;
2676 }
2677
2678 static gboolean
2679 pspp_sheet_view_button_release (GtkWidget *widget,
2680 GdkEventButton *event)
2681 {
2682 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
2683
2684 pspp_sheet_view_stop_editing (tree_view, FALSE);
2685 if (tree_view->priv->rubber_band_status != RUBBER_BAND_ACTIVE
2686 && pspp_sheet_view_button_release_edit (tree_view, event))
2687 {
2688 if (tree_view->priv->pressed_button == event->button)
2689 tree_view->priv->pressed_button = -1;
2690
2691 tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
2692 return TRUE;
2693 }
2694
2695 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
2696 return pspp_sheet_view_button_release_drag_column (widget, event);
2697
2698 if (tree_view->priv->rubber_band_status)
2699 pspp_sheet_view_stop_rubber_band (tree_view);
2700
2701 if (tree_view->priv->pressed_button == event->button)
2702 tree_view->priv->pressed_button = -1;
2703
2704 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
2705 return pspp_sheet_view_button_release_column_resize (widget, event);
2706
2707 return FALSE;
2708 }
2709
2710 static gboolean
2711 pspp_sheet_view_grab_broken (GtkWidget *widget,
2712 GdkEventGrabBroken *event)
2713 {
2714 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
2715
2716 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
2717 pspp_sheet_view_button_release_drag_column (widget, (GdkEventButton *)event);
2718
2719 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
2720 pspp_sheet_view_button_release_column_resize (widget, (GdkEventButton *)event);
2721
2722 return TRUE;
2723 }
2724
2725 /* GtkWidget::motion_event function set.
2726 */
2727
2728 static void
2729 do_prelight (PsppSheetView *tree_view,
2730 int node,
2731 /* these are in bin_window coords */
2732 gint x,
2733 gint y)
2734 {
2735 int prev_node = tree_view->priv->prelight_node;
2736
2737 if (prev_node != node)
2738 {
2739 tree_view->priv->prelight_node = node;
2740
2741 if (prev_node >= 0)
2742 _pspp_sheet_view_queue_draw_node (tree_view, prev_node, NULL);
2743
2744 if (node >= 0)
2745 _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
2746 }
2747 }
2748
2749 static void
2750 prelight_or_select (PsppSheetView *tree_view,
2751 int node,
2752 /* these are in bin_window coords */
2753 gint x,
2754 gint y)
2755 {
2756 PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection);
2757
2758 if (tree_view->priv->hover_selection &&
2759 (mode == PSPP_SHEET_SELECTION_SINGLE || mode == PSPP_SHEET_SELECTION_BROWSE) &&
2760 !(tree_view->priv->edited_column &&
2761 tree_view->priv->edited_column->editable_widget))
2762 {
2763 if (node >= 0)
2764 {
2765 if (!pspp_sheet_view_node_is_selected (tree_view, node))
2766 {
2767 GtkTreePath *path;
2768
2769 path = _pspp_sheet_view_find_path (tree_view, node);
2770 pspp_sheet_selection_select_path (tree_view->priv->selection, path);
2771 if (pspp_sheet_view_node_is_selected (tree_view, node))
2772 {
2773 PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
2774 pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, FALSE);
2775 }
2776 gtk_tree_path_free (path);
2777 }
2778 }
2779
2780 else if (mode == PSPP_SHEET_SELECTION_SINGLE)
2781 pspp_sheet_selection_unselect_all (tree_view->priv->selection);
2782 }
2783
2784 do_prelight (tree_view, node, x, y);
2785 }
2786
2787 static void
2788 ensure_unprelighted (PsppSheetView *tree_view)
2789 {
2790 do_prelight (tree_view,
2791 -1,
2792 -1000, -1000); /* coords not possibly over an arrow */
2793
2794 g_assert (tree_view->priv->prelight_node < 0);
2795 }
2796
2797 static void
2798 update_prelight (PsppSheetView *tree_view,
2799 gint x,
2800 gint y)
2801 {
2802 int new_y;
2803 int node;
2804
2805 if (tree_view->priv->row_count == 0)
2806 return;
2807
2808 if (x == -10000)
2809 {
2810 ensure_unprelighted (tree_view);
2811 return;
2812 }
2813
2814 new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
2815 if (new_y < 0)
2816 new_y = 0;
2817
2818 pspp_sheet_view_find_offset (tree_view, new_y, &node);
2819
2820 if (node >= 0)
2821 prelight_or_select (tree_view, node, x, y);
2822 }
2823
2824
2825
2826
2827 /* Our motion arrow is either a box (in the case of the original spot)
2828 * or an arrow. It is expander_size wide.
2829 */
2830 /*
2831 * 11111111111111
2832 * 01111111111110
2833 * 00111111111100
2834 * 00011111111000
2835 * 00001111110000
2836 * 00000111100000
2837 * 00000111100000
2838 * 00000111100000
2839 * ~ ~ ~ ~ ~ ~ ~
2840 * 00000111100000
2841 * 00000111100000
2842 * 00000111100000
2843 * 00001111110000
2844 * 00011111111000
2845 * 00111111111100
2846 * 01111111111110
2847 * 11111111111111
2848 */
2849
2850 static void
2851 pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view)
2852 {
2853 PsppSheetViewColumnReorder *reorder = tree_view->priv->cur_reorder;
2854 GtkWidget *widget = GTK_WIDGET (tree_view);
2855 GdkBitmap *mask = NULL;
2856 gint x;
2857 gint y;
2858 gint width;
2859 gint height;
2860 gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
2861 GdkWindowAttr attributes;
2862 guint attributes_mask;
2863
2864 if (!reorder ||
2865 reorder->left_column == tree_view->priv->drag_column ||
2866 reorder->right_column == tree_view->priv->drag_column)
2867 arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
2868 else if (reorder->left_column || reorder->right_column)
2869 {
2870 GdkRectangle visible_rect;
2871 pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
2872 if (reorder->left_column)
2873 x = reorder->left_column->allocation.x + reorder->left_column->allocation.width;
2874 else
2875 x = reorder->right_column->allocation.x;
2876
2877 if (x < visible_rect.x)
2878 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
2879 else if (x > visible_rect.x + visible_rect.width)
2880 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
2881 else
2882 arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
2883 }
2884
2885 /* We want to draw the rectangle over the initial location. */
2886 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
2887 {
2888 GdkGC *gc;
2889 GdkColor col;
2890
2891 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
2892 {
2893 if (tree_view->priv->drag_highlight_window)
2894 {
2895 gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
2896 NULL);
2897 gdk_window_destroy (tree_view->priv->drag_highlight_window);
2898 }
2899
2900 attributes.window_type = GDK_WINDOW_CHILD;
2901 attributes.wclass = GDK_INPUT_OUTPUT;
2902 attributes.x = tree_view->priv->drag_column_x;
2903 attributes.y = 0;
2904 width = attributes.width = tree_view->priv->drag_column->allocation.width;
2905 height = attributes.height = tree_view->priv->drag_column->allocation.height;
2906 attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2907 attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2908 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2909 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2910 tree_view->priv->drag_highlight_window = gdk_window_new (tree_view->priv->header_window, &attributes, attributes_mask);
2911 gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2912
2913 mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2914 gc = gdk_gc_new (mask);
2915 col.pixel = 1;
2916 gdk_gc_set_foreground (gc, &col);
2917 gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2918 col.pixel = 0;
2919 gdk_gc_set_foreground(gc, &col);
2920 gdk_draw_rectangle (mask, gc, TRUE, 2, 2, width - 4, height - 4);
2921 g_object_unref (gc);
2922
2923 gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2924 mask, 0, 0);
2925 if (mask) g_object_unref (mask);
2926 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
2927 }
2928 }
2929 else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
2930 {
2931 gint i, j = 1;
2932 GdkGC *gc;
2933 GdkColor col;
2934
2935 width = tree_view->priv->expander_size;
2936
2937 /* Get x, y, width, height of arrow */
2938 gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
2939 if (reorder->left_column)
2940 {
2941 x += reorder->left_column->allocation.x + reorder->left_column->allocation.width - width/2;
2942 height = reorder->left_column->allocation.height;
2943 }
2944 else
2945 {
2946 x += reorder->right_column->allocation.x - width/2;
2947 height = reorder->right_column->allocation.height;
2948 }
2949 y -= tree_view->priv->expander_size/2; /* The arrow takes up only half the space */
2950 height += tree_view->priv->expander_size;
2951
2952 /* Create the new window */
2953 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
2954 {
2955 if (tree_view->priv->drag_highlight_window)
2956 {
2957 gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
2958 NULL);
2959 gdk_window_destroy (tree_view->priv->drag_highlight_window);
2960 }
2961
2962 attributes.window_type = GDK_WINDOW_TEMP;
2963 attributes.wclass = GDK_INPUT_OUTPUT;
2964 attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2965 attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2966 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2967 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2968 attributes.x = x;
2969 attributes.y = y;
2970 attributes.width = width;
2971 attributes.height = height;
2972 tree_view->priv->drag_highlight_window = gdk_window_new (gtk_widget_get_root_window (widget),
2973 &attributes, attributes_mask);
2974 gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2975
2976 mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2977 gc = gdk_gc_new (mask);
2978 col.pixel = 1;
2979 gdk_gc_set_foreground (gc, &col);
2980 gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2981
2982 /* Draw the 2 arrows as per above */
2983 col.pixel = 0;
2984 gdk_gc_set_foreground (gc, &col);
2985 for (i = 0; i < width; i ++)
2986 {
2987 if (i == (width/2 - 1))
2988 continue;
2989 gdk_draw_line (mask, gc, i, j, i, height - j);
2990 if (i < (width/2 - 1))
2991 j++;
2992 else
2993 j--;
2994 }
2995 g_object_unref (gc);
2996 gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2997 mask, 0, 0);
2998 if (mask) g_object_unref (mask);
2999 }
3000
3001 tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
3002 gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
3003 }
3004 else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
3005 arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3006 {
3007 gint i, j = 1;
3008 GdkGC *gc;
3009 GdkColor col;
3010
3011 width = tree_view->priv->expander_size;
3012
3013 /* Get x, y, width, height of arrow */
3014 width = width/2; /* remember, the arrow only takes half the available width */
3015 gdk_window_get_origin (widget->window, &x, &y);
3016 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3017 x += widget->allocation.width - width;
3018
3019 if (reorder->left_column)
3020 height = reorder->left_column->allocation.height;
3021 else
3022 height = reorder->right_column->allocation.height;
3023
3024 y -= tree_view->priv->expander_size;
3025 height += 2*tree_view->priv->expander_size;
3026
3027 /* Create the new window */
3028 if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
3029 tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
3030 {
3031 if (tree_view->priv->drag_highlight_window)
3032 {
3033 gdk_window_set_user_data (tree_view->priv->drag_highlight_window,
3034 NULL);
3035 gdk_window_destroy (tree_view->priv->drag_highlight_window);
3036 }
3037
3038 attributes.window_type = GDK_WINDOW_TEMP;
3039 attributes.wclass = GDK_INPUT_OUTPUT;
3040 attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
3041 attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
3042 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
3043 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
3044 attributes.x = x;
3045 attributes.y = y;
3046 attributes.width = width;
3047 attributes.height = height;
3048 tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
3049 gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
3050
3051 mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
3052 gc = gdk_gc_new (mask);
3053 col.pixel = 1;
3054 gdk_gc_set_foreground (gc, &col);
3055 gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
3056
3057 /* Draw the 2 arrows as per above */
3058 col.pixel = 0;
3059 gdk_gc_set_foreground (gc, &col);
3060 j = tree_view->priv->expander_size;
3061 for (i = 0; i < width; i ++)
3062 {
3063 gint k;
3064 if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
3065 k = width - i - 1;
3066 else
3067 k = i;
3068 gdk_draw_line (mask, gc, k, j, k, height - j);
3069 gdk_draw_line (mask, gc, k, 0, k, tree_view->priv->expander_size - j);
3070 gdk_draw_line (mask, gc, k, height, k, height - tree_view->priv->expander_size + j);
3071 j--;
3072 }
3073 g_object_unref (gc);
3074 gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
3075 mask, 0, 0);
3076 if (mask) g_object_unref (mask);
3077 }
3078
3079 tree_view->priv->drag_column_window_state = arrow_type;
3080 gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
3081 }
3082 else
3083 {
3084 g_warning (G_STRLOC"Invalid PsppSheetViewColumnReorder struct");
3085 gdk_window_hide (tree_view->priv->drag_highlight_window);
3086 return;
3087 }
3088
3089 gdk_window_show (tree_view->priv->drag_highlight_window);
3090 gdk_window_raise (tree_view->priv->drag_highlight_window);
3091 }
3092
3093 static gboolean
3094 pspp_sheet_view_motion_resize_column (GtkWidget *widget,
3095 GdkEventMotion *event)
3096 {
3097 gint x;
3098 gint new_width;
3099 PsppSheetViewColumn *column;
3100 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
3101
3102 column = pspp_sheet_view_get_column (tree_view, tree_view->priv->drag_pos);
3103
3104 if (event->is_hint || event->window != widget->window)
3105 gtk_widget_get_pointer (widget, &x, NULL);
3106 else
3107 x = event->x;
3108
3109 if (tree_view->priv->hadjustment)
3110 x += tree_view->priv->hadjustment->value;
3111
3112 new_width = pspp_sheet_view_new_column_width (tree_view,
3113 tree_view->priv->drag_pos, &x);
3114 if (x != tree_view->priv->x_drag &&
3115 (new_width != column->fixed_width))
3116 {
3117 column->use_resized_width = TRUE;
3118 column->resized_width = new_width;
3119 #if 0
3120 if (column->expand)
3121 column->resized_width -= tree_view->priv->last_extra_space_per_column;
3122 #endif
3123 gtk_widget_queue_resize (widget);
3124 }
3125
3126 return FALSE;
3127 }
3128
3129
3130 static void
3131 pspp_sheet_view_update_current_reorder (PsppSheetView *tree_view)
3132 {
3133 PsppSheetViewColumnReorder *reorder = NULL;
3134 GList *list;
3135 gint mouse_x;
3136
3137 gdk_window_get_pointer (tree_view->priv->header_window, &mouse_x, NULL, NULL);
3138 for (list = tree_view->priv->column_drag_info; list; list = list->next)
3139 {
3140 reorder = (PsppSheetViewColumnReorder *) list->data;
3141 if (mouse_x >= reorder->left_align && mouse_x < reorder->right_align)
3142 break;
3143 reorder = NULL;
3144 }
3145
3146 /* if (reorder && reorder == tree_view->priv->cur_reorder)
3147 return;*/
3148
3149 tree_view->priv->cur_reorder = reorder;
3150 pspp_sheet_view_motion_draw_column_motion_arrow (tree_view);
3151 }
3152
3153 static void
3154 pspp_sheet_view_vertical_autoscroll (PsppSheetView *tree_view)
3155 {
3156 GdkRectangle visible_rect;
3157 gint y;
3158 gint offset;
3159 gfloat value;
3160
3161 gdk_window_get_pointer (tree_view->priv->bin_window, NULL, &y, NULL);
3162 y += tree_view->priv->dy;
3163
3164 pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
3165
3166 /* see if we are near the edge. */
3167 offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE);
3168 if (offset > 0)
3169 {
3170 offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE);
3171 if (offset < 0)
3172 return;
3173 }
3174
3175 value = CLAMP (tree_view->priv->vadjustment->value + offset, 0.0,
3176 tree_view->priv->vadjustment->upper - tree_view->priv->vadjustment->page_size);
3177 gtk_adjustment_set_value (tree_view->priv->vadjustment, value);
3178 }
3179
3180 static gboolean
3181 pspp_sheet_view_horizontal_autoscroll (PsppSheetView *tree_view)
3182 {
3183 GdkRectangle visible_rect;
3184 gint x;
3185 gint offset;
3186 gfloat value;
3187
3188 gdk_window_get_pointer (tree_view->priv->bin_window, &x, NULL, NULL);
3189
3190 pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
3191
3192 /* See if we are near the edge. */
3193 offset = x - (visible_rect.x + SCROLL_EDGE_SIZE);
3194 if (offset > 0)
3195 {
3196 offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE);
3197 if (offset < 0)
3198 return TRUE;
3199 }
3200 offset = offset/3;
3201
3202 value = CLAMP (tree_view->priv->hadjustment->value + offset,
3203 0.0, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size);
3204 gtk_adjustment_set_value (tree_view->priv->hadjustment, value);
3205
3206 return TRUE;
3207
3208 }
3209
3210 static gboolean
3211 pspp_sheet_view_motion_drag_column (GtkWidget *widget,
3212 GdkEventMotion *event)
3213 {
3214 PsppSheetView *tree_view = (PsppSheetView *) widget;
3215 PsppSheetViewColumn *column = tree_view->priv->drag_column;
3216 gint x, y;
3217
3218 /* Sanity Check */
3219 if ((column == NULL) ||
3220 (event->window != tree_view->priv->drag_window))
3221 return FALSE;
3222
3223 /* Handle moving the header */
3224 gdk_window_get_position (tree_view->priv->drag_window, &x, &y);
3225 x = CLAMP (x + (gint)event->x - column->drag_x, 0,
3226 MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->allocation.width);
3227 gdk_window_move (tree_view->priv->drag_window, x, y);
3228
3229 /* autoscroll, if needed */
3230 pspp_sheet_view_horizontal_autoscroll (tree_view);
3231 /* Update the current reorder position and arrow; */
3232 pspp_sheet_view_update_current_reorder (tree_view);
3233
3234 return TRUE;
3235 }
3236
3237 static void
3238 pspp_sheet_view_stop_rubber_band (PsppSheetView *tree_view)
3239 {
3240 remove_scroll_timeout (tree_view);
3241 gtk_grab_remove (GTK_WIDGET (tree_view));
3242
3243 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
3244 {
3245 GtkTreePath *tmp_path;
3246
3247 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3248
3249 /* The anchor path should be set to the start path */
3250 tmp_path = _pspp_sheet_view_find_path (tree_view,
3251 tree_view->priv->rubber_band_start_node);
3252
3253 if (tree_view->priv->anchor)
3254 gtk_tree_row_reference_free (tree_view->priv->anchor);
3255
3256 tree_view->priv->anchor =
3257 gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
3258 tree_view->priv->model,
3259 tmp_path);
3260
3261 gtk_tree_path_free (tmp_path);
3262
3263 /* ... and the cursor to the end path */
3264 tmp_path = _pspp_sheet_view_find_path (tree_view,
3265 tree_view->priv->rubber_band_end_node);
3266 pspp_sheet_view_real_set_cursor (PSPP_SHEET_VIEW (tree_view), tmp_path, FALSE, FALSE);
3267 gtk_tree_path_free (tmp_path);
3268
3269 _pspp_sheet_selection_emit_changed (tree_view->priv->selection);
3270 }
3271
3272 /* Clear status variables */
3273 tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
3274 tree_view->priv->rubber_band_shift = 0;
3275 tree_view->priv->rubber_band_ctrl = 0;
3276
3277 tree_view->priv->rubber_band_start_node = -1;
3278 tree_view->priv->rubber_band_end_node = -1;
3279 }
3280
3281 static void
3282 pspp_sheet_view_update_rubber_band_selection_range (PsppSheetView *tree_view,
3283 int start_node,
3284 int end_node,
3285 gboolean select,
3286 gboolean skip_start,
3287 gboolean skip_end)
3288 {
3289 if (start_node == end_node)
3290 return;
3291
3292 /* We skip the first node and jump inside the loop */
3293 if (skip_start)
3294 goto skip_first;
3295
3296 do
3297 {
3298 /* Small optimization by assuming insensitive nodes are never
3299 * selected.
3300 */
3301 if (select)
3302 {
3303 if (tree_view->priv->rubber_band_shift)
3304 pspp_sheet_view_node_select (tree_view, start_node);
3305 else if (tree_view->priv->rubber_band_ctrl)
3306 {
3307 /* Toggle the selection state */
3308 if (pspp_sheet_view_node_is_selected (tree_view, start_node))
3309 pspp_sheet_view_node_unselect (tree_view, start_node);
3310 else
3311 pspp_sheet_view_node_select (tree_view, start_node);
3312 }
3313 else
3314 pspp_sheet_view_node_select (tree_view, start_node);
3315 }
3316 else
3317 {
3318 /* Mirror the above */
3319 if (tree_view->priv->rubber_band_shift)
3320 pspp_sheet_view_node_unselect (tree_view, start_node);
3321 else if (tree_view->priv->rubber_band_ctrl)
3322 {
3323 /* Toggle the selection state */
3324 if (pspp_sheet_view_node_is_selected (tree_view, start_node))
3325 pspp_sheet_view_node_unselect (tree_view, start_node);
3326 else
3327 pspp_sheet_view_node_select (tree_view, start_node);
3328 }
3329 else
3330 pspp_sheet_view_node_unselect (tree_view, start_node);
3331 }
3332
3333 _pspp_sheet_view_queue_draw_node (tree_view, start_node, NULL);
3334
3335 if (start_node == end_node)
3336 break;
3337
3338 skip_first:
3339
3340 start_node = pspp_sheet_view_node_next (tree_view, start_node);
3341
3342 if (start_node < 0)
3343 /* Ran out of tree */
3344 break;
3345
3346 if (skip_end && start_node == end_node)
3347 break;
3348 }
3349 while (TRUE);
3350 }
3351
3352 static gint
3353 pspp_sheet_view_node_find_offset (PsppSheetView *tree_view,
3354 int node)
3355 {
3356 return node * tree_view->priv->fixed_height;
3357 }
3358
3359 static gint
3360 pspp_sheet_view_find_offset (PsppSheetView *tree_view,
3361 gint height,
3362 int *new_node)
3363 {
3364 int fixed_height = tree_view->priv->fixed_height;
3365 if (fixed_height <= 0
3366 || height < 0
3367 || height >= tree_view->priv->row_count * fixed_height)
3368 {
3369 *new_node = -1;
3370 return 0;
3371 }
3372 else
3373 {
3374 *new_node = height / fixed_height;
3375 return height % fixed_height;
3376 }
3377 }
3378
3379 static void
3380 pspp_sheet_view_update_rubber_band_selection (PsppSheetView *tree_view)
3381 {
3382 int start_node;
3383 int end_node;
3384
3385 pspp_sheet_view_find_offset (tree_view, MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &start_node);
3386 pspp_sheet_view_find_offset (tree_view, MAX (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &end_node);
3387
3388 /* Handle the start area first */
3389 if (tree_view->priv->rubber_band_start_node < 0)
3390 {
3391 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3392 start_node,
3393 end_node,
3394 TRUE,
3395 FALSE,
3396 FALSE);
3397 }
3398 else if (start_node < tree_view->priv->rubber_band_start_node)
3399 {
3400 /* New node is above the old one; selection became bigger */
3401 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3402 start_node,
3403 tree_view->priv->rubber_band_start_node,
3404 TRUE,
3405 FALSE,
3406 TRUE);
3407 }
3408 else if (start_node > tree_view->priv->rubber_band_start_node)
3409 {
3410 /* New node is below the old one; selection became smaller */
3411 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3412 tree_view->priv->rubber_band_start_node,
3413 start_node,
3414 FALSE,
3415 FALSE,
3416 TRUE);
3417 }
3418
3419 tree_view->priv->rubber_band_start_node = start_node;
3420
3421 /* Next, handle the end area */
3422 if (tree_view->priv->rubber_band_end_node < 0)
3423 {
3424 /* In the event this happens, start_node was also -1; this case is
3425 * handled above.
3426 */
3427 }
3428 else if (end_node < 0)
3429 {
3430 /* Find the last node in the tree */
3431 pspp_sheet_view_find_offset (tree_view, tree_view->priv->height - 1,
3432 &end_node);
3433
3434 /* Selection reached end of the tree */
3435 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3436 tree_view->priv->rubber_band_end_node,
3437 end_node,
3438 TRUE,
3439 TRUE,
3440 FALSE);
3441 }
3442 else if (end_node > tree_view->priv->rubber_band_end_node)
3443 {
3444 /* New node is below the old one; selection became bigger */
3445 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3446 tree_view->priv->rubber_band_end_node,
3447 end_node,
3448 TRUE,
3449 TRUE,
3450 FALSE);
3451 }
3452 else if (end_node < tree_view->priv->rubber_band_end_node)
3453 {
3454 /* New node is above the old one; selection became smaller */
3455 pspp_sheet_view_update_rubber_band_selection_range (tree_view,
3456 end_node,
3457 tree_view->priv->rubber_band_end_node,
3458 FALSE,
3459 TRUE,
3460 FALSE);
3461 }
3462
3463 tree_view->priv->rubber_band_end_node = end_node;
3464 }
3465
3466 static void
3467 pspp_sheet_view_update_rubber_band (PsppSheetView *tree_view)
3468 {
3469 gint x, y;
3470 GdkRectangle old_area;
3471 GdkRectangle new_area;
3472 GdkRectangle common;
3473 GdkRegion *invalid_region;
3474 PsppSheetViewColumn *column;
3475
3476 old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
3477 old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
3478 old_area.width = ABS (tree_view->priv->rubber_band_x - tree_view->priv->press_start_x) + 1;
3479 old_area.height = ABS (tree_view->priv->rubber_band_y - tree_view->priv->press_start_y) + 1;
3480
3481 gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, NULL);
3482
3483 x = MAX (x, 0);
3484 y = MAX (y, 0) + tree_view->priv->dy;
3485
3486 new_area.x = MIN (tree_view->priv->press_start_x, x);
3487 new_area.y = MIN (tree_view->priv->press_start_y, y) - tree_view->priv->dy;
3488 new_area.width = ABS (x - tree_view->priv->press_start_x) + 1;
3489 new_area.height = ABS (y - tree_view->priv->press_start_y) + 1;
3490
3491 invalid_region = gdk_region_rectangle (&old_area);
3492 gdk_region_union_with_rect (invalid_region, &new_area);
3493
3494 gdk_rectangle_intersect (&old_area, &new_area, &common);
3495 if (common.width > 2 && common.height > 2)
3496 {
3497 GdkRegion *common_region;
3498
3499 /* make sure the border is invalidated */
3500 common.x += 1;
3501 common.y += 1;
3502 common.width -= 2;
3503 common.height -= 2;
3504
3505 common_region = gdk_region_rectangle (&common);
3506
3507 gdk_region_subtract (invalid_region, common_region);
3508 gdk_region_destroy (common_region);
3509 }
3510
3511 gdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE);
3512
3513 gdk_region_destroy (invalid_region);
3514
3515 tree_view->priv->rubber_band_x = x;
3516 tree_view->priv->rubber_band_y = y;
3517 pspp_sheet_view_get_path_at_pos (tree_view, x, y, NULL, &column, NULL, NULL);
3518
3519 pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
3520 pspp_sheet_selection_select_column_range (tree_view->priv->selection,
3521 tree_view->priv->anchor_column,
3522 column);
3523
3524 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3525
3526 pspp_sheet_view_update_rubber_band_selection (tree_view);
3527 }
3528
3529 static void
3530 pspp_sheet_view_paint_rubber_band (PsppSheetView *tree_view,
3531 GdkRectangle *area)
3532 {
3533 cairo_t *cr;
3534 GdkRectangle rect;
3535 GdkRectangle rubber_rect;
3536
3537 return;
3538 rubber_rect.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
3539 rubber_rect.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
3540 rubber_rect.width = ABS (tree_view->priv->press_start_x - tree_view->priv->rubber_band_x) + 1;
3541 rubber_rect.height = ABS (tree_view->priv->press_start_y - tree_view->priv->rubber_band_y) + 1;
3542
3543 if (!gdk_rectangle_intersect (&rubber_rect, area, &rect))
3544 return;
3545
3546 cr = gdk_cairo_create (tree_view->priv->bin_window);
3547 cairo_set_line_width (cr, 1.0);
3548
3549 cairo_set_source_rgba (cr,
3550 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].red / 65535.,
3551 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].green / 65535.,
3552 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].blue / 65535.,
3553 .25);
3554
3555 gdk_cairo_rectangle (cr, &rect);
3556 cairo_clip (cr);
3557 cairo_paint (cr);
3558
3559 cairo_set_source_rgb (cr,
3560 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].red / 65535.,
3561 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].green / 65535.,
3562 GTK_WIDGET (tree_view)->style->fg[GTK_STATE_NORMAL].blue / 65535.);
3563
3564 cairo_rectangle (cr,
3565 rubber_rect.x + 0.5, rubber_rect.y + 0.5,
3566 rubber_rect.width - 1, rubber_rect.height - 1);
3567 cairo_stroke (cr);
3568
3569 cairo_destroy (cr);
3570 }
3571
3572 static gboolean
3573 pspp_sheet_view_motion_bin_window (GtkWidget *widget,
3574 GdkEventMotion *event)
3575 {
3576 PsppSheetView *tree_view;
3577 int node;
3578 gint new_y;
3579
3580 tree_view = (PsppSheetView *) widget;
3581
3582 if (tree_view->priv->row_count == 0)
3583 return FALSE;
3584
3585 if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
3586 {
3587 GdkRectangle background_area, cell_area;
3588 PsppSheetViewColumn *column;
3589
3590 if (find_click (tree_view, event->x, event->y, &node, &column,
3591 &background_area, &cell_area)
3592 && tree_view->priv->focus_column == column
3593 && tree_view->priv->press_start_node == node)
3594 return FALSE;
3595
3596 gtk_grab_add (GTK_WIDGET (tree_view));
3597 pspp_sheet_view_update_rubber_band (tree_view);
3598
3599 tree_view->priv->rubber_band_status = RUBBER_BAND_ACTIVE;
3600 }
3601 else if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
3602 {
3603 pspp_sheet_view_update_rubber_band (tree_view);
3604
3605 add_scroll_timeout (tree_view);
3606 }
3607
3608 /* only check for an initiated drag when a button is pressed */
3609 if (tree_view->priv->pressed_button >= 0
3610 && !tree_view->priv->rubber_band_status)
3611 pspp_sheet_view_maybe_begin_dragging_row (tree_view, event);
3612
3613 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
3614 if (new_y < 0)
3615 new_y = 0;
3616
3617 pspp_sheet_view_find_offset (tree_view, new_y, &node);
3618
3619 tree_view->priv->event_last_x = event->x;
3620 tree_view->priv->event_last_y = event->y;
3621
3622 prelight_or_select (tree_view, node, event->x, event->y);
3623
3624 return TRUE;
3625 }
3626
3627 static gboolean
3628 pspp_sheet_view_motion (GtkWidget *widget,
3629 GdkEventMotion *event)
3630 {
3631 PsppSheetView *tree_view;
3632
3633 tree_view = (PsppSheetView *) widget;
3634
3635 /* Resizing a column */
3636 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
3637 return pspp_sheet_view_motion_resize_column (widget, event);
3638
3639 /* Drag column */
3640 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
3641 return pspp_sheet_view_motion_drag_column (widget, event);
3642
3643 /* Sanity check it */
3644 if (event->window == tree_view->priv->bin_window)
3645 return pspp_sheet_view_motion_bin_window (widget, event);
3646
3647 return FALSE;
3648 }
3649
3650 /* Invalidate the focus rectangle near the edge of the bin_window; used when
3651 * the tree is empty.
3652 */
3653 static void
3654 invalidate_empty_focus (PsppSheetView *tree_view)
3655 {
3656 GdkRectangle area;
3657
3658 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
3659 return;
3660
3661 area.x = 0;
3662 area.y = 0;
3663 gdk_drawable_get_size (tree_view->priv->bin_window, &area.width, &area.height);
3664 gdk_window_invalidate_rect (tree_view->priv->bin_window, &area, FALSE);
3665 }
3666
3667 /* Draws a focus rectangle near the edge of the bin_window; used when the tree
3668 * is empty.
3669 */
3670 static void
3671 draw_empty_focus (PsppSheetView *tree_view, GdkRectangle *clip_area)
3672 {
3673 GtkWidget *widget = GTK_WIDGET (tree_view);
3674 gint w, h;
3675
3676 if (!gtk_widget_has_focus (widget))
3677 return;
3678
3679 gdk_drawable_get_size (tree_view->priv->bin_window, &w, &h);
3680
3681 w -= 2;
3682 h -= 2;
3683
3684 if (w > 0 && h > 0)
3685 gtk_paint_focus (gtk_widget_get_style (widget),
3686 tree_view->priv->bin_window,
3687 gtk_widget_get_state (widget),
3688 clip_area,
3689 widget,
3690 NULL,
3691 1, 1, w, h);
3692 }
3693
3694 static void
3695 pspp_sheet_view_draw_grid_lines (PsppSheetView *tree_view,
3696 GdkEventExpose *event,
3697 gint n_visible_columns,
3698 gint min_y,
3699 gint max_y)
3700 {
3701 GList *list = tree_view->priv->columns;
3702 gint i = 0;
3703 gint current_x = 0;
3704 gint height;
3705
3706 if (tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
3707 && tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_BOTH)
3708 return;
3709
3710 gdk_drawable_get_size (event->window, NULL, &height);
3711
3712 /* Only draw the lines for visible rows and columns */
3713 for (list = tree_view->priv->columns; list; list = list->next, i++)
3714 {
3715 PsppSheetViewColumn *column = list->data;
3716
3717 /* We don't want a line for the last column */
3718 if (i == n_visible_columns - 1)
3719 break;
3720
3721 if (! column->visible)
3722 continue;
3723
3724 current_x += column->width;
3725
3726 if (current_x - 1 >= event->area.x
3727 && current_x - 1 < event->area.x + event->area.width)
3728 gdk_draw_line (event->window,
3729 tree_view->priv->grid_line_gc,
3730 current_x - 1, min_y,
3731 current_x - 1, max_y - min_y);
3732 }
3733 }
3734
3735 /* Warning: Very scary function.
3736 * Modify at your own risk
3737 *
3738 * KEEP IN SYNC WITH pspp_sheet_view_create_row_drag_icon()!
3739 * FIXME: It's not...
3740 */
3741 static gboolean
3742 pspp_sheet_view_bin_expose (GtkWidget *widget,
3743 GdkEventExpose *event)
3744 {
3745 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
3746 GtkTreePath *path;
3747 GList *list;
3748 int node;
3749 int cursor = -1;
3750 int drag_highlight = -1;
3751 GtkTreeIter iter;
3752 gint new_y;
3753 gint y_offset, cell_offset;
3754 gint max_height;
3755 gint depth;
3756 GdkRectangle background_area;
3757 GdkRectangle cell_area;
3758 guint flags;
3759 gint bin_window_width;
3760 gint bin_window_height;
3761 GtkTreePath *cursor_path;
3762 GtkTreePath *drag_dest_path;
3763 GList *first_column, *last_column;
3764 gint vertical_separator;
3765 gint horizontal_separator;
3766 gint focus_line_width;
3767 gboolean allow_rules;
3768 gboolean has_special_cell;
3769 gboolean rtl;
3770 gint n_visible_columns;
3771 gint grid_line_width;
3772 gboolean row_ending_details;
3773 gboolean draw_vgrid_lines, draw_hgrid_lines;
3774 gint min_y, max_y;
3775
3776 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
3777
3778 gtk_widget_style_get (widget,
3779 "horizontal-separator", &horizontal_separator,
3780 "vertical-separator", &vertical_separator,
3781 "allow-rules", &allow_rules,
3782 "focus-line-width", &focus_line_width,
3783 "row-ending-details", &row_ending_details,
3784 NULL);
3785
3786 if (tree_view->priv->row_count == 0)
3787 {
3788 draw_empty_focus (tree_view, &event->area);
3789 return TRUE;
3790 }
3791
3792 /* clip event->area to the visible area */
3793 if (event->area.height < 0)
3794 return TRUE;
3795
3796 validate_visible_area (tree_view);
3797
3798 new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, event->area.y);
3799
3800 if (new_y < 0)
3801 new_y = 0;
3802 y_offset = -pspp_sheet_view_find_offset (tree_view, new_y, &node);
3803 gdk_drawable_get_size (tree_view->priv->bin_window,
3804 &bin_window_width, &bin_window_height);
3805
3806 if (tree_view->priv->height < bin_window_height)
3807 {
3808 gtk_paint_flat_box (widget->style,
3809 event->window,
3810 widget->state,
3811 GTK_SHADOW_NONE,
3812 &event->area,
3813 widget,
3814 "cell_even",
3815 0, tree_view->priv->height,
3816 bin_window_width,
3817 bin_window_height - tree_view->priv->height);
3818 }
3819
3820 if (node < 0)
3821 return TRUE;
3822
3823 /* find the path for the node */
3824 path = _pspp_sheet_view_find_path ((PsppSheetView *)widget, node);
3825 gtk_tree_model_get_iter (tree_view->priv->model,
3826 &iter,
3827 path);
3828 depth = gtk_tree_path_get_depth (path);
3829 gtk_tree_path_free (path);
3830
3831 cursor_path = NULL;
3832 drag_dest_path = NULL;
3833
3834 if (tree_view->priv->cursor)
3835 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
3836
3837 if (cursor_path)
3838 _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor);
3839
3840 if (tree_view->priv->drag_dest_row)
3841 drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
3842
3843 if (drag_dest_path)
3844 _pspp_sheet_view_find_node (tree_view, drag_dest_path,
3845 &drag_highlight);
3846
3847 draw_vgrid_lines =
3848 tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
3849 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
3850 draw_hgrid_lines =
3851 tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
3852 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
3853
3854 if (draw_vgrid_lines || draw_hgrid_lines)
3855 gtk_widget_style_get (widget, "grid-line-width", &grid_line_width, NULL);
3856
3857 n_visible_columns = 0;
3858 for (list = tree_view->priv->columns; list; list = list->next)
3859 {
3860 if (! PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
3861 continue;
3862 n_visible_columns ++;
3863 }
3864
3865 /* Find the last column */
3866 for (last_column = g_list_last (tree_view->priv->columns);
3867 last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
3868 last_column = last_column->prev)
3869 ;
3870
3871 /* and the first */
3872 for (first_column = g_list_first (tree_view->priv->columns);
3873 first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
3874 first_column = first_column->next)
3875 ;
3876
3877 /* Actually process the expose event. To do this, we want to
3878 * start at the first node of the event, and walk the tree in
3879 * order, drawing each successive node.
3880 */
3881
3882 min_y = y_offset;
3883 do
3884 {
3885 gboolean parity;
3886 gboolean is_first = FALSE;
3887 gboolean is_last = FALSE;
3888 gboolean done = FALSE;
3889 gboolean selected;
3890
3891 max_height = ROW_HEIGHT (tree_view);
3892
3893 cell_offset = 0;
3894
3895 background_area.y = y_offset + event->area.y;
3896 background_area.height = max_height;
3897 max_y = background_area.y + max_height;
3898
3899 flags = 0;
3900
3901 if (node == tree_view->priv->prelight_node)
3902 flags |= GTK_CELL_RENDERER_PRELIT;
3903
3904 selected = pspp_sheet_view_node_is_selected (tree_view, node);
3905
3906 parity = node % 2;
3907
3908 if (tree_view->priv->special_cells == PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT)
3909 {
3910 /* we *need* to set cell data on all cells before the call
3911 * to _has_special_cell, else _has_special_cell() does not
3912 * return a correct value.
3913 */
3914 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
3915 list;
3916 list = (rtl ? list->prev : list->next))
3917 {
3918 PsppSheetViewColumn *column = list->data;
3919 pspp_sheet_view_column_cell_set_cell_data (column,
3920 tree_view->priv->model,
3921 &iter);
3922 }
3923
3924 has_special_cell = pspp_sheet_view_has_special_cell (tree_view);
3925 }
3926 else
3927 has_special_cell = tree_view->priv->special_cells == PSPP_SHEET_VIEW_SPECIAL_CELLS_YES;
3928
3929 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
3930 list;
3931 list = (rtl ? list->prev : list->next))
3932 {
3933 PsppSheetViewColumn *column = list->data;
3934 const gchar *detail = NULL;
3935 gboolean selected_column;
3936 GtkStateType state;
3937
3938 if (!column->visible)
3939 continue;
3940
3941 if (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
3942 selected_column = column->selected && column->selectable;
3943 else
3944 selected_column = TRUE;
3945
3946 if (cell_offset > event->area.x + event->area.width ||
3947 cell_offset + column->width < event->area.x)
3948 {
3949 cell_offset += column->width;
3950 continue;
3951 }
3952
3953 if (selected && selected_column)
3954 flags |= GTK_CELL_RENDERER_SELECTED;
3955 else
3956 flags &= ~GTK_CELL_RENDERER_SELECTED;
3957
3958 if (column->show_sort_indicator)
3959 flags |= GTK_CELL_RENDERER_SORTED;
3960 else
3961 flags &= ~GTK_CELL_RENDERER_SORTED;
3962
3963 if (cursor == node)
3964 flags |= GTK_CELL_RENDERER_FOCUSED;
3965 else
3966 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3967
3968 background_area.x = cell_offset;
3969 background_area.width = column->width;
3970
3971 cell_area = background_area;
3972 cell_area.y += vertical_separator / 2;
3973 cell_area.x += horizontal_separator / 2;
3974 cell_area.height -= vertical_separator;
3975 cell_area.width -= horizontal_separator;
3976
3977 if (draw_vgrid_lines)
3978 {
3979 if (list == first_column)
3980 {
3981 cell_area.width -= grid_line_width / 2;
3982 }
3983 else if (list == last_column)
3984 {
3985 cell_area.x += grid_line_width / 2;
3986 cell_area.width -= grid_line_width / 2;
3987 }
3988 else
3989 {
3990 cell_area.x += grid_line_width / 2;
3991 cell_area.width -= grid_line_width;
3992 }
3993 }
3994
3995 if (draw_hgrid_lines)
3996 {
3997 cell_area.y += grid_line_width / 2;
3998 cell_area.height -= grid_line_width;
3999 }
4000
4001 if (gdk_region_rect_in (event->region, &background_area) == GDK_OVERLAP_RECTANGLE_OUT)
4002 {
4003 cell_offset += column->width;
4004 continue;
4005 }
4006
4007 pspp_sheet_view_column_cell_set_cell_data (column,
4008 tree_view->priv->model,
4009 &iter);
4010
4011 /* Select the detail for drawing the cell. relevant
4012 * factors are parity, sortedness, and whether to
4013 * display rules.
4014 */
4015 if (allow_rules && tree_view->priv->has_rules)
4016 {
4017 if ((flags & GTK_CELL_RENDERER_SORTED) &&
4018 n_visible_columns >= 3)
4019 {
4020 if (parity)
4021 detail = "cell_odd_ruled_sorted";
4022 else
4023 detail = "cell_even_ruled_sorted";
4024 }
4025 else
4026 {
4027 if (parity)
4028 detail = "cell_odd_ruled";
4029 else
4030 detail = "cell_even_ruled";
4031 }
4032 }
4033 else
4034 {
4035 if ((flags & GTK_CELL_RENDERER_SORTED) &&
4036 n_visible_columns >= 3)
4037 {
4038 if (parity)
4039 detail = "cell_odd_sorted";
4040 else
4041 detail = "cell_even_sorted";
4042 }
4043 else
4044 {
4045 if (parity)
4046 detail = "cell_odd";
4047 else
4048 detail = "cell_even";
4049 }
4050 }
4051
4052 g_assert (detail);
4053
4054 if (widget->state == GTK_STATE_INSENSITIVE)
4055 state = GTK_STATE_INSENSITIVE;
4056 else if (flags & GTK_CELL_RENDERER_SELECTED)
4057 state = GTK_STATE_SELECTED;
4058 else
4059 state = GTK_STATE_NORMAL;
4060
4061 /* Draw background */
4062 if (row_ending_details)
4063 {
4064 char new_detail[128];
4065
4066 is_first = (rtl ? !list->next : !list->prev);
4067 is_last = (rtl ? !list->prev : !list->next);
4068
4069 /* (I don't like the snprintfs either, but couldn't find a
4070 * less messy way).
4071 */
4072 if (is_first && is_last)
4073 g_snprintf (new_detail, 127, "%s", detail);
4074 else if (is_first)
4075 g_snprintf (new_detail, 127, "%s_start", detail);
4076 else if (is_last)
4077 g_snprintf (new_detail, 127, "%s_end", detail);
4078 else
4079 g_snprintf (new_detail, 128, "%s_middle", detail);
4080
4081 gtk_paint_flat_box (widget->style,
4082 event->window,
4083 state,
4084 GTK_SHADOW_NONE,
4085 &event->area,
4086 widget,
4087 new_detail,
4088 background_area.x,
4089 background_area.y,
4090 background_area.width,
4091 background_area.height);
4092 }
4093 else
4094 {
4095 gtk_paint_flat_box (widget->style,
4096 event->window,
4097 state,
4098 GTK_SHADOW_NONE,
4099 &event->area,
4100 widget,
4101 detail,
4102 background_area.x,
4103 background_area.y,
4104 background_area.width,
4105 background_area.height);
4106 }
4107
4108 if (draw_hgrid_lines)
4109 {
4110 if (background_area.y > 0)
4111 gdk_draw_line (event->window,
4112 tree_view->priv->grid_line_gc,
4113 background_area.x, background_area.y,
4114 background_area.x + background_area.width,
4115 background_area.y);
4116
4117 if (y_offset + max_height >= event->area.height)
4118 gdk_draw_line (event->window,
4119 tree_view->priv->grid_line_gc,
4120 background_area.x, background_area.y + max_height,
4121 background_area.x + background_area.width,
4122 background_area.y + max_height);
4123 }
4124
4125 _pspp_sheet_view_column_cell_render (column,
4126 event->window,
4127 &background_area,
4128 &cell_area,
4129 &event->area,
4130 flags);
4131
4132 if (node == cursor && has_special_cell &&
4133 ((column == tree_view->priv->focus_column &&
4134 PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS) &&
4135 gtk_widget_has_focus (widget)) ||
4136 (column == tree_view->priv->edited_column)))
4137 {
4138 _pspp_sheet_view_column_cell_draw_focus (column,
4139 event->window,
4140 &background_area,
4141 &cell_area,
4142 &event->area,
4143 flags);
4144 }
4145
4146 cell_offset += column->width;
4147 }
4148
4149 if (cell_offset < event->area.x)
4150 {
4151 gtk_paint_flat_box (widget->style,
4152 event->window,
4153 GTK_STATE_NORMAL,
4154 GTK_SHADOW_NONE,
4155 &event->area,
4156 widget,
4157 "base",
4158 cell_offset,
4159 background_area.y,
4160 event->area.x - cell_offset,
4161 background_area.height);
4162 }
4163
4164 if (node == drag_highlight)
4165 {
4166 /* Draw indicator for the drop
4167 */
4168 gint highlight_y = -1;
4169 int node = -1;
4170 gint width;
4171
4172 switch (tree_view->priv->drag_dest_pos)
4173 {
4174 case PSPP_SHEET_VIEW_DROP_BEFORE:
4175 highlight_y = background_area.y - 1;
4176 if (highlight_y < 0)
4177 highlight_y = 0;
4178 break;
4179
4180 case PSPP_SHEET_VIEW_DROP_AFTER:
4181 highlight_y = background_area.y + background_area.height - 1;
4182 break;
4183
4184 case PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE:
4185 case PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER:
4186 _pspp_sheet_view_find_node (tree_view, drag_dest_path, &node);
4187
4188 if (node < 0)
4189 break;
4190 gdk_drawable_get_size (tree_view->priv->bin_window,
4191 &width, NULL);
4192
4193 if (row_ending_details)
4194 gtk_paint_focus (widget->style,
4195 tree_view->priv->bin_window,
4196 gtk_widget_get_state (widget),
4197 &event->area,
4198 widget,
4199 (is_first
4200 ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
4201 : (is_last ? "treeview-drop-indicator-right" : "tree-view-drop-indicator-middle" )),
4202 0, BACKGROUND_FIRST_PIXEL (tree_view, node)
4203 - focus_line_width / 2,
4204 width, ROW_HEIGHT (tree_view)
4205 - focus_line_width + 1);
4206 else
4207 gtk_paint_focus (widget->style,
4208 tree_view->priv->bin_window,
4209 gtk_widget_get_state (widget),
4210 &event->area,
4211 widget,
4212 "treeview-drop-indicator",
4213 0, BACKGROUND_FIRST_PIXEL (tree_view, node)
4214 - focus_line_width / 2,
4215 width, ROW_HEIGHT (tree_view)
4216 - focus_line_width + 1);
4217 break;
4218 }
4219
4220 if (highlight_y >= 0)
4221 {
4222 gdk_draw_line (event->window,
4223 widget->style->fg_gc[gtk_widget_get_state (widget)],
4224 0,
4225 highlight_y,
4226 rtl ? 0 : bin_window_width,
4227 highlight_y);
4228 }
4229 }
4230
4231 /* draw the big row-spanning focus rectangle, if needed */
4232 if (!has_special_cell && node == cursor &&
4233 PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS) &&
4234 gtk_widget_has_focus (widget))
4235 {
4236 gint tmp_y, tmp_height;
4237 gint width;
4238 GtkStateType focus_rect_state;
4239
4240 focus_rect_state =
4241 flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
4242 (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
4243 (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
4244 GTK_STATE_NORMAL));
4245
4246 gdk_drawable_get_size (tree_view->priv->bin_window,
4247 &width, NULL);
4248
4249 if (draw_hgrid_lines)
4250 {
4251 tmp_y = BACKGROUND_FIRST_PIXEL (tree_view, node) + grid_line_width / 2;
4252 tmp_height = ROW_HEIGHT (tree_view) - grid_line_width;
4253 }
4254 else
4255 {
4256 tmp_y = BACKGROUND_FIRST_PIXEL (tree_view, node);
4257 tmp_height = ROW_HEIGHT (tree_view);
4258 }
4259
4260 if (row_ending_details)
4261 gtk_paint_focus (widget->style,
4262 tree_view->priv->bin_window,
4263 focus_rect_state,
4264 &event->area,
4265 widget,
4266 (is_first
4267 ? (is_last ? "treeview" : "treeview-left" )
4268 : (is_last ? "treeview-right" : "treeview-middle" )),
4269 0, tmp_y,
4270 width, tmp_height);
4271 else
4272 gtk_paint_focus (widget->style,
4273 tree_view->priv->bin_window,
4274 focus_rect_state,
4275 &event->area,
4276 widget,
4277 "treeview",
4278 0, tmp_y,
4279 width, tmp_height);
4280 }
4281
4282 y_offset += max_height;
4283
4284 do
4285 {
4286 node = pspp_sheet_view_node_next (tree_view, node);
4287 if (node >= 0)
4288 {
4289 gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
4290 done = TRUE;
4291
4292 /* Sanity Check! */
4293 TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
4294 }
4295 else
4296 goto done;
4297 }
4298 while (!done);
4299 }
4300 while (y_offset < event->area.height);
4301
4302 done:
4303 pspp_sheet_view_draw_grid_lines (tree_view, event, n_visible_columns,
4304 min_y, max_y);
4305
4306 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
4307 {
4308 GdkRectangle *rectangles;
4309 gint n_rectangles;
4310
4311 gdk_region_get_rectangles (event->region,
4312 &rectangles,
4313 &n_rectangles);
4314
4315 while (n_rectangles--)
4316 pspp_sheet_view_paint_rubber_band (tree_view, &rectangles[n_rectangles]);
4317
4318 g_free (rectangles);
4319 }
4320
4321 if (cursor_path)
4322 gtk_tree_path_free (cursor_path);
4323
4324 if (drag_dest_path)
4325 gtk_tree_path_free (drag_dest_path);
4326
4327 return FALSE;
4328 }
4329
4330 static gboolean
4331 pspp_sheet_view_expose (GtkWidget *widget,
4332 GdkEventExpose *event)
4333 {
4334 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
4335
4336 if (event->window == tree_view->priv->bin_window)
4337 {
4338 gboolean retval;
4339 GList *tmp_list;
4340
4341 retval = pspp_sheet_view_bin_expose (widget, event);
4342
4343 /* We can't just chain up to Container::expose as it will try to send the
4344 * event to the headers, so we handle propagating it to our children
4345 * (eg. widgets being edited) ourselves.
4346 */
4347 tmp_list = tree_view->priv->children;
4348 while (tmp_list)
4349 {
4350 PsppSheetViewChild *child = tmp_list->data;
4351 tmp_list = tmp_list->next;
4352
4353 gtk_container_propagate_expose (GTK_CONTAINER (tree_view), child->widget, event);
4354 }
4355
4356 return retval;
4357 }
4358
4359 else if (event->window == tree_view->priv->header_window)
4360 {
4361 gint n_visible_columns;
4362 GList *list;
4363
4364 gtk_paint_flat_box (widget->style,
4365 event->window,
4366 GTK_STATE_NORMAL,
4367 GTK_SHADOW_NONE,
4368 &event->area,
4369 widget,
4370 "cell_odd",
4371 event->area.x,
4372 event->area.y,
4373 event->area.width,
4374 event->area.height);
4375
4376 for (list = tree_view->priv->columns; list != NULL; list = list->next)
4377 {
4378 PsppSheetViewColumn *column = list->data;
4379
4380 if (column == tree_view->priv->drag_column || !column->visible)
4381 continue;
4382
4383 if (span_intersects (column->allocation.x, column->allocation.width,
4384 event->area.x, event->area.width)
4385 && column->button != NULL)
4386 gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
4387 column->button, event);
4388 }
4389
4390 n_visible_columns = 0;
4391 for (list = tree_view->priv->columns; list; list = list->next)
4392 {
4393 if (! PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
4394 continue;
4395 n_visible_columns ++;
4396 }
4397 pspp_sheet_view_draw_grid_lines (tree_view,
4398 event,
4399 n_visible_columns,
4400 event->area.y,
4401 event->area.height);
4402 }
4403 else if (event->window == tree_view->priv->drag_window)
4404 {
4405 gtk_container_propagate_expose (GTK_CONTAINER (tree_view),
4406 tree_view->priv->drag_column->button,
4407 event);
4408 }
4409 return TRUE;
4410 }
4411
4412 enum
4413 {
4414 DROP_HOME,
4415 DROP_RIGHT,
4416 DROP_LEFT,
4417 DROP_END
4418 };
4419
4420 /* returns 0x1 when no column has been found -- yes it's hackish */
4421 static PsppSheetViewColumn *
4422 pspp_sheet_view_get_drop_column (PsppSheetView *tree_view,
4423 PsppSheetViewColumn *column,
4424 gint drop_position)
4425 {
4426 PsppSheetViewColumn *left_column = NULL;
4427 PsppSheetViewColumn *cur_column = NULL;
4428 GList *tmp_list;
4429
4430 if (!column->reorderable)
4431 return (PsppSheetViewColumn *)0x1;
4432
4433 switch (drop_position)
4434 {
4435 case DROP_HOME:
4436 /* find first column where we can drop */
4437 tmp_list = tree_view->priv->columns;
4438 if (column == PSPP_SHEET_VIEW_COLUMN (tmp_list->data))
4439 return (PsppSheetViewColumn *)0x1;
4440
4441 while (tmp_list)
4442 {
4443 g_assert (tmp_list);
4444
4445 cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4446 tmp_list = tmp_list->next;
4447
4448 if (left_column && left_column->visible == FALSE)
4449 continue;
4450
4451 if (!tree_view->priv->column_drop_func)
4452 return left_column;
4453
4454 if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
4455 {
4456 left_column = cur_column;
4457 continue;
4458 }
4459
4460 return left_column;
4461 }
4462
4463 if (!tree_view->priv->column_drop_func)
4464 return left_column;
4465
4466 if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
4467 return left_column;
4468 else
4469 return (PsppSheetViewColumn *)0x1;
4470 break;
4471
4472 case DROP_RIGHT:
4473 /* find first column after column where we can drop */
4474 tmp_list = tree_view->priv->columns;
4475
4476 for (; tmp_list; tmp_list = tmp_list->next)
4477 if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data) == column)
4478 break;
4479
4480 if (!tmp_list || !tmp_list->next)
4481 return (PsppSheetViewColumn *)0x1;
4482
4483 tmp_list = tmp_list->next;
4484 left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4485 tmp_list = tmp_list->next;
4486
4487 while (tmp_list)
4488 {
4489 g_assert (tmp_list);
4490
4491 cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4492 tmp_list = tmp_list->next;
4493
4494 if (left_column && left_column->visible == FALSE)
4495 {
4496 left_column = cur_column;
4497 if (tmp_list)
4498 tmp_list = tmp_list->next;
4499 continue;
4500 }
4501
4502 if (!tree_view->priv->column_drop_func)
4503 return left_column;
4504
4505 if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
4506 {
4507 left_column = cur_column;
4508 continue;
4509 }
4510
4511 return left_column;
4512 }
4513
4514 if (!tree_view->priv->column_drop_func)
4515 return left_column;
4516
4517 if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
4518 return left_column;
4519 else
4520 return (PsppSheetViewColumn *)0x1;
4521 break;
4522
4523 case DROP_LEFT:
4524 /* find first column before column where we can drop */
4525 tmp_list = tree_view->priv->columns;
4526
4527 for (; tmp_list; tmp_list = tmp_list->next)
4528 if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data) == column)
4529 break;
4530
4531 if (!tmp_list || !tmp_list->prev)
4532 return (PsppSheetViewColumn *)0x1;
4533
4534 tmp_list = tmp_list->prev;
4535 cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4536 tmp_list = tmp_list->prev;
4537
4538 while (tmp_list)
4539 {
4540 g_assert (tmp_list);
4541
4542 left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4543
4544 if (left_column && !left_column->visible)
4545 {
4546 /*if (!tmp_list->prev)
4547 return (PsppSheetViewColumn *)0x1;
4548 */
4549 /*
4550 cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->prev->data);
4551 tmp_list = tmp_list->prev->prev;
4552 continue;*/
4553
4554 cur_column = left_column;
4555 if (tmp_list)
4556 tmp_list = tmp_list->prev;
4557 continue;
4558 }
4559
4560 if (!tree_view->priv->column_drop_func)
4561 return left_column;
4562
4563 if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
4564 return left_column;
4565
4566 cur_column = left_column;
4567 tmp_list = tmp_list->prev;
4568 }
4569
4570 if (!tree_view->priv->column_drop_func)
4571 return NULL;
4572
4573 if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
4574 return NULL;
4575 else
4576 return (PsppSheetViewColumn *)0x1;
4577 break;
4578
4579 case DROP_END:
4580 /* same as DROP_HOME case, but doing it backwards */
4581 tmp_list = g_list_last (tree_view->priv->columns);
4582 cur_column = NULL;
4583
4584 if (column == PSPP_SHEET_VIEW_COLUMN (tmp_list->data))
4585 return (PsppSheetViewColumn *)0x1;
4586
4587 while (tmp_list)
4588 {
4589 g_assert (tmp_list);
4590
4591 left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
4592
4593 if (left_column && !left_column->visible)
4594 {
4595 cur_column = left_column;
4596 tmp_list = tmp_list->prev;
4597 }
4598
4599 if (!tree_view->priv->column_drop_func)
4600 return left_column;
4601
4602 if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
4603 return left_column;
4604
4605 cur_column = left_column;
4606 tmp_list = tmp_list->prev;
4607 }
4608
4609 if (!tree_view->priv->column_drop_func)
4610 return NULL;
4611
4612 if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
4613 return NULL;
4614 else
4615 return (PsppSheetViewColumn *)0x1;
4616 break;
4617 }
4618
4619 return (PsppSheetViewColumn *)0x1;
4620 }
4621
4622 static gboolean
4623 pspp_sheet_view_key_press (GtkWidget *widget,
4624 GdkEventKey *event)
4625 {
4626 PsppSheetView *tree_view = (PsppSheetView *) widget;
4627
4628 if (tree_view->priv->rubber_band_status)
4629 {
4630 if (event->keyval == GDK_Escape)
4631 pspp_sheet_view_stop_rubber_band (tree_view);
4632
4633 return TRUE;
4634 }
4635
4636 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
4637 {
4638 if (event->keyval == GDK_Escape)
4639 {
4640 tree_view->priv->cur_reorder = NULL;
4641 pspp_sheet_view_button_release_drag_column (widget, NULL);
4642 }
4643 return TRUE;
4644 }
4645
4646 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
4647 {
4648 GList *focus_column;
4649 gboolean rtl;
4650
4651 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
4652
4653 for (focus_column = tree_view->priv->columns;
4654 focus_column;
4655 focus_column = focus_column->next)
4656 {
4657 PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
4658
4659 if (column->button && gtk_widget_has_focus (column->button))
4660 break;
4661 }
4662
4663 if (focus_column &&
4664 (event->state & GDK_SHIFT_MASK) && (event->state & GDK_MOD1_MASK) &&
4665 (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
4666 || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
4667 {
4668 PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
4669
4670 if (!column->resizable)
4671 {
4672 gtk_widget_error_bell (widget);
4673 return TRUE;
4674 }
4675
4676 if (event->keyval == (rtl ? GDK_Right : GDK_Left)
4677 || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
4678 {
4679 gint old_width = column->resized_width;
4680
4681 column->resized_width = MAX (column->resized_width,
4682 column->width);
4683 column->resized_width -= 2;
4684 if (column->resized_width < 0)
4685 column->resized_width = 0;
4686
4687 if (column->min_width == -1)
4688 column->resized_width = MAX (column->button_request,
4689 column->resized_width);
4690 else
4691 column->resized_width = MAX (column->min_width,
4692 column->resized_width);
4693
4694 if (column->max_width != -1)
4695 column->resized_width = MIN (column->resized_width,
4696 column->max_width);
4697
4698 column->use_resized_width = TRUE;
4699
4700 if (column->resized_width != old_width)
4701 gtk_widget_queue_resize (widget);
4702 else
4703 gtk_widget_error_bell (widget);
4704 }
4705 else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
4706 || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
4707 {
4708 gint old_width = column->resized_width;
4709
4710 column->resized_width = MAX (column->resized_width,
4711 column->width);
4712 column->resized_width += 2;
4713
4714 if (column->max_width != -1)
4715 column->resized_width = MIN (column->resized_width,
4716 column->max_width);
4717
4718 column->use_resized_width = TRUE;
4719
4720 if (column->resized_width != old_width)
4721 gtk_widget_queue_resize (widget);
4722 else
4723 gtk_widget_error_bell (widget);
4724 }
4725
4726 return TRUE;
4727 }
4728
4729 if (focus_column &&
4730 (event->state & GDK_MOD1_MASK) &&
4731 (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
4732 || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
4733 || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
4734 || event->keyval == GDK_End || event->keyval == GDK_KP_End))
4735 {
4736 PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
4737
4738 if (event->keyval == (rtl ? GDK_Right : GDK_Left)
4739 || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
4740 {
4741 PsppSheetViewColumn *col;
4742 col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_LEFT);
4743 if (col != (PsppSheetViewColumn *)0x1)
4744 pspp_sheet_view_move_column_after (tree_view, column, col);
4745 else
4746 gtk_widget_error_bell (widget);
4747 }
4748 else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
4749 || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
4750 {
4751 PsppSheetViewColumn *col;
4752 col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_RIGHT);
4753 if (col != (PsppSheetViewColumn *)0x1)
4754 pspp_sheet_view_move_column_after (tree_view, column, col);
4755 else
4756 gtk_widget_error_bell (widget);
4757 }
4758 else if (event->keyval == GDK_Home || event->keyval == GDK_KP_Home)
4759 {
4760 PsppSheetViewColumn *col;
4761 col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_HOME);
4762 if (col != (PsppSheetViewColumn *)0x1)
4763 pspp_sheet_view_move_column_after (tree_view, column, col);
4764 else
4765 gtk_widget_error_bell (widget);
4766 }
4767 else if (event->keyval == GDK_End || event->keyval == GDK_KP_End)
4768 {
4769 PsppSheetViewColumn *col;
4770 col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_END);
4771 if (col != (PsppSheetViewColumn *)0x1)
4772 pspp_sheet_view_move_column_after (tree_view, column, col);
4773 else
4774 gtk_widget_error_bell (widget);
4775 }
4776
4777 return TRUE;
4778 }
4779 }
4780
4781 /* Chain up to the parent class. It handles the keybindings. */
4782 if (GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->key_press_event (widget, event))
4783 return TRUE;
4784
4785 if (tree_view->priv->search_entry_avoid_unhandled_binding)
4786 {
4787 tree_view->priv->search_entry_avoid_unhandled_binding = FALSE;
4788 return FALSE;
4789 }
4790
4791 /* We pass the event to the search_entry. If its text changes, then we start
4792 * the typeahead find capabilities. */
4793 if (gtk_widget_has_focus (GTK_WIDGET (tree_view))
4794 && tree_view->priv->enable_search
4795 && !tree_view->priv->search_custom_entry_set)
4796 {
4797 GdkEvent *new_event;
4798 char *old_text;
4799 const char *new_text;
4800 gboolean retval;
4801 GdkScreen *screen;
4802 gboolean text_modified;
4803 gulong popup_menu_id;
4804
4805 pspp_sheet_view_ensure_interactive_directory (tree_view);
4806
4807 /* Make a copy of the current text */
4808 old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
4809 new_event = gdk_event_copy ((GdkEvent *) event);
4810 g_object_unref (((GdkEventKey *) new_event)->window);
4811 ((GdkEventKey *) new_event)->window = g_object_ref (tree_view->priv->search_window->window);
4812 gtk_widget_realize (tree_view->priv->search_window);
4813
4814 popup_menu_id = g_signal_connect (tree_view->priv->search_entry,
4815 "popup-menu", G_CALLBACK (gtk_true),
4816 NULL);
4817
4818 /* Move the entry off screen */
4819 screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
4820 gtk_window_move (GTK_WINDOW (tree_view->priv->search_window),
4821 gdk_screen_get_width (screen) + 1,
4822 gdk_screen_get_height (screen) + 1);
4823 gtk_widget_show (tree_view->priv->search_window);
4824
4825 /* Send the event to the window. If the preedit_changed signal is emitted
4826 * during this event, we will set priv->imcontext_changed */
4827 tree_view->priv->imcontext_changed = FALSE;
4828 retval = gtk_widget_event (tree_view->priv->search_window, new_event);
4829 gdk_event_free (new_event);
4830 gtk_widget_hide (tree_view->priv->search_window);
4831
4832 g_signal_handler_disconnect (tree_view->priv->search_entry,
4833 popup_menu_id);
4834
4835 /* We check to make sure that the entry tried to handle the text, and that
4836 * the text has changed.
4837 */
4838 new_text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
4839 text_modified = strcmp (old_text, new_text) != 0;
4840 g_free (old_text);
4841 if (tree_view->priv->imcontext_changed || /* we're in a preedit */
4842 (retval && text_modified)) /* ...or the text was modified */
4843 {
4844 if (pspp_sheet_view_real_start_interactive_search (tree_view, FALSE))
4845 {
4846 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
4847 return TRUE;
4848 }
4849 else
4850 {
4851 gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
4852 return FALSE;
4853 }
4854 }
4855 }
4856
4857 return FALSE;
4858 }
4859
4860 static gboolean
4861 pspp_sheet_view_key_release (GtkWidget *widget,
4862 GdkEventKey *event)
4863 {
4864 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
4865
4866 if (tree_view->priv->rubber_band_status)
4867 return TRUE;
4868
4869 return GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->key_release_event (widget, event);
4870 }
4871
4872 /* FIXME Is this function necessary? Can I get an enter_notify event
4873 * w/o either an expose event or a mouse motion event?
4874 */
4875 static gboolean
4876 pspp_sheet_view_enter_notify (GtkWidget *widget,
4877 GdkEventCrossing *event)
4878 {
4879 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
4880 int node;
4881 gint new_y;
4882
4883 /* Sanity check it */
4884 if (event->window != tree_view->priv->bin_window)
4885 return FALSE;
4886
4887 if (tree_view->priv->row_count == 0)
4888 return FALSE;
4889
4890 if (event->mode == GDK_CROSSING_GRAB ||
4891 event->mode == GDK_CROSSING_GTK_GRAB ||
4892 event->mode == GDK_CROSSING_GTK_UNGRAB ||
4893 event->mode == GDK_CROSSING_STATE_CHANGED)
4894 return TRUE;
4895
4896 /* find the node internally */
4897 new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
4898 if (new_y < 0)
4899 new_y = 0;
4900 pspp_sheet_view_find_offset (tree_view, new_y, &node);
4901
4902 tree_view->priv->event_last_x = event->x;
4903 tree_view->priv->event_last_y = event->y;
4904
4905 prelight_or_select (tree_view, node, event->x, event->y);
4906
4907 return TRUE;
4908 }
4909
4910 static gboolean
4911 pspp_sheet_view_leave_notify (GtkWidget *widget,
4912 GdkEventCrossing *event)
4913 {
4914 PsppSheetView *tree_view;
4915
4916 if (event->mode == GDK_CROSSING_GRAB)
4917 return TRUE;
4918
4919 tree_view = PSPP_SHEET_VIEW (widget);
4920
4921 if (tree_view->priv->prelight_node >= 0)
4922 _pspp_sheet_view_queue_draw_node (tree_view,
4923 tree_view->priv->prelight_node,
4924 NULL);
4925
4926 tree_view->priv->event_last_x = -10000;
4927 tree_view->priv->event_last_y = -10000;
4928
4929 prelight_or_select (tree_view,
4930 -1,
4931 -1000, -1000); /* coords not possibly over an arrow */
4932
4933 return TRUE;
4934 }
4935
4936
4937 static gint
4938 pspp_sheet_view_focus_out (GtkWidget *widget,
4939 GdkEventFocus *event)
4940 {
4941 PsppSheetView *tree_view;
4942
4943 tree_view = PSPP_SHEET_VIEW (widget);
4944
4945 gtk_widget_queue_draw (widget);
4946
4947 /* destroy interactive search dialog */
4948 if (tree_view->priv->search_window)
4949 pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
4950
4951 return FALSE;
4952 }
4953
4954
4955 /* Incremental Reflow
4956 */
4957
4958 static void
4959 pspp_sheet_view_node_queue_redraw (PsppSheetView *tree_view,
4960 int node)
4961 {
4962 gint y;
4963
4964 y = pspp_sheet_view_node_find_offset (tree_view, node)
4965 - tree_view->priv->vadjustment->value
4966 + TREE_VIEW_HEADER_HEIGHT (tree_view);
4967
4968 gtk_widget_queue_draw_area (GTK_WIDGET (tree_view),
4969 0, y,
4970 GTK_WIDGET (tree_view)->allocation.width,
4971 tree_view->priv->fixed_height);
4972 }
4973
4974 static gboolean
4975 node_is_visible (PsppSheetView *tree_view,
4976 int node)
4977 {
4978 int y;
4979 int height;
4980
4981 y = pspp_sheet_view_node_find_offset (tree_view, node);
4982 height = ROW_HEIGHT (tree_view);
4983
4984 if (y >= tree_view->priv->vadjustment->value &&
4985 y + height <= (tree_view->priv->vadjustment->value
4986 + tree_view->priv->vadjustment->page_size))
4987 return TRUE;
4988
4989 return FALSE;
4990 }
4991
4992 /* Returns the row height. */
4993 static gint
4994 validate_row (PsppSheetView *tree_view,
4995 int node,
4996 GtkTreeIter *iter,
4997 GtkTreePath *path)
4998 {
4999 PsppSheetViewColumn *column;
5000 GList *list, *first_column, *last_column;
5001 gint height = 0;
5002 gint horizontal_separator;
5003 gint vertical_separator;
5004 gint focus_line_width;
5005 gboolean retval = FALSE;
5006 gboolean draw_vgrid_lines, draw_hgrid_lines;
5007 gint focus_pad;
5008 gint grid_line_width;
5009 gboolean wide_separators;
5010 gint separator_height;
5011
5012 gtk_widget_style_get (GTK_WIDGET (tree_view),
5013 "focus-padding", &focus_pad,
5014 "focus-line-width", &focus_line_width,
5015 "horizontal-separator", &horizontal_separator,
5016 "vertical-separator", &vertical_separator,
5017 "grid-line-width", &grid_line_width,
5018 "wide-separators", &wide_separators,
5019 "separator-height", &separator_height,
5020 NULL);
5021
5022 draw_vgrid_lines =
5023 tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
5024 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
5025 draw_hgrid_lines =
5026 tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
5027 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
5028
5029 for (last_column = g_list_last (tree_view->priv->columns);
5030 last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
5031 last_column = last_column->prev)
5032 ;
5033
5034 for (first_column = g_list_first (tree_view->priv->columns);
5035 first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
5036 first_column = first_column->next)
5037 ;
5038
5039 for (list = tree_view->priv->columns; list; list = list->next)
5040 {
5041 gint tmp_width;
5042 gint tmp_height;
5043
5044 column = list->data;
5045
5046 if (! column->visible)
5047 continue;
5048
5049 pspp_sheet_view_column_cell_set_cell_data (column, tree_view->priv->model, iter);
5050 pspp_sheet_view_column_cell_get_size (column,
5051 NULL, NULL, NULL,
5052 &tmp_width, &tmp_height);
5053
5054 tmp_height += vertical_separator;
5055 height = MAX (height, tmp_height);
5056
5057 tmp_width = tmp_width + horizontal_separator;
5058
5059 if (draw_vgrid_lines)
5060 {
5061 if (list->data == first_column || list->data == last_column)
5062 tmp_width += grid_line_width / 2.0;
5063 else
5064 tmp_width += grid_line_width;
5065 }
5066
5067 if (tmp_width > column->requested_width)
5068 {
5069 retval = TRUE;
5070 column->requested_width = tmp_width;
5071 }
5072 }
5073
5074 if (draw_hgrid_lines)
5075 height += grid_line_width;
5076
5077 tree_view->priv->post_validation_flag = TRUE;
5078 return height;
5079 }
5080
5081
5082 static void
5083 validate_visible_area (PsppSheetView *tree_view)
5084 {
5085 GtkTreePath *path = NULL;
5086 GtkTreePath *above_path = NULL;
5087 GtkTreeIter iter;
5088 int node = -1;
5089 gboolean size_changed = FALSE;
5090 gint total_height;
5091 gint area_above = 0;
5092 gint area_below = 0;
5093
5094 if (tree_view->priv->row_count == 0)
5095 return;
5096
5097 if (tree_view->priv->scroll_to_path == NULL)
5098 return;
5099
5100 total_height = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
5101
5102 if (total_height == 0)
5103 return;
5104
5105 path = gtk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
5106 if (path)
5107 {
5108 /* we are going to scroll, and will update dy */
5109 _pspp_sheet_view_find_node (tree_view, path, &node);
5110 gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
5111
5112 if (tree_view->priv->scroll_to_use_align)
5113 {
5114 gint height = ROW_HEIGHT (tree_view);
5115 area_above = (total_height - height) *
5116 tree_view->priv->scroll_to_row_align;
5117 area_below = total_height - area_above - height;
5118 area_above = MAX (area_above, 0);
5119 area_below = MAX (area_below, 0);
5120 }
5121 else
5122 {
5123 /* two cases:
5124 * 1) row not visible
5125 * 2) row visible
5126 */
5127 gint dy;
5128 gint height = ROW_HEIGHT (tree_view);
5129
5130 dy = pspp_sheet_view_node_find_offset (tree_view, node);
5131
5132 if (dy >= tree_view->priv->vadjustment->value &&
5133 dy + height <= (tree_view->priv->vadjustment->value
5134 + tree_view->priv->vadjustment->page_size))
5135 {
5136 /* row visible: keep the row at the same position */
5137 area_above = dy - tree_view->priv->vadjustment->value;
5138 area_below = (tree_view->priv->vadjustment->value +
5139 tree_view->priv->vadjustment->page_size)
5140 - dy - height;
5141 }
5142 else
5143 {
5144 /* row not visible */
5145 if (dy >= 0
5146 && dy + height <= tree_view->priv->vadjustment->page_size)
5147 {
5148 /* row at the beginning -- fixed */
5149 area_above = dy;
5150 area_below = tree_view->priv->vadjustment->page_size
5151 - area_above - height;
5152 }
5153 else if (dy >= (tree_view->priv->vadjustment->upper -
5154 tree_view->priv->vadjustment->page_size))
5155 {
5156 /* row at the end -- fixed */
5157 area_above = dy - (tree_view->priv->vadjustment->upper -
5158 tree_view->priv->vadjustment->page_size);
5159 area_below = tree_view->priv->vadjustment->page_size -
5160 area_above - height;
5161
5162 if (area_below < 0)
5163 {
5164 area_above = tree_view->priv->vadjustment->page_size - height;
5165 area_below = 0;
5166 }
5167 }
5168 else
5169 {
5170 /* row somewhere in the middle, bring it to the top
5171 * of the view
5172 */
5173 area_above = 0;
5174 area_below = total_height - height;
5175 }
5176 }
5177 }
5178 }
5179 else
5180 /* the scroll to isn't valid; ignore it.
5181 */
5182 {
5183 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
5184 tree_view->priv->scroll_to_path = NULL;
5185 return;
5186 }
5187
5188 above_path = gtk_tree_path_copy (path);
5189
5190 /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
5191 * backwards is much slower then forward, as there is no iter_prev function.
5192 * We go forwards first in case we run out of tree. Then we go backwards to
5193 * fill out the top.
5194 */
5195 while (node >= 0 && area_below > 0)
5196 {
5197 gboolean done = FALSE;
5198 do
5199 {
5200 node = pspp_sheet_view_node_next (tree_view, node);
5201 if (node >= 0)
5202 {
5203 gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
5204 done = TRUE;
5205 gtk_tree_path_next (path);
5206
5207 /* Sanity Check! */
5208 TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
5209 }
5210 else
5211 break;
5212 }
5213 while (!done);
5214
5215 if (node < 0)
5216 break;
5217
5218 area_below -= ROW_HEIGHT (tree_view);
5219 }
5220 gtk_tree_path_free (path);
5221
5222 /* If we ran out of tree, and have extra area_below left, we need to add it
5223 * to area_above */
5224 if (area_below > 0)
5225 area_above += area_below;
5226
5227 _pspp_sheet_view_find_node (tree_view, above_path, &node);
5228
5229 /* We walk backwards */
5230 while (area_above > 0)
5231 {
5232 node = pspp_sheet_view_node_prev (tree_view, node);
5233
5234 /* Always find the new path in the tree. We cannot just assume
5235 * a gtk_tree_path_prev() is enough here, as there might be children
5236 * in between this node and the previous sibling node. If this
5237 * appears to be a performance hotspot in profiles, we can look into
5238 * intrigate logic for keeping path, node and iter in sync like
5239 * we do for forward walks. (Which will be hard because of the lacking
5240 * iter_prev).
5241 */
5242
5243 if (node < 0)
5244 break;
5245
5246 gtk_tree_path_free (above_path);
5247 above_path = _pspp_sheet_view_find_path (tree_view, node);
5248
5249 gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
5250
5251 area_above -= ROW_HEIGHT (tree_view);
5252 }
5253
5254 /* set the dy here to scroll to the path,
5255 * and sync the top row accordingly
5256 */
5257 pspp_sheet_view_set_top_row (tree_view, above_path, -area_above);
5258 pspp_sheet_view_top_row_to_dy (tree_view);
5259
5260 /* update width/height and queue a resize */
5261 if (size_changed)
5262 {
5263 GtkRequisition requisition;
5264
5265 /* We temporarily guess a size, under the assumption that it will be the
5266 * same when we get our next size_allocate. If we don't do this, we'll be
5267 * in an inconsistent state if we call top_row_to_dy. */
5268
5269 gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
5270 tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
5271 tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
5272 gtk_adjustment_changed (tree_view->priv->hadjustment);
5273 gtk_adjustment_changed (tree_view->priv->vadjustment);
5274 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
5275 }
5276
5277 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
5278 tree_view->priv->scroll_to_path = NULL;
5279
5280 if (above_path)
5281 gtk_tree_path_free (above_path);
5282
5283 if (tree_view->priv->scroll_to_column)
5284 {
5285 tree_view->priv->scroll_to_column = NULL;
5286 }
5287 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
5288 }
5289
5290 static void
5291 initialize_fixed_height_mode (PsppSheetView *tree_view)
5292 {
5293 if (!tree_view->priv->row_count)
5294 return;
5295
5296 if (tree_view->priv->fixed_height_set)
5297 return;
5298
5299 if (tree_view->priv->fixed_height < 0)
5300 {
5301 GtkTreeIter iter;
5302 GtkTreePath *path;
5303
5304 int node = 0;
5305
5306 path = _pspp_sheet_view_find_path (tree_view, node);
5307 gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
5308
5309 tree_view->priv->fixed_height = validate_row (tree_view, node, &iter, path);
5310
5311 gtk_tree_path_free (path);
5312
5313 g_object_notify (G_OBJECT (tree_view), "fixed-height");
5314 }
5315 }
5316
5317 /* Our strategy for finding nodes to validate is a little convoluted. We find
5318 * the left-most uninvalidated node. We then try walking right, validating
5319 * nodes. Once we find a valid node, we repeat the previous process of finding
5320 * the first invalid node.
5321 */
5322
5323 static gboolean
5324 validate_rows_handler (PsppSheetView *tree_view)
5325 {
5326 initialize_fixed_height_mode (tree_view);
5327 if (tree_view->priv->validate_rows_timer)
5328 {
5329 g_source_remove (tree_view->priv->validate_rows_timer);
5330 tree_view->priv->validate_rows_timer = 0;
5331 }
5332
5333 return FALSE;
5334 }
5335
5336 static gboolean
5337 do_presize_handler (PsppSheetView *tree_view)
5338 {
5339 GtkRequisition requisition;
5340
5341 validate_visible_area (tree_view);
5342 tree_view->priv->presize_handler_timer = 0;
5343
5344 gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
5345
5346 tree_view->priv->hadjustment->upper = MAX (tree_view->priv->hadjustment->upper, (gfloat)requisition.width);
5347 tree_view->priv->vadjustment->upper = MAX (tree_view->priv->vadjustment->upper, (gfloat)requisition.height);
5348 gtk_adjustment_changed (tree_view->priv->hadjustment);
5349 gtk_adjustment_changed (tree_view->priv->vadjustment);
5350 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
5351
5352 return FALSE;
5353 }
5354
5355 static gboolean
5356 presize_handler_callback (gpointer data)
5357 {
5358 do_presize_handler (PSPP_SHEET_VIEW (data));
5359
5360 return FALSE;
5361 }
5362
5363 static void
5364 install_presize_handler (PsppSheetView *tree_view)
5365 {
5366 if (! gtk_widget_get_realized (GTK_WIDGET (tree_view)))
5367 return;
5368
5369 if (! tree_view->priv->presize_handler_timer)
5370 {
5371 tree_view->priv->presize_handler_timer =
5372 gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL);
5373 }
5374 if (! tree_view->priv->validate_rows_timer)
5375 {
5376 tree_view->priv->validate_rows_timer =
5377 gdk_threads_add_idle_full (PSPP_SHEET_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL);
5378 }
5379 }
5380
5381 static gboolean
5382 scroll_sync_handler (PsppSheetView *tree_view)
5383 {
5384 if (tree_view->priv->height <= tree_view->priv->vadjustment->page_size)
5385 gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
5386 else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
5387 pspp_sheet_view_top_row_to_dy (tree_view);
5388 else
5389 pspp_sheet_view_dy_to_top_row (tree_view);
5390
5391 tree_view->priv->scroll_sync_timer = 0;
5392
5393 return FALSE;
5394 }
5395
5396 static void
5397 install_scroll_sync_handler (PsppSheetView *tree_view)
5398 {
5399 if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
5400 return;
5401
5402 if (!tree_view->priv->scroll_sync_timer)
5403 {
5404 tree_view->priv->scroll_sync_timer =
5405 gdk_threads_add_idle_full (PSPP_SHEET_VIEW_PRIORITY_SCROLL_SYNC, (GSourceFunc) scroll_sync_handler, tree_view, NULL);
5406 }
5407 }
5408
5409 static void
5410 pspp_sheet_view_set_top_row (PsppSheetView *tree_view,
5411 GtkTreePath *path,
5412 gint offset)
5413 {
5414 gtk_tree_row_reference_free (tree_view->priv->top_row);
5415
5416 if (!path)
5417 {
5418 tree_view->priv->top_row = NULL;
5419 tree_view->priv->top_row_dy = 0;
5420 }
5421 else
5422 {
5423 tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
5424 tree_view->priv->top_row_dy = offset;
5425 }
5426 }
5427
5428 /* Always call this iff dy is in the visible range. If the tree is empty, then
5429 * it's set to be NULL, and top_row_dy is 0;
5430 */
5431 static void
5432 pspp_sheet_view_dy_to_top_row (PsppSheetView *tree_view)
5433 {
5434 gint offset;
5435 GtkTreePath *path;
5436 int node;
5437
5438 if (tree_view->priv->row_count == 0)
5439 {
5440 pspp_sheet_view_set_top_row (tree_view, NULL, 0);
5441 }
5442 else
5443 {
5444 offset = pspp_sheet_view_find_offset (tree_view,
5445 tree_view->priv->dy,
5446 &node);
5447
5448 if (node < 0)
5449 {
5450 pspp_sheet_view_set_top_row (tree_view, NULL, 0);
5451 }
5452 else
5453 {
5454 path = _pspp_sheet_view_find_path (tree_view, node);
5455 pspp_sheet_view_set_top_row (tree_view, path, offset);
5456 gtk_tree_path_free (path);
5457 }
5458 }
5459 }
5460
5461 static void
5462 pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view)
5463 {
5464 GtkTreePath *path;
5465 int node;
5466 int new_dy;
5467
5468 /* Avoid recursive calls */
5469 if (tree_view->priv->in_top_row_to_dy)
5470 return;
5471
5472 if (tree_view->priv->top_row)
5473 path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
5474 else
5475 path = NULL;
5476
5477 if (!path)
5478 node = -1;
5479 else
5480 _pspp_sheet_view_find_node (tree_view, path, &node);
5481
5482 if (path)
5483 gtk_tree_path_free (path);
5484
5485 if (node < 0)
5486 {
5487 /* keep dy and set new toprow */
5488 gtk_tree_row_reference_free (tree_view->priv->top_row);
5489 tree_view->priv->top_row = NULL;
5490 tree_view->priv->top_row_dy = 0;
5491 /* DO NOT install the idle handler */
5492 pspp_sheet_view_dy_to_top_row (tree_view);
5493 return;
5494 }
5495
5496 if (ROW_HEIGHT (tree_view) < tree_view->priv->top_row_dy)
5497 {
5498 /* new top row -- do NOT install the idle handler */
5499 pspp_sheet_view_dy_to_top_row (tree_view);
5500 return;
5501 }
5502
5503 new_dy = pspp_sheet_view_node_find_offset (tree_view, node);
5504 new_dy += tree_view->priv->top_row_dy;
5505
5506 if (new_dy + tree_view->priv->vadjustment->page_size > tree_view->priv->height)
5507 new_dy = tree_view->priv->height - tree_view->priv->vadjustment->page_size;
5508
5509 new_dy = MAX (0, new_dy);
5510
5511 tree_view->priv->in_top_row_to_dy = TRUE;
5512 gtk_adjustment_set_value (tree_view->priv->vadjustment, (gdouble)new_dy);
5513 tree_view->priv->in_top_row_to_dy = FALSE;
5514 }
5515
5516
5517 void
5518 _pspp_sheet_view_install_mark_rows_col_dirty (PsppSheetView *tree_view)
5519 {
5520 install_presize_handler (tree_view);
5521 }
5522
5523 /* Drag-and-drop */
5524
5525 static void
5526 set_source_row (GdkDragContext *context,
5527 GtkTreeModel *model,
5528 GtkTreePath *source_row)
5529 {
5530 g_object_set_data_full (G_OBJECT (context),
5531 "gtk-tree-view-source-row",
5532 source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
5533 (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
5534 }
5535
5536 static GtkTreePath*
5537 get_source_row (GdkDragContext *context)
5538 {
5539 GtkTreeRowReference *ref =
5540 g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
5541
5542 if (ref)
5543 return gtk_tree_row_reference_get_path (ref);
5544 else
5545 return NULL;
5546 }
5547
5548 typedef struct
5549 {
5550 GtkTreeRowReference *dest_row;
5551 guint path_down_mode : 1;
5552 guint empty_view_drop : 1;
5553 guint drop_append_mode : 1;
5554 }
5555 DestRow;
5556
5557 static void
5558 dest_row_free (gpointer data)
5559 {
5560 DestRow *dr = (DestRow *)data;
5561
5562 gtk_tree_row_reference_free (dr->dest_row);
5563 g_slice_free (DestRow, dr);
5564 }
5565
5566 static void
5567 set_dest_row (GdkDragContext *context,
5568 GtkTreeModel *model,
5569 GtkTreePath *dest_row,
5570 gboolean path_down_mode,
5571 gboolean empty_view_drop,
5572 gboolean drop_append_mode)
5573 {
5574 DestRow *dr;
5575
5576 if (!dest_row)
5577 {
5578 g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
5579 NULL, NULL);
5580 return;
5581 }
5582
5583 dr = g_slice_new (DestRow);
5584
5585 dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
5586 dr->path_down_mode = path_down_mode != FALSE;
5587 dr->empty_view_drop = empty_view_drop != FALSE;
5588 dr->drop_append_mode = drop_append_mode != FALSE;
5589
5590 g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
5591 dr, (GDestroyNotify) dest_row_free);
5592 }
5593
5594 static GtkTreePath*
5595 get_dest_row (GdkDragContext *context,
5596 gboolean *path_down_mode)
5597 {
5598 DestRow *dr =
5599 g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
5600
5601 if (dr)
5602 {
5603 GtkTreePath *path = NULL;
5604
5605 if (path_down_mode)
5606 *path_down_mode = dr->path_down_mode;
5607
5608 if (dr->dest_row)
5609 path = gtk_tree_row_reference_get_path (dr->dest_row);
5610 else if (dr->empty_view_drop)
5611 path = gtk_tree_path_new_from_indices (0, -1);
5612 else
5613 path = NULL;
5614
5615 if (path && dr->drop_append_mode)
5616 gtk_tree_path_next (path);
5617
5618 return path;
5619 }
5620 else
5621 return NULL;
5622 }
5623
5624 /* Get/set whether drag_motion requested the drag data and
5625 * drag_data_received should thus not actually insert the data,
5626 * since the data doesn't result from a drop.
5627 */
5628 static void
5629 set_status_pending (GdkDragContext *context,
5630 GdkDragAction suggested_action)
5631 {
5632 g_object_set_data (G_OBJECT (context),
5633 "gtk-tree-view-status-pending",
5634 GINT_TO_POINTER (suggested_action));
5635 }
5636
5637 static GdkDragAction
5638 get_status_pending (GdkDragContext *context)
5639 {
5640 return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
5641 "gtk-tree-view-status-pending"));
5642 }
5643
5644 static TreeViewDragInfo*
5645 get_info (PsppSheetView *tree_view)
5646 {
5647 return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
5648 }
5649
5650 static void
5651 destroy_info (TreeViewDragInfo *di)
5652 {
5653 g_slice_free (TreeViewDragInfo, di);
5654 }
5655
5656 static TreeViewDragInfo*
5657 ensure_info (PsppSheetView *tree_view)
5658 {
5659 TreeViewDragInfo *di;
5660
5661 di = get_info (tree_view);
5662
5663 if (di == NULL)
5664 {
5665 di = g_slice_new0 (TreeViewDragInfo);
5666
5667 g_object_set_data_full (G_OBJECT (tree_view),
5668 "gtk-tree-view-drag-info",
5669 di,
5670 (GDestroyNotify) destroy_info);
5671 }
5672
5673 return di;
5674 }
5675
5676 static void
5677 remove_info (PsppSheetView *tree_view)
5678 {
5679 g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
5680 }
5681
5682 #if 0
5683 static gint
5684 drag_scan_timeout (gpointer data)
5685 {
5686 PsppSheetView *tree_view;
5687 gint x, y;
5688 GdkModifierType state;
5689 GtkTreePath *path = NULL;
5690 PsppSheetViewColumn *column = NULL;
5691 GdkRectangle visible_rect;
5692
5693 GDK_THREADS_ENTER ();
5694
5695 tree_view = PSPP_SHEET_VIEW (data);
5696
5697 gdk_window_get_pointer (tree_view->priv->bin_window,
5698 &x, &y, &state);
5699
5700 pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
5701
5702 /* See if we are near the edge. */
5703 if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
5704 (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
5705 (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
5706 (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
5707 {
5708 pspp_sheet_view_get_path_at_pos (tree_view,
5709 tree_view->priv->bin_window,
5710 x, y,
5711 &path,
5712 &column,
5713 NULL,
5714 NULL);
5715
5716 if (path != NULL)
5717 {
5718 pspp_sheet_view_scroll_to_cell (tree_view,
5719 path,
5720 column,
5721 TRUE,
5722 0.5, 0.5);
5723
5724 gtk_tree_path_free (path);
5725 }
5726 }
5727
5728 GDK_THREADS_LEAVE ();
5729
5730 return TRUE;
5731 }
5732 #endif /* 0 */
5733
5734 static void
5735 add_scroll_timeout (PsppSheetView *tree_view)
5736 {
5737 if (tree_view->priv->scroll_timeout == 0)
5738 {
5739 tree_view->priv->scroll_timeout =
5740 gdk_threads_add_timeout (150, scroll_row_timeout, tree_view);
5741 }
5742 }
5743
5744 static void
5745 remove_scroll_timeout (PsppSheetView *tree_view)
5746 {
5747 if (tree_view->priv->scroll_timeout != 0)
5748 {
5749 g_source_remove (tree_view->priv->scroll_timeout);
5750 tree_view->priv->scroll_timeout = 0;
5751 }
5752 }
5753
5754 static gboolean
5755 check_model_dnd (GtkTreeModel *model,
5756 GType required_iface,
5757 const gchar *signal)
5758 {
5759 if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
5760 {
5761 g_warning ("You must override the default '%s' handler "
5762 "on PsppSheetView when using models that don't support "
5763 "the %s interface and enabling drag-and-drop. The simplest way to do this "
5764 "is to connect to '%s' and call "
5765 "g_signal_stop_emission_by_name() in your signal handler to prevent "
5766 "the default handler from running. Look at the source code "
5767 "for the default handler in gtktreeview.c to get an idea what "
5768 "your handler should do. (gtktreeview.c is in the GTK source "
5769 "code.) If you're using GTK from a language other than C, "
5770 "there may be a more natural way to override default handlers, e.g. via derivation.",
5771 signal, g_type_name (required_iface), signal);
5772 return FALSE;
5773 }
5774 else
5775 return TRUE;
5776 }
5777
5778 static gboolean
5779 scroll_row_timeout (gpointer data)
5780 {
5781 PsppSheetView *tree_view = data;
5782
5783 pspp_sheet_view_horizontal_autoscroll (tree_view);
5784 pspp_sheet_view_vertical_autoscroll (tree_view);
5785
5786 if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
5787 pspp_sheet_view_update_rubber_band (tree_view);
5788
5789 return TRUE;
5790 }
5791
5792 /* Returns TRUE if event should not be propagated to parent widgets */
5793 static gboolean
5794 set_destination_row (PsppSheetView *tree_view,
5795 GdkDragContext *context,
5796 /* coordinates relative to the widget */
5797 gint x,
5798 gint y,
5799 GdkDragAction *suggested_action,
5800 GdkAtom *target)
5801 {
5802 GtkTreePath *path = NULL;
5803 PsppSheetViewDropPosition pos;
5804 PsppSheetViewDropPosition old_pos;
5805 TreeViewDragInfo *di;
5806 GtkWidget *widget;
5807 GtkTreePath *old_dest_path = NULL;
5808 gboolean can_drop = FALSE;
5809
5810 *suggested_action = 0;
5811 *target = GDK_NONE;
5812
5813 widget = GTK_WIDGET (tree_view);
5814
5815 di = get_info (tree_view);
5816
5817 if (di == NULL || y - TREE_VIEW_HEADER_HEIGHT (tree_view) < 0)
5818 {
5819 /* someone unset us as a drag dest, note that if
5820 * we return FALSE drag_leave isn't called
5821 */
5822
5823 pspp_sheet_view_set_drag_dest_row (tree_view,
5824 NULL,
5825 PSPP_SHEET_VIEW_DROP_BEFORE);
5826
5827 remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
5828
5829 return FALSE; /* no longer a drop site */
5830 }
5831
5832 *target = gtk_drag_dest_find_target (widget, context,
5833 gtk_drag_dest_get_target_list (widget));
5834 if (*target == GDK_NONE)
5835 {
5836 return FALSE;
5837 }
5838
5839 if (!pspp_sheet_view_get_dest_row_at_pos (tree_view,
5840 x, y,
5841 &path,
5842 &pos))
5843 {
5844 gint n_children;
5845 GtkTreeModel *model;
5846
5847 /* the row got dropped on empty space, let's setup a special case
5848 */
5849
5850 if (path)
5851 gtk_tree_path_free (path);
5852
5853 model = pspp_sheet_view_get_model (tree_view);
5854
5855 n_children = gtk_tree_model_iter_n_children (model, NULL);
5856 if (n_children)
5857 {
5858 pos = PSPP_SHEET_VIEW_DROP_AFTER;
5859 path = gtk_tree_path_new_from_indices (n_children - 1, -1);
5860 }
5861 else
5862 {
5863 pos = PSPP_SHEET_VIEW_DROP_BEFORE;
5864 path = gtk_tree_path_new_from_indices (0, -1);
5865 }
5866
5867 can_drop = TRUE;
5868
5869 goto out;
5870 }
5871
5872 g_assert (path);
5873
5874 /* If we left the current row's "open" zone, unset the timeout for
5875 * opening the row
5876 */
5877 pspp_sheet_view_get_drag_dest_row (tree_view,
5878 &old_dest_path,
5879 &old_pos);
5880
5881 if (old_dest_path)
5882 gtk_tree_path_free (old_dest_path);
5883
5884 if (TRUE /* FIXME if the location droppable predicate */)
5885 {
5886 can_drop = TRUE;
5887 }
5888
5889 out:
5890 if (can_drop)
5891 {
5892 GtkWidget *source_widget;
5893
5894 *suggested_action = context->suggested_action;
5895 source_widget = gtk_drag_get_source_widget (context);
5896
5897 if (source_widget == widget)
5898 {
5899 /* Default to MOVE, unless the user has
5900 * pressed ctrl or shift to affect available actions
5901 */
5902 if ((context->actions & GDK_ACTION_MOVE) != 0)
5903 *suggested_action = GDK_ACTION_MOVE;
5904 }
5905
5906 pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
5907 path, pos);
5908 }
5909 else
5910 {
5911 /* can't drop here */
5912 pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
5913 NULL,
5914 PSPP_SHEET_VIEW_DROP_BEFORE);
5915 }
5916
5917 if (path)
5918 gtk_tree_path_free (path);
5919
5920 return TRUE;
5921 }
5922
5923 static GtkTreePath*
5924 get_logical_dest_row (PsppSheetView *tree_view,
5925 gboolean *path_down_mode,
5926 gboolean *drop_append_mode)
5927 {
5928 /* adjust path to point to the row the drop goes in front of */
5929 GtkTreePath *path = NULL;
5930 PsppSheetViewDropPosition pos;
5931
5932 g_return_val_if_fail (path_down_mode != NULL, NULL);
5933 g_return_val_if_fail (drop_append_mode != NULL, NULL);
5934
5935 *path_down_mode = FALSE;
5936 *drop_append_mode = 0;
5937
5938 pspp_sheet_view_get_drag_dest_row (tree_view, &path, &pos);
5939
5940 if (path == NULL)
5941 return NULL;
5942
5943 if (pos == PSPP_SHEET_VIEW_DROP_BEFORE)
5944 ; /* do nothing */
5945 else if (pos == PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE ||
5946 pos == PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER)
5947 *path_down_mode = TRUE;
5948 else
5949 {
5950 GtkTreeIter iter;
5951 GtkTreeModel *model = pspp_sheet_view_get_model (tree_view);
5952
5953 g_assert (pos == PSPP_SHEET_VIEW_DROP_AFTER);
5954
5955 if (!gtk_tree_model_get_iter (model, &iter, path) ||
5956 !gtk_tree_model_iter_next (model, &iter))
5957 *drop_append_mode = 1;
5958 else
5959 {
5960 *drop_append_mode = 0;
5961 gtk_tree_path_next (path);
5962 }
5963 }
5964
5965 return path;
5966 }
5967
5968 static gboolean
5969 pspp_sheet_view_maybe_begin_dragging_row (PsppSheetView *tree_view,
5970 GdkEventMotion *event)
5971 {
5972 GtkWidget *widget = GTK_WIDGET (tree_view);
5973 GdkDragContext *context;
5974 TreeViewDragInfo *di;
5975 GtkTreePath *path = NULL;
5976 gint button;
5977 gint cell_x, cell_y;
5978 GtkTreeModel *model;
5979 gboolean retval = FALSE;
5980
5981 di = get_info (tree_view);
5982
5983 if (di == NULL || !di->source_set)
5984 goto out;
5985
5986 if (tree_view->priv->pressed_button < 0)
5987 goto out;
5988
5989 if (!gtk_drag_check_threshold (widget,
5990 tree_view->priv->press_start_x,
5991 tree_view->priv->press_start_y,
5992 event->x, event->y))
5993 goto out;
5994
5995 model = pspp_sheet_view_get_model (tree_view);
5996
5997 if (model == NULL)
5998 goto out;
5999
6000 button = tree_view->priv->pressed_button;
6001 tree_view->priv->pressed_button = -1;
6002
6003 pspp_sheet_view_get_path_at_pos (tree_view,
6004 tree_view->priv->press_start_x,
6005 tree_view->priv->press_start_y,
6006 &path,
6007 NULL,
6008 &cell_x,
6009 &cell_y);
6010
6011 if (path == NULL)
6012 goto out;
6013
6014 if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
6015 !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
6016 path))
6017 goto out;
6018
6019 if (!(GDK_BUTTON1_MASK << (button - 1) & di->start_button_mask))
6020 goto out;
6021
6022 /* Now we can begin the drag */
6023
6024 retval = TRUE;
6025
6026 context = gtk_drag_begin (widget,
6027 gtk_drag_source_get_target_list (widget),
6028 di->source_actions,
6029 button,
6030 (GdkEvent*)event);
6031
6032 set_source_row (context, model, path);
6033
6034 out:
6035 if (path)
6036 gtk_tree_path_free (path);
6037
6038 return retval;
6039 }
6040
6041
6042 static void
6043 pspp_sheet_view_drag_begin (GtkWidget *widget,
6044 GdkDragContext *context)
6045 {
6046 PsppSheetView *tree_view;
6047 GtkTreePath *path = NULL;
6048 gint cell_x, cell_y;
6049 GdkPixmap *row_pix;
6050 TreeViewDragInfo *di;
6051
6052 tree_view = PSPP_SHEET_VIEW (widget);
6053
6054 /* if the user uses a custom DND source impl, we don't set the icon here */
6055 di = get_info (tree_view);
6056
6057 if (di == NULL || !di->source_set)
6058 return;
6059
6060 pspp_sheet_view_get_path_at_pos (tree_view,
6061 tree_view->priv->press_start_x,
6062 tree_view->priv->press_start_y,
6063 &path,
6064 NULL,
6065 &cell_x,
6066 &cell_y);
6067
6068 g_return_if_fail (path != NULL);
6069
6070 row_pix = pspp_sheet_view_create_row_drag_icon (tree_view,
6071 path);
6072
6073 gtk_drag_set_icon_pixmap (context,
6074 gdk_drawable_get_colormap (row_pix),
6075 row_pix,
6076 NULL,
6077 /* the + 1 is for the black border in the icon */
6078 tree_view->priv->press_start_x + 1,
6079 cell_y + 1);
6080
6081 g_object_unref (row_pix);
6082 gtk_tree_path_free (path);
6083 }
6084
6085 static void
6086 pspp_sheet_view_drag_end (GtkWidget *widget,
6087 GdkDragContext *context)
6088 {
6089 /* do nothing */
6090 }
6091
6092 /* Default signal implementations for the drag signals */
6093 static void
6094 pspp_sheet_view_drag_data_get (GtkWidget *widget,
6095 GdkDragContext *context,
6096 GtkSelectionData *selection_data,
6097 guint info,
6098 guint time)
6099 {
6100 PsppSheetView *tree_view;
6101 GtkTreeModel *model;
6102 TreeViewDragInfo *di;
6103 GtkTreePath *source_row;
6104
6105 tree_view = PSPP_SHEET_VIEW (widget);
6106
6107 model = pspp_sheet_view_get_model (tree_view);
6108
6109 if (model == NULL)
6110 return;
6111
6112 di = get_info (PSPP_SHEET_VIEW (widget));
6113
6114 if (di == NULL)
6115 return;
6116
6117 source_row = get_source_row (context);
6118
6119 if (source_row == NULL)
6120 return;
6121
6122 /* We can implement the GTK_TREE_MODEL_ROW target generically for
6123 * any model; for DragSource models there are some other targets
6124 * we also support.
6125 */
6126
6127 if (GTK_IS_TREE_DRAG_SOURCE (model) &&
6128 gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
6129 source_row,
6130 selection_data))
6131 goto done;
6132
6133 /* If drag_data_get does nothing, try providing row data. */
6134 if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
6135 {
6136 gtk_tree_set_row_drag_data (selection_data,
6137 model,
6138 source_row);
6139 }
6140
6141 done:
6142 gtk_tree_path_free (source_row);
6143 }
6144
6145
6146 static void
6147 pspp_sheet_view_drag_data_delete (GtkWidget *widget,
6148 GdkDragContext *context)
6149 {
6150 TreeViewDragInfo *di;
6151 GtkTreeModel *model;
6152 PsppSheetView *tree_view;
6153 GtkTreePath *source_row;
6154
6155 tree_view = PSPP_SHEET_VIEW (widget);
6156 model = pspp_sheet_view_get_model (tree_view);
6157
6158 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
6159 return;
6160
6161 di = get_info (tree_view);
6162
6163 if (di == NULL)
6164 return;
6165
6166 source_row = get_source_row (context);
6167
6168 if (source_row == NULL)
6169 return;
6170
6171 gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
6172 source_row);
6173
6174 gtk_tree_path_free (source_row);
6175
6176 set_source_row (context, NULL, NULL);
6177 }
6178
6179 static void
6180 pspp_sheet_view_drag_leave (GtkWidget *widget,
6181 GdkDragContext *context,
6182 guint time)
6183 {
6184 /* unset any highlight row */
6185 pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
6186 NULL,
6187 PSPP_SHEET_VIEW_DROP_BEFORE);
6188
6189 remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
6190 }
6191
6192
6193 static gboolean
6194 pspp_sheet_view_drag_motion (GtkWidget *widget,
6195 GdkDragContext *context,
6196 /* coordinates relative to the widget */
6197 gint x,
6198 gint y,
6199 guint time)
6200 {
6201 gboolean empty;
6202 GtkTreePath *path = NULL;
6203 PsppSheetViewDropPosition pos;
6204 PsppSheetView *tree_view;
6205 GdkDragAction suggested_action = 0;
6206 GdkAtom target;
6207
6208 tree_view = PSPP_SHEET_VIEW (widget);
6209
6210 if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
6211 return FALSE;
6212
6213 pspp_sheet_view_get_drag_dest_row (tree_view, &path, &pos);
6214
6215 /* we only know this *after* set_desination_row */
6216 empty = tree_view->priv->empty_view_drop;
6217
6218 if (path == NULL && !empty)
6219 {
6220 /* Can't drop here. */
6221 gdk_drag_status (context, 0, time);
6222 }
6223 else
6224 {
6225 if (tree_view->priv->open_dest_timeout == 0 &&
6226 (pos == PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER ||
6227 pos == PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE))
6228 {
6229 /* Nothing. */
6230 }
6231 else
6232 {
6233 add_scroll_timeout (tree_view);
6234 }
6235
6236 if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
6237 {
6238 /* Request data so we can use the source row when
6239 * determining whether to accept the drop
6240 */
6241 set_status_pending (context, suggested_action);
6242 gtk_drag_get_data (widget, context, target, time);
6243 }
6244 else
6245 {
6246 set_status_pending (context, 0);
6247 gdk_drag_status (context, suggested_action, time);
6248 }
6249 }
6250
6251 if (path)
6252 gtk_tree_path_free (path);
6253
6254 return TRUE;
6255 }
6256
6257
6258 static gboolean
6259 pspp_sheet_view_drag_drop (GtkWidget *widget,
6260 GdkDragContext *context,
6261 /* coordinates relative to the widget */
6262 gint x,
6263 gint y,
6264 guint time)
6265 {
6266 PsppSheetView *tree_view;
6267 GtkTreePath *path;
6268 GdkDragAction suggested_action = 0;
6269 GdkAtom target = GDK_NONE;
6270 TreeViewDragInfo *di;
6271 GtkTreeModel *model;
6272 gboolean path_down_mode;
6273 gboolean drop_append_mode;
6274
6275 tree_view = PSPP_SHEET_VIEW (widget);
6276
6277 model = pspp_sheet_view_get_model (tree_view);
6278
6279 remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
6280
6281 di = get_info (tree_view);
6282
6283 if (di == NULL)
6284 return FALSE;
6285
6286 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
6287 return FALSE;
6288
6289 if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
6290 return FALSE;
6291
6292 path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
6293
6294 if (target != GDK_NONE && path != NULL)
6295 {
6296 /* in case a motion had requested drag data, change things so we
6297 * treat drag data receives as a drop.
6298 */
6299 set_status_pending (context, 0);
6300 set_dest_row (context, model, path,
6301 path_down_mode, tree_view->priv->empty_view_drop,
6302 drop_append_mode);
6303 }
6304
6305 if (path)
6306 gtk_tree_path_free (path);
6307
6308 /* Unset this thing */
6309 pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
6310 NULL,
6311 PSPP_SHEET_VIEW_DROP_BEFORE);
6312
6313 if (target != GDK_NONE)
6314 {
6315 gtk_drag_get_data (widget, context, target, time);
6316 return TRUE;
6317 }
6318 else
6319 return FALSE;
6320 }
6321
6322 static void
6323 pspp_sheet_view_drag_data_received (GtkWidget *widget,
6324 GdkDragContext *context,
6325 /* coordinates relative to the widget */
6326 gint x,
6327 gint y,
6328 GtkSelectionData *selection_data,
6329 guint info,
6330 guint time)
6331 {
6332 GtkTreePath *path;
6333 TreeViewDragInfo *di;
6334 gboolean accepted = FALSE;
6335 GtkTreeModel *model;
6336 PsppSheetView *tree_view;
6337 GtkTreePath *dest_row;
6338 GdkDragAction suggested_action;
6339 gboolean path_down_mode;
6340 gboolean drop_append_mode;
6341
6342 tree_view = PSPP_SHEET_VIEW (widget);
6343
6344 model = pspp_sheet_view_get_model (tree_view);
6345
6346 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
6347 return;
6348
6349 di = get_info (tree_view);
6350
6351 if (di == NULL)
6352 return;
6353
6354 suggested_action = get_status_pending (context);
6355
6356 if (suggested_action)
6357 {
6358 /* We are getting this data due to a request in drag_motion,
6359 * rather than due to a request in drag_drop, so we are just
6360 * supposed to call drag_status, not actually paste in the
6361 * data.
6362 */
6363 path = get_logical_dest_row (tree_view, &path_down_mode,
6364 &drop_append_mode);
6365
6366 if (path == NULL)
6367 suggested_action = 0;
6368 else if (path_down_mode)
6369 gtk_tree_path_down (path);
6370
6371 if (suggested_action)
6372 {
6373 if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
6374 path,
6375 selection_data))
6376 {
6377 if (path_down_mode)
6378 {
6379 path_down_mode = FALSE;
6380 gtk_tree_path_up (path);
6381
6382 if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
6383 path,
6384 selection_data))
6385 suggested_action = 0;
6386 }
6387 else
6388 suggested_action = 0;
6389 }
6390 }
6391
6392 gdk_drag_status (context, suggested_action, time);
6393
6394 if (path)
6395 gtk_tree_path_free (path);
6396
6397 /* If you can't drop, remove user drop indicator until the next motion */
6398 if (suggested_action == 0)
6399 pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
6400 NULL,
6401 PSPP_SHEET_VIEW_DROP_BEFORE);
6402
6403 return;
6404 }
6405
6406 dest_row = get_dest_row (context, &path_down_mode);
6407
6408 if (dest_row == NULL)
6409 return;
6410
6411 if (selection_data->length >= 0)
6412 {
6413 if (path_down_mode)
6414 {
6415 gtk_tree_path_down (dest_row);
6416 if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
6417 dest_row, selection_data))
6418 gtk_tree_path_up (dest_row);
6419 }
6420 }
6421
6422 if (selection_data->length >= 0)
6423 {
6424 if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
6425 dest_row,
6426 selection_data))
6427 accepted = TRUE;
6428 }
6429
6430 gtk_drag_finish (context,
6431 accepted,
6432 (context->action == GDK_ACTION_MOVE),
6433 time);
6434
6435 if (gtk_tree_path_get_depth (dest_row) == 1
6436 && gtk_tree_path_get_indices (dest_row)[0] == 0)
6437 {
6438 /* special special case drag to "0", scroll to first item */
6439 if (!tree_view->priv->scroll_to_path)
6440 pspp_sheet_view_scroll_to_cell (tree_view, dest_row, NULL, FALSE, 0.0, 0.0);
6441 }
6442
6443 gtk_tree_path_free (dest_row);
6444
6445 /* drop dest_row */
6446 set_dest_row (context, NULL, NULL, FALSE, FALSE, FALSE);
6447 }
6448
6449
6450
6451 /* GtkContainer Methods
6452 */
6453
6454
6455 static void
6456 pspp_sheet_view_remove (GtkContainer *container,
6457 GtkWidget *widget)
6458 {
6459 PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
6460 PsppSheetViewChild *child = NULL;
6461 GList *tmp_list;
6462
6463 tmp_list = tree_view->priv->children;
6464 while (tmp_list)
6465 {
6466 child = tmp_list->data;
6467 if (child->widget == widget)
6468 {
6469 gtk_widget_unparent (widget);
6470
6471 tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
6472 g_list_free_1 (tmp_list);
6473 g_slice_free (PsppSheetViewChild, child);
6474 return;
6475 }
6476
6477 tmp_list = tmp_list->next;
6478 }
6479
6480 tmp_list = tree_view->priv->columns;
6481
6482 while (tmp_list)
6483 {
6484 PsppSheetViewColumn *column;
6485 column = tmp_list->data;
6486 if (column->button == widget)
6487 {
6488 gtk_widget_unparent (widget);
6489 return;
6490 }
6491 tmp_list = tmp_list->next;
6492 }
6493 }
6494
6495 static void
6496 pspp_sheet_view_forall (GtkContainer *container,
6497 gboolean include_internals,
6498 GtkCallback callback,
6499 gpointer callback_data)
6500 {
6501 PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
6502 PsppSheetViewChild *child = NULL;
6503 PsppSheetViewColumn *column;
6504 GList *tmp_list;
6505
6506 tmp_list = tree_view->priv->children;
6507 while (tmp_list)
6508 {
6509 child = tmp_list->data;
6510 tmp_list = tmp_list->next;
6511
6512 (* callback) (child->widget, callback_data);
6513 }
6514 if (include_internals == FALSE)
6515 return;
6516
6517 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
6518 {
6519 column = tmp_list->data;
6520
6521 if (column->button)
6522 (* callback) (column->button, callback_data);
6523 }
6524 }
6525
6526 /* Returns TRUE if the treeview contains no "special" (editable or activatable)
6527 * cells. If so we draw one big row-spanning focus rectangle.
6528 */
6529 static gboolean
6530 pspp_sheet_view_has_special_cell (PsppSheetView *tree_view)
6531 {
6532 GList *list;
6533
6534 if (tree_view->priv->special_cells != PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT)
6535 return tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_YES;
6536
6537 for (list = tree_view->priv->columns; list; list = list->next)
6538 {
6539 if (!((PsppSheetViewColumn *)list->data)->visible)
6540 continue;
6541 if (_pspp_sheet_view_column_count_special_cells (list->data))
6542 return TRUE;
6543 }
6544
6545 return FALSE;
6546 }
6547
6548 static void
6549 pspp_sheet_view_focus_column (PsppSheetView *tree_view,
6550 PsppSheetViewColumn *focus_column,
6551 gboolean clamp_column_visible)
6552 {
6553 g_return_if_fail (focus_column != NULL);
6554
6555 tree_view->priv->focus_column = focus_column;
6556 if (!focus_column->button)
6557 {
6558 pspp_sheet_view_column_set_need_button (focus_column, TRUE);
6559 g_return_if_fail (focus_column->button != NULL);
6560 }
6561
6562 if (GTK_CONTAINER (tree_view)->focus_child != focus_column->button)
6563 gtk_widget_grab_focus (focus_column->button);
6564
6565 if (clamp_column_visible)
6566 pspp_sheet_view_clamp_column_visible (tree_view, focus_column, FALSE);
6567 }
6568
6569 /* Returns TRUE if the focus is within the headers, after the focus operation is
6570 * done
6571 */
6572 static gboolean
6573 pspp_sheet_view_header_focus (PsppSheetView *tree_view,
6574 GtkDirectionType dir,
6575 gboolean clamp_column_visible)
6576 {
6577 GtkWidget *focus_child;
6578 PsppSheetViewColumn *focus_column;
6579 GList *last_column, *first_column;
6580 GList *tmp_list;
6581 gboolean rtl;
6582
6583 if (! PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
6584 return FALSE;
6585
6586 focus_child = GTK_CONTAINER (tree_view)->focus_child;
6587
6588 first_column = tree_view->priv->columns;
6589 while (first_column)
6590 {
6591 PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (first_column->data);
6592
6593 if (pspp_sheet_view_column_can_focus (c) && c->visible)
6594 break;
6595 first_column = first_column->next;
6596 }
6597
6598 /* No headers are visible, or are focusable. We can't focus in or out.
6599 */
6600 if (first_column == NULL)
6601 return FALSE;
6602
6603 last_column = g_list_last (tree_view->priv->columns);
6604 while (last_column)
6605 {
6606 PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (last_column->data);
6607
6608 if (pspp_sheet_view_column_can_focus (c) && c->visible)
6609 break;
6610 last_column = last_column->prev;
6611 }
6612
6613
6614 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
6615
6616 switch (dir)
6617 {
6618 case GTK_DIR_TAB_BACKWARD:
6619 case GTK_DIR_TAB_FORWARD:
6620 case GTK_DIR_UP:
6621 case GTK_DIR_DOWN:
6622 if (focus_child == NULL)
6623 {
6624 if (tree_view->priv->focus_column != NULL &&
6625 pspp_sheet_view_column_can_focus (tree_view->priv->focus_column))
6626 focus_column = tree_view->priv->focus_column;
6627 else
6628 focus_column = first_column->data;
6629 pspp_sheet_view_focus_column (tree_view, focus_column,
6630 clamp_column_visible);
6631 return TRUE;
6632 }
6633 return FALSE;
6634
6635 case GTK_DIR_LEFT:
6636 case GTK_DIR_RIGHT:
6637 if (focus_child == NULL)
6638 {
6639 if (tree_view->priv->focus_column != NULL)
6640 focus_column = tree_view->priv->focus_column;
6641 else if (dir == GTK_DIR_LEFT)
6642 focus_column = last_column->data;
6643 else
6644 focus_column = first_column->data;
6645 pspp_sheet_view_focus_column (tree_view, focus_column,
6646 clamp_column_visible);
6647 return TRUE;
6648 }
6649
6650 if (gtk_widget_child_focus (focus_child, dir))
6651 {
6652 /* The focus moves inside the button. */
6653 /* This is probably a great example of bad UI */
6654 if (clamp_column_visible)
6655 pspp_sheet_view_clamp_column_visible (tree_view,
6656 tree_view->priv->focus_column,
6657 FALSE);
6658 return TRUE;
6659 }
6660
6661 /* We need to move the focus among the row of buttons. */
6662 for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
6663 if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data)->button == focus_child)
6664 break;
6665
6666 if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT))
6667 || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)))
6668 {
6669 gtk_widget_error_bell (GTK_WIDGET (tree_view));
6670 return TRUE;
6671 }
6672
6673 while (tmp_list)
6674 {
6675 PsppSheetViewColumn *column;
6676
6677 if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))
6678 tmp_list = tmp_list->next;
6679 else
6680 tmp_list = tmp_list->prev;
6681
6682 if (tmp_list == NULL)
6683 {
6684 g_warning ("Internal button not found");
6685 break;
6686 }
6687 column = tmp_list->data;
6688 if (column->button &&
6689 column->visible &&
6690 pspp_sheet_view_column_can_focus (column))
6691 {
6692 pspp_sheet_view_focus_column (tree_view, column,
6693 clamp_column_visible);
6694 return TRUE;
6695 }
6696 }
6697 return FALSE;
6698
6699 default:
6700 g_assert_not_reached ();
6701 break;
6702 }
6703
6704 return FALSE;
6705 }
6706
6707 /* This function returns in 'path' the first focusable path, if the given path
6708 * is already focusable, it's the returned one.
6709 *
6710 */
6711 static gboolean
6712 search_first_focusable_path (PsppSheetView *tree_view,
6713 GtkTreePath **path,
6714 gboolean search_forward,
6715 int *new_node)
6716 {
6717 /* XXX this function is trivial given that the sheetview doesn't support
6718 separator rows */
6719 int node = -1;
6720
6721 if (!path || !*path)
6722 return FALSE;
6723
6724 _pspp_sheet_view_find_node (tree_view, *path, &node);
6725
6726 if (node < 0)
6727 return FALSE;
6728
6729 if (new_node)
6730 *new_node = node;
6731
6732 return (*path != NULL);
6733 }
6734
6735 static gint
6736 pspp_sheet_view_focus (GtkWidget *widget,
6737 GtkDirectionType direction)
6738 {
6739 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
6740 GtkContainer *container = GTK_CONTAINER (widget);
6741 GtkWidget *focus_child;
6742
6743 if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
6744 return FALSE;
6745
6746 focus_child = container->focus_child;
6747
6748 pspp_sheet_view_stop_editing (PSPP_SHEET_VIEW (widget), FALSE);
6749 /* Case 1. Headers currently have focus. */
6750 if (focus_child)
6751 {
6752 switch (direction)
6753 {
6754 case GTK_DIR_LEFT:
6755 case GTK_DIR_RIGHT:
6756 pspp_sheet_view_header_focus (tree_view, direction, TRUE);
6757 return TRUE;
6758 case GTK_DIR_TAB_BACKWARD:
6759 case GTK_DIR_UP:
6760 return FALSE;
6761 case GTK_DIR_TAB_FORWARD:
6762 case GTK_DIR_DOWN:
6763 gtk_widget_grab_focus (widget);
6764 return TRUE;
6765 default:
6766 g_assert_not_reached ();
6767 return FALSE;
6768 }
6769 }
6770
6771 /* Case 2. We don't have focus at all. */
6772 if (!gtk_widget_has_focus (widget))
6773 {
6774 if (!pspp_sheet_view_header_focus (tree_view, direction, FALSE))
6775 gtk_widget_grab_focus (widget);
6776 return TRUE;
6777 }
6778
6779 /* Case 3. We have focus already. */
6780 if (direction == GTK_DIR_TAB_BACKWARD)
6781 return (pspp_sheet_view_header_focus (tree_view, direction, FALSE));
6782 else if (direction == GTK_DIR_TAB_FORWARD)
6783 return FALSE;
6784
6785 /* Other directions caught by the keybindings */
6786 gtk_widget_grab_focus (widget);
6787 return TRUE;
6788 }
6789
6790 static void
6791 pspp_sheet_view_grab_focus (GtkWidget *widget)
6792 {
6793 GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->grab_focus (widget);
6794
6795 pspp_sheet_view_focus_to_cursor (PSPP_SHEET_VIEW (widget));
6796 }
6797
6798 static void
6799 pspp_sheet_view_style_set (GtkWidget *widget,
6800 GtkStyle *previous_style)
6801 {
6802 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
6803 GList *list;
6804 PsppSheetViewColumn *column;
6805
6806 if (gtk_widget_get_realized (widget))
6807 {
6808 gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
6809 gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
6810 gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
6811
6812 pspp_sheet_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
6813 }
6814
6815 gtk_widget_style_get (widget,
6816 "expander-size", &tree_view->priv->expander_size,
6817 NULL);
6818 tree_view->priv->expander_size += EXPANDER_EXTRA_PADDING;
6819
6820 for (list = tree_view->priv->columns; list; list = list->next)
6821 {
6822 column = list->data;
6823 _pspp_sheet_view_column_cell_set_dirty (column);
6824 }
6825
6826 tree_view->priv->fixed_height = -1;
6827
6828 /* Invalidate cached button style. */
6829 if (tree_view->priv->button_style)
6830 {
6831 g_object_unref (tree_view->priv->button_style);
6832 tree_view->priv->button_style = NULL;
6833 }
6834
6835 gtk_widget_queue_resize (widget);
6836 }
6837
6838
6839 static void
6840 pspp_sheet_view_set_focus_child (GtkContainer *container,
6841 GtkWidget *child)
6842 {
6843 PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
6844 GList *list;
6845
6846 for (list = tree_view->priv->columns; list; list = list->next)
6847 {
6848 if (PSPP_SHEET_VIEW_COLUMN (list->data)->button == child)
6849 {
6850 tree_view->priv->focus_column = PSPP_SHEET_VIEW_COLUMN (list->data);
6851 break;
6852 }
6853 }
6854
6855 GTK_CONTAINER_CLASS (pspp_sheet_view_parent_class)->set_focus_child (container, child);
6856 }
6857
6858 static void
6859 pspp_sheet_view_set_adjustments (PsppSheetView *tree_view,
6860 GtkAdjustment *hadj,
6861 GtkAdjustment *vadj)
6862 {
6863 gboolean need_adjust = FALSE;
6864
6865 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
6866
6867 if (hadj)
6868 g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
6869 else
6870 hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
6871 if (vadj)
6872 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
6873 else
6874 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
6875
6876 if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
6877 {
6878 g_signal_handlers_disconnect_by_func (tree_view->priv->hadjustment,
6879 pspp_sheet_view_adjustment_changed,
6880 tree_view);
6881 g_object_unref (tree_view->priv->hadjustment);
6882 }
6883
6884 if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
6885 {
6886 g_signal_handlers_disconnect_by_func (tree_view->priv->vadjustment,
6887 pspp_sheet_view_adjustment_changed,
6888 tree_view);
6889 g_object_unref (tree_view->priv->vadjustment);
6890 }
6891
6892 if (tree_view->priv->hadjustment != hadj)
6893 {
6894 tree_view->priv->hadjustment = hadj;
6895 g_object_ref_sink (tree_view->priv->hadjustment);
6896
6897 g_signal_connect (tree_view->priv->hadjustment, "value-changed",
6898 G_CALLBACK (pspp_sheet_view_adjustment_changed),
6899 tree_view);
6900 need_adjust = TRUE;
6901 }
6902
6903 if (tree_view->priv->vadjustment != vadj)
6904 {
6905 tree_view->priv->vadjustment = vadj;
6906 g_object_ref_sink (tree_view->priv->vadjustment);
6907
6908 g_signal_connect (tree_view->priv->vadjustment, "value-changed",
6909 G_CALLBACK (pspp_sheet_view_adjustment_changed),
6910 tree_view);
6911 need_adjust = TRUE;
6912 }
6913
6914 if (need_adjust)
6915 pspp_sheet_view_adjustment_changed (NULL, tree_view);
6916 }
6917
6918
6919 static gboolean
6920 pspp_sheet_view_real_move_cursor (PsppSheetView *tree_view,
6921 GtkMovementStep step,
6922 gint count)
6923 {
6924 GdkModifierType state;
6925
6926 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
6927 g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
6928 step == GTK_MOVEMENT_VISUAL_POSITIONS ||
6929 step == GTK_MOVEMENT_DISPLAY_LINES ||
6930 step == GTK_MOVEMENT_PAGES ||
6931 step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
6932
6933 if (tree_view->priv->row_count == 0)
6934 return FALSE;
6935 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
6936 return FALSE;
6937
6938 pspp_sheet_view_stop_editing (tree_view, FALSE);
6939 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
6940 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
6941
6942 if (gtk_get_current_event_state (&state))
6943 {
6944 if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
6945 tree_view->priv->ctrl_pressed = TRUE;
6946 if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
6947 tree_view->priv->shift_pressed = TRUE;
6948 }
6949 /* else we assume not pressed */
6950
6951 switch (step)
6952 {
6953 /* currently we make no distinction. When we go bi-di, we need to */
6954 case GTK_MOVEMENT_LOGICAL_POSITIONS:
6955 case GTK_MOVEMENT_VISUAL_POSITIONS:
6956 pspp_sheet_view_move_cursor_left_right (tree_view, count);
6957 break;
6958 case GTK_MOVEMENT_DISPLAY_LINES:
6959 pspp_sheet_view_move_cursor_up_down (tree_view, count);
6960 break;
6961 case GTK_MOVEMENT_PAGES:
6962 pspp_sheet_view_move_cursor_page_up_down (tree_view, count);
6963 break;
6964 case GTK_MOVEMENT_BUFFER_ENDS:
6965 pspp_sheet_view_move_cursor_start_end (tree_view, count);
6966 break;
6967 default:
6968 g_assert_not_reached ();
6969 }
6970
6971 tree_view->priv->ctrl_pressed = FALSE;
6972 tree_view->priv->shift_pressed = FALSE;
6973
6974 return TRUE;
6975 }
6976
6977 static void
6978 pspp_sheet_view_put (PsppSheetView *tree_view,
6979 GtkWidget *child_widget,
6980 /* in bin_window coordinates */
6981 gint x,
6982 gint y,
6983 gint width,
6984 gint height)
6985 {
6986 PsppSheetViewChild *child;
6987
6988 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
6989 g_return_if_fail (GTK_IS_WIDGET (child_widget));
6990
6991 child = g_slice_new (PsppSheetViewChild);
6992
6993 child->widget = child_widget;
6994 child->x = x;
6995 child->y = y;
6996 child->width = width;
6997 child->height = height;
6998
6999 tree_view->priv->children = g_list_append (tree_view->priv->children, child);
7000
7001 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
7002 gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
7003
7004 gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
7005 }
7006
7007 void
7008 _pspp_sheet_view_child_move_resize (PsppSheetView *tree_view,
7009 GtkWidget *widget,
7010 /* in tree coordinates */
7011 gint x,
7012 gint y,
7013 gint width,
7014 gint height)
7015 {
7016 PsppSheetViewChild *child = NULL;
7017 GList *list;
7018 GdkRectangle allocation;
7019
7020 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
7021 g_return_if_fail (GTK_IS_WIDGET (widget));
7022
7023 for (list = tree_view->priv->children; list; list = list->next)
7024 {
7025 if (((PsppSheetViewChild *)list->data)->widget == widget)
7026 {
7027 child = list->data;
7028 break;
7029 }
7030 }
7031 if (child == NULL)
7032 return;
7033
7034 allocation.x = child->x = x;
7035 allocation.y = child->y = y;
7036 allocation.width = child->width = width;
7037 allocation.height = child->height = height;
7038
7039 if (gtk_widget_get_realized (widget))
7040 gtk_widget_size_allocate (widget, &allocation);
7041 }
7042
7043
7044 /* TreeModel Callbacks
7045 */
7046
7047 static void
7048 pspp_sheet_view_row_changed (GtkTreeModel *model,
7049 GtkTreePath *path,
7050 GtkTreeIter *iter,
7051 gpointer data)
7052 {
7053 PsppSheetView *tree_view = (PsppSheetView *)data;
7054 int node;
7055 gboolean free_path = FALSE;
7056 GtkTreePath *cursor_path;
7057
7058 g_return_if_fail (path != NULL || iter != NULL);
7059
7060 if (tree_view->priv->cursor != NULL)
7061 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7062 else
7063 cursor_path = NULL;
7064
7065 if (tree_view->priv->edited_column &&
7066 (cursor_path == NULL || gtk_tree_path_compare (cursor_path, path) == 0))
7067 pspp_sheet_view_stop_editing (tree_view, TRUE);
7068
7069 if (cursor_path != NULL)
7070 gtk_tree_path_free (cursor_path);
7071
7072 if (path == NULL)
7073 {
7074 path = gtk_tree_model_get_path (model, iter);
7075 free_path = TRUE;
7076 }
7077 else if (iter == NULL)
7078 gtk_tree_model_get_iter (model, iter, path);
7079
7080 _pspp_sheet_view_find_node (tree_view,
7081 path,
7082 &node);
7083
7084 if (node >= 0)
7085 {
7086 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
7087 pspp_sheet_view_node_queue_redraw (tree_view, node);
7088 }
7089
7090 if (free_path)
7091 gtk_tree_path_free (path);
7092 }
7093
7094 static void
7095 pspp_sheet_view_row_inserted (GtkTreeModel *model,
7096 GtkTreePath *path,
7097 GtkTreeIter *iter,
7098 gpointer data)
7099 {
7100 PsppSheetView *tree_view = (PsppSheetView *) data;
7101 gint *indices;
7102 int tmpnode = -1;
7103 gint height = tree_view->priv->fixed_height;
7104 gboolean free_path = FALSE;
7105 gboolean node_visible = TRUE;
7106
7107 g_return_if_fail (path != NULL || iter != NULL);
7108
7109 if (path == NULL)
7110 {
7111 path = gtk_tree_model_get_path (model, iter);
7112 free_path = TRUE;
7113 }
7114 else if (iter == NULL)
7115 gtk_tree_model_get_iter (model, iter, path);
7116
7117 tree_view->priv->row_count = gtk_tree_model_iter_n_children (model, NULL);
7118
7119 /* Update all row-references */
7120 gtk_tree_row_reference_inserted (G_OBJECT (data), path);
7121 indices = gtk_tree_path_get_indices (path);
7122 tmpnode = indices[0];
7123
7124 range_tower_insert0 (tree_view->priv->selected, tmpnode, 1);
7125
7126 if (height > 0)
7127 {
7128 if (node_visible && node_is_visible (tree_view, tmpnode))
7129 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
7130 else
7131 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
7132 }
7133 else
7134 install_presize_handler (tree_view);
7135 if (free_path)
7136 gtk_tree_path_free (path);
7137 }
7138
7139 static void
7140 pspp_sheet_view_row_deleted (GtkTreeModel *model,
7141 GtkTreePath *path,
7142 gpointer data)
7143 {
7144 PsppSheetView *tree_view = (PsppSheetView *)data;
7145 int node;
7146
7147 g_return_if_fail (path != NULL);
7148
7149 gtk_tree_row_reference_deleted (G_OBJECT (data), path);
7150
7151 _pspp_sheet_view_find_node (tree_view, path, &node);
7152
7153 if (node < 0)
7154 return;
7155
7156 range_tower_delete (tree_view->priv->selected, node, 1);
7157
7158 /* Ensure we don't have a dangling pointer to a dead node */
7159 ensure_unprelighted (tree_view);
7160
7161 /* Cancel editting if we've started */
7162 pspp_sheet_view_stop_editing (tree_view, TRUE);
7163
7164 if (tree_view->priv->destroy_count_func)
7165 {
7166 gint child_count = 0;
7167 tree_view->priv->destroy_count_func (tree_view, path, child_count, tree_view->priv->destroy_count_data);
7168 }
7169
7170 tree_view->priv->row_count = gtk_tree_model_iter_n_children (model, NULL);
7171
7172 if (! gtk_tree_row_reference_valid (tree_view->priv->top_row))
7173 {
7174 gtk_tree_row_reference_free (tree_view->priv->top_row);
7175 tree_view->priv->top_row = NULL;
7176 }
7177
7178 install_scroll_sync_handler (tree_view);
7179
7180 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
7181
7182 #if 0
7183 if (helper_data.changed)
7184 g_signal_emit_by_name (tree_view->priv->selection, "changed");
7185 #endif
7186 }
7187
7188 static void
7189 pspp_sheet_view_rows_reordered (GtkTreeModel *model,
7190 GtkTreePath *parent,
7191 GtkTreeIter *iter,
7192 gint *new_order,
7193 gpointer data)
7194 {
7195 PsppSheetView *tree_view = PSPP_SHEET_VIEW (data);
7196 gint len;
7197
7198 /* XXX need to adjust selection */
7199 len = gtk_tree_model_iter_n_children (model, iter);
7200
7201 if (len < 2)
7202 return;
7203
7204 gtk_tree_row_reference_reordered (G_OBJECT (data),
7205 parent,
7206 iter,
7207 new_order);
7208
7209 if (gtk_tree_path_get_depth (parent) != 0)
7210 return;
7211
7212 if (tree_view->priv->edited_column)
7213 pspp_sheet_view_stop_editing (tree_view, TRUE);
7214
7215 /* we need to be unprelighted */
7216 ensure_unprelighted (tree_view);
7217
7218 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
7219
7220 pspp_sheet_view_dy_to_top_row (tree_view);
7221 }
7222
7223
7224 /* Internal tree functions
7225 */
7226
7227
7228 static void
7229 pspp_sheet_view_get_background_xrange (PsppSheetView *tree_view,
7230 PsppSheetViewColumn *column,
7231 gint *x1,
7232 gint *x2)
7233 {
7234 PsppSheetViewColumn *tmp_column = NULL;
7235 gint total_width;
7236 GList *list;
7237 gboolean rtl;
7238
7239 if (x1)
7240 *x1 = 0;
7241
7242 if (x2)
7243 *x2 = 0;
7244
7245 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7246
7247 total_width = 0;
7248 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
7249 list;
7250 list = (rtl ? list->prev : list->next))
7251 {
7252 tmp_column = list->data;
7253
7254 if (tmp_column == column)
7255 break;
7256
7257 if (tmp_column->visible)
7258 total_width += tmp_column->width;
7259 }
7260
7261 if (tmp_column != column)
7262 {
7263 g_warning (G_STRLOC": passed-in column isn't in the tree");
7264 return;
7265 }
7266
7267 if (x1)
7268 *x1 = total_width;
7269
7270 if (x2)
7271 {
7272 if (column->visible)
7273 *x2 = total_width + column->width;
7274 else
7275 *x2 = total_width; /* width of 0 */
7276 }
7277 }
7278
7279 /* Make sure the node is visible vertically */
7280 static void
7281 pspp_sheet_view_clamp_node_visible (PsppSheetView *tree_view,
7282 int node)
7283 {
7284 gint node_dy, height;
7285 GtkTreePath *path = NULL;
7286
7287 if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
7288 return;
7289
7290 /* just return if the node is visible, avoiding a costly expose */
7291 node_dy = pspp_sheet_view_node_find_offset (tree_view, node);
7292 height = ROW_HEIGHT (tree_view);
7293 if (node_dy >= tree_view->priv->vadjustment->value
7294 && node_dy + height <= (tree_view->priv->vadjustment->value
7295 + tree_view->priv->vadjustment->page_size))
7296 return;
7297
7298 path = _pspp_sheet_view_find_path (tree_view, node);
7299 if (path)
7300 {
7301 /* We process updates because we want to clear old selected items when we scroll.
7302 * if this is removed, we get a "selection streak" at the bottom. */
7303 gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
7304 pspp_sheet_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
7305 gtk_tree_path_free (path);
7306 }
7307 }
7308
7309 static void
7310 pspp_sheet_view_clamp_column_visible (PsppSheetView *tree_view,
7311 PsppSheetViewColumn *column,
7312 gboolean focus_to_cell)
7313 {
7314 gint x, width;
7315
7316 if (column == NULL)
7317 return;
7318
7319 x = column->allocation.x;
7320 width = column->allocation.width;
7321
7322 if (width > tree_view->priv->hadjustment->page_size)
7323 {
7324 /* The column is larger than the horizontal page size. If the
7325 * column has cells which can be focussed individually, then we make
7326 * sure the cell which gets focus is fully visible (if even the
7327 * focus cell is bigger than the page size, we make sure the
7328 * left-hand side of the cell is visible).
7329 *
7330 * If the column does not have those so-called special cells, we
7331 * make sure the left-hand side of the column is visible.
7332 */
7333
7334 if (focus_to_cell && pspp_sheet_view_has_special_cell (tree_view))
7335 {
7336 GtkTreePath *cursor_path;
7337 GdkRectangle background_area, cell_area, focus_area;
7338
7339 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7340
7341 pspp_sheet_view_get_cell_area (tree_view,
7342 cursor_path, column, &cell_area);
7343 pspp_sheet_view_get_background_area (tree_view,
7344 cursor_path, column,
7345 &background_area);
7346
7347 gtk_tree_path_free (cursor_path);
7348
7349 _pspp_sheet_view_column_get_focus_area (column,
7350 &background_area,
7351 &cell_area,
7352 &focus_area);
7353
7354 x = focus_area.x;
7355 width = focus_area.width;
7356
7357 if (width < tree_view->priv->hadjustment->page_size)
7358 {
7359 if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < (x + width))
7360 gtk_adjustment_set_value (tree_view->priv->hadjustment,
7361 x + width - tree_view->priv->hadjustment->page_size);
7362 else if (tree_view->priv->hadjustment->value > x)
7363 gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
7364 }
7365 }
7366
7367 gtk_adjustment_set_value (tree_view->priv->hadjustment,
7368 CLAMP (x,
7369 tree_view->priv->hadjustment->lower,
7370 tree_view->priv->hadjustment->upper
7371 - tree_view->priv->hadjustment->page_size));
7372 }
7373 else
7374 {
7375 if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) < (x + width))
7376 gtk_adjustment_set_value (tree_view->priv->hadjustment,
7377 x + width - tree_view->priv->hadjustment->page_size);
7378 else if (tree_view->priv->hadjustment->value > x)
7379 gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
7380 }
7381 }
7382
7383 GtkTreePath *
7384 _pspp_sheet_view_find_path (PsppSheetView *tree_view,
7385 int node)
7386 {
7387 GtkTreePath *path;
7388
7389 path = gtk_tree_path_new ();
7390 if (node >= 0)
7391 gtk_tree_path_append_index (path, node);
7392 return path;
7393 }
7394
7395 void
7396 _pspp_sheet_view_find_node (PsppSheetView *tree_view,
7397 GtkTreePath *path,
7398 int *node)
7399 {
7400 gint *indices = gtk_tree_path_get_indices (path);
7401 gint depth = gtk_tree_path_get_depth (path);
7402
7403 *node = -1;
7404 if (depth == 0 || indices[0] < 0 || indices[0] >= tree_view->priv->row_count)
7405 return;
7406 *node = indices[0];
7407 }
7408
7409 static void
7410 pspp_sheet_view_add_move_binding (GtkBindingSet *binding_set,
7411 guint keyval,
7412 guint modmask,
7413 gboolean add_shifted_binding,
7414 GtkMovementStep step,
7415 gint count)
7416 {
7417
7418 gtk_binding_entry_add_signal (binding_set, keyval, modmask,
7419 "move-cursor", 2,
7420 G_TYPE_ENUM, step,
7421 G_TYPE_INT, count);
7422
7423 if (add_shifted_binding)
7424 gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
7425 "move-cursor", 2,
7426 G_TYPE_ENUM, step,
7427 G_TYPE_INT, count);
7428
7429 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
7430 return;
7431
7432 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
7433 "move-cursor", 2,
7434 G_TYPE_ENUM, step,
7435 G_TYPE_INT, count);
7436
7437 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
7438 "move-cursor", 2,
7439 G_TYPE_ENUM, step,
7440 G_TYPE_INT, count);
7441 }
7442
7443 static void
7444 pspp_sheet_view_set_column_drag_info (PsppSheetView *tree_view,
7445 PsppSheetViewColumn *column)
7446 {
7447 PsppSheetViewColumn *left_column;
7448 PsppSheetViewColumn *cur_column = NULL;
7449 PsppSheetViewColumnReorder *reorder;
7450 gboolean rtl;
7451 GList *tmp_list;
7452 gint left;
7453
7454 /* We want to precalculate the motion list such that we know what column slots
7455 * are available.
7456 */
7457 left_column = NULL;
7458 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7459
7460 /* First, identify all possible drop spots */
7461 if (rtl)
7462 tmp_list = g_list_last (tree_view->priv->columns);
7463 else
7464 tmp_list = g_list_first (tree_view->priv->columns);
7465
7466 while (tmp_list)
7467 {
7468 cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
7469 tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
7470
7471 if (cur_column->visible == FALSE)
7472 continue;
7473
7474 /* If it's not the column moving and func tells us to skip over the column, we continue. */
7475 if (left_column != column && cur_column != column &&
7476 tree_view->priv->column_drop_func &&
7477 ! tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
7478 {
7479 left_column = cur_column;
7480 continue;
7481 }
7482 reorder = g_slice_new0 (PsppSheetViewColumnReorder);
7483 reorder->left_column = left_column;
7484 left_column = reorder->right_column = cur_column;
7485
7486 tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7487 }
7488
7489 /* Add the last one */
7490 if (tree_view->priv->column_drop_func == NULL ||
7491 ((left_column != column) &&
7492 tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
7493 {
7494 reorder = g_slice_new0 (PsppSheetViewColumnReorder);
7495 reorder->left_column = left_column;
7496 reorder->right_column = NULL;
7497 tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
7498 }
7499
7500 /* We quickly check to see if it even makes sense to reorder columns. */
7501 /* If there is nothing that can be moved, then we return */
7502
7503 if (tree_view->priv->column_drag_info == NULL)
7504 return;
7505
7506 /* We know there are always 2 slots possbile, as you can always return column. */
7507 /* If that's all there is, return */
7508 if (tree_view->priv->column_drag_info->next == NULL ||
7509 (tree_view->priv->column_drag_info->next->next == NULL &&
7510 ((PsppSheetViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
7511 ((PsppSheetViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
7512 {
7513 for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7514 g_slice_free (PsppSheetViewColumnReorder, tmp_list->data);
7515 g_list_free (tree_view->priv->column_drag_info);
7516 tree_view->priv->column_drag_info = NULL;
7517 return;
7518 }
7519 /* We fill in the ranges for the columns, now that we've isolated them */
7520 left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7521
7522 for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
7523 {
7524 reorder = (PsppSheetViewColumnReorder *) tmp_list->data;
7525
7526 reorder->left_align = left;
7527 if (tmp_list->next != NULL)
7528 {
7529 g_assert (tmp_list->next->data);
7530 left = reorder->right_align = (reorder->right_column->allocation.x +
7531 reorder->right_column->allocation.width +
7532 ((PsppSheetViewColumnReorder *)tmp_list->next->data)->left_column->allocation.x)/2;
7533 }
7534 else
7535 {
7536 gint width;
7537
7538 gdk_drawable_get_size (tree_view->priv->header_window, &width, NULL);
7539 reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
7540 }
7541 }
7542 }
7543
7544 void
7545 _pspp_sheet_view_column_start_drag (PsppSheetView *tree_view,
7546 PsppSheetViewColumn *column)
7547 {
7548 GdkEvent *send_event;
7549 GtkAllocation allocation;
7550 gint x, y, width, height;
7551 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
7552 GdkDisplay *display = gdk_screen_get_display (screen);
7553
7554 g_return_if_fail (tree_view->priv->column_drag_info == NULL);
7555 g_return_if_fail (tree_view->priv->cur_reorder == NULL);
7556 g_return_if_fail (column->button);
7557
7558 pspp_sheet_view_set_column_drag_info (tree_view, column);
7559
7560 if (tree_view->priv->column_drag_info == NULL)
7561 return;
7562
7563 if (tree_view->priv->drag_window == NULL)
7564 {
7565 GdkWindowAttr attributes;
7566 guint attributes_mask;
7567
7568 attributes.window_type = GDK_WINDOW_CHILD;
7569 attributes.wclass = GDK_INPUT_OUTPUT;
7570 attributes.x = column->allocation.x;
7571 attributes.y = 0;
7572 attributes.width = column->allocation.width;
7573 attributes.height = column->allocation.height;
7574 attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
7575 attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
7576 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
7577 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
7578
7579 tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
7580 &attributes,
7581 attributes_mask);
7582 gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
7583 }
7584
7585 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
7586 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
7587
7588 gtk_grab_remove (column->button);
7589
7590 send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
7591 send_event->crossing.send_event = TRUE;
7592 send_event->crossing.window = g_object_ref (GTK_BUTTON (column->button)->event_window);
7593 send_event->crossing.subwindow = NULL;
7594 send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
7595 send_event->crossing.time = GDK_CURRENT_TIME;
7596
7597 gtk_propagate_event (column->button, send_event);
7598 gdk_event_free (send_event);
7599
7600 send_event = gdk_event_new (GDK_BUTTON_RELEASE);
7601 send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
7602 send_event->button.send_event = TRUE;
7603 send_event->button.time = GDK_CURRENT_TIME;
7604 send_event->button.x = -1;
7605 send_event->button.y = -1;
7606 send_event->button.axes = NULL;
7607 send_event->button.state = 0;
7608 send_event->button.button = 1;
7609 send_event->button.device = gdk_display_get_core_pointer (display);
7610 send_event->button.x_root = 0;
7611 send_event->button.y_root = 0;
7612
7613 gtk_propagate_event (column->button, send_event);
7614 gdk_event_free (send_event);
7615
7616 /* Kids, don't try this at home */
7617 g_object_ref (column->button);
7618 gtk_container_remove (GTK_CONTAINER (tree_view), column->button);
7619 gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7620 gtk_widget_set_parent (column->button, GTK_WIDGET (tree_view));
7621 g_object_unref (column->button);
7622
7623 tree_view->priv->drag_column_x = column->allocation.x;
7624 allocation = column->allocation;
7625 allocation.x = 0;
7626 gtk_widget_size_allocate (column->button, &allocation);
7627 gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
7628
7629 tree_view->priv->drag_column = column;
7630 gdk_window_show (tree_view->priv->drag_window);
7631
7632 gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
7633 gdk_drawable_get_size (tree_view->priv->header_window, &width, &height);
7634
7635 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7636 while (gtk_events_pending ())
7637 gtk_main_iteration ();
7638
7639 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG);
7640 gdk_pointer_grab (tree_view->priv->drag_window,
7641 FALSE,
7642 GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
7643 NULL, NULL, GDK_CURRENT_TIME);
7644 gdk_keyboard_grab (tree_view->priv->drag_window,
7645 FALSE,
7646 GDK_CURRENT_TIME);
7647 }
7648
7649 void
7650 _pspp_sheet_view_queue_draw_node (PsppSheetView *tree_view,
7651 int node,
7652 const GdkRectangle *clip_rect)
7653 {
7654 GdkRectangle rect;
7655
7656 if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
7657 return;
7658
7659 rect.x = 0;
7660 rect.width = MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width);
7661
7662 rect.y = BACKGROUND_FIRST_PIXEL (tree_view, node);
7663 rect.height = ROW_HEIGHT (tree_view);
7664
7665 if (clip_rect)
7666 {
7667 GdkRectangle new_rect;
7668
7669 gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
7670
7671 gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
7672 }
7673 else
7674 {
7675 gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
7676 }
7677 }
7678
7679 static void
7680 pspp_sheet_view_queue_draw_path (PsppSheetView *tree_view,
7681 GtkTreePath *path,
7682 const GdkRectangle *clip_rect)
7683 {
7684 int node = -1;
7685
7686 _pspp_sheet_view_find_node (tree_view, path, &node);
7687
7688 if (node)
7689 _pspp_sheet_view_queue_draw_node (tree_view, node, clip_rect);
7690 }
7691
7692 static void
7693 pspp_sheet_view_focus_to_cursor (PsppSheetView *tree_view)
7694
7695 {
7696 GtkTreePath *cursor_path;
7697
7698 if ((tree_view->priv->row_count == 0) ||
7699 (! gtk_widget_get_realized (GTK_WIDGET (tree_view))))
7700 return;
7701
7702 cursor_path = NULL;
7703 if (tree_view->priv->cursor)
7704 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7705
7706 if (cursor_path == NULL)
7707 {
7708 /* There's no cursor. Move the cursor to the first selected row, if any
7709 * are selected, otherwise to the first row in the sheetview.
7710 */
7711 GList *selected_rows;
7712 GtkTreeModel *model;
7713 PsppSheetSelection *selection;
7714
7715 selection = pspp_sheet_view_get_selection (tree_view);
7716 selected_rows = pspp_sheet_selection_get_selected_rows (selection, &model);
7717
7718 if (selected_rows)
7719 {
7720 /* XXX we could avoid doing O(n) work to get this result */
7721 cursor_path = gtk_tree_path_copy((const GtkTreePath *)(selected_rows->data));
7722 g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
7723 g_list_free (selected_rows);
7724 }
7725 else
7726 {
7727 cursor_path = gtk_tree_path_new_first ();
7728 search_first_focusable_path (tree_view, &cursor_path,
7729 TRUE, NULL);
7730 }
7731
7732 gtk_tree_row_reference_free (tree_view->priv->cursor);
7733 tree_view->priv->cursor = NULL;
7734
7735 if (cursor_path)
7736 {
7737 if (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
7738 tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
7739 pspp_sheet_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE);
7740 else
7741 pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
7742 }
7743 }
7744
7745 if (cursor_path)
7746 {
7747 /* Now find a column for the cursor. */
7748 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
7749
7750 pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
7751 gtk_tree_path_free (cursor_path);
7752
7753 if (tree_view->priv->focus_column == NULL)
7754 {
7755 GList *list;
7756 for (list = tree_view->priv->columns; list; list = list->next)
7757 {
7758 if (PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
7759 {
7760 tree_view->priv->focus_column = PSPP_SHEET_VIEW_COLUMN (list->data);
7761 pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
7762 pspp_sheet_selection_select_column (tree_view->priv->selection, tree_view->priv->focus_column);
7763 break;
7764 }
7765 }
7766
7767 }
7768 }
7769 }
7770
7771 static void
7772 pspp_sheet_view_move_cursor_up_down (PsppSheetView *tree_view,
7773 gint count)
7774 {
7775 gint selection_count;
7776 int cursor_node = -1;
7777 int new_cursor_node = -1;
7778 GtkTreePath *cursor_path = NULL;
7779 gboolean grab_focus = TRUE;
7780
7781 if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
7782 return;
7783
7784 cursor_path = NULL;
7785 if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
7786 /* FIXME: we lost the cursor; should we get the first? */
7787 return;
7788
7789 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7790 _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
7791
7792 if (cursor_node < 0)
7793 /* FIXME: we lost the cursor; should we get the first? */
7794 return;
7795
7796 selection_count = pspp_sheet_selection_count_selected_rows (tree_view->priv->selection);
7797
7798 if (selection_count == 0
7799 && tree_view->priv->selection->type != PSPP_SHEET_SELECTION_NONE
7800 && !tree_view->priv->ctrl_pressed)
7801 {
7802 /* Don't move the cursor, but just select the current node */
7803 new_cursor_node = cursor_node;
7804 }
7805 else
7806 {
7807 if (count == -1)
7808 new_cursor_node = pspp_sheet_view_node_prev (tree_view, cursor_node);
7809 else
7810 new_cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
7811 }
7812
7813 gtk_tree_path_free (cursor_path);
7814
7815 if (new_cursor_node)
7816 {
7817 cursor_path = _pspp_sheet_view_find_path (tree_view, new_cursor_node);
7818
7819 search_first_focusable_path (tree_view, &cursor_path,
7820 (count != -1),
7821 &new_cursor_node);
7822
7823 if (cursor_path)
7824 gtk_tree_path_free (cursor_path);
7825 }
7826
7827 /*
7828 * If the list has only one item and multi-selection is set then select
7829 * the row (if not yet selected).
7830 */
7831 if ((tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
7832 tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE) &&
7833 new_cursor_node < 0)
7834 {
7835 if (count == -1)
7836 new_cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
7837 else
7838 new_cursor_node = pspp_sheet_view_node_prev (tree_view, cursor_node);
7839
7840 if (new_cursor_node < 0
7841 && !pspp_sheet_view_node_is_selected (tree_view, cursor_node))
7842 {
7843 new_cursor_node = cursor_node;
7844 }
7845 else
7846 {
7847 new_cursor_node = -1;
7848 }
7849 }
7850
7851 if (new_cursor_node >= 0)
7852 {
7853 cursor_path = _pspp_sheet_view_find_path (tree_view, new_cursor_node);
7854 pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE);
7855 gtk_tree_path_free (cursor_path);
7856 }
7857 else
7858 {
7859 pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
7860
7861 if (!tree_view->priv->shift_pressed)
7862 {
7863 if (! gtk_widget_keynav_failed (GTK_WIDGET (tree_view),
7864 count < 0 ?
7865 GTK_DIR_UP : GTK_DIR_DOWN))
7866 {
7867 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
7868
7869 if (toplevel)
7870 gtk_widget_child_focus (toplevel,
7871 count < 0 ?
7872 GTK_DIR_TAB_BACKWARD :
7873 GTK_DIR_TAB_FORWARD);
7874
7875 grab_focus = FALSE;
7876 }
7877 }
7878 else
7879 {
7880 gtk_widget_error_bell (GTK_WIDGET (tree_view));
7881 }
7882 }
7883
7884 if (grab_focus)
7885 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7886 }
7887
7888 static void
7889 pspp_sheet_view_move_cursor_page_up_down (PsppSheetView *tree_view,
7890 gint count)
7891 {
7892 int cursor_node = -1;
7893 GtkTreePath *old_cursor_path = NULL;
7894 GtkTreePath *cursor_path = NULL;
7895 int start_cursor_node = -1;
7896 gint y;
7897 gint window_y;
7898 gint vertical_separator;
7899
7900 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
7901 return;
7902
7903 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7904 old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7905 else
7906 /* This is sorta weird. Focus in should give us a cursor */
7907 return;
7908
7909 gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
7910 _pspp_sheet_view_find_node (tree_view, old_cursor_path, &cursor_node);
7911
7912 if (cursor_node < 0)
7913 {
7914 /* FIXME: we lost the cursor. Should we try to get one? */
7915 gtk_tree_path_free (old_cursor_path);
7916 return;
7917 }
7918
7919 y = pspp_sheet_view_node_find_offset (tree_view, cursor_node);
7920 window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
7921 y += tree_view->priv->cursor_offset;
7922 y += count * (int)tree_view->priv->vadjustment->page_increment;
7923 y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower, (gint)tree_view->priv->vadjustment->upper - vertical_separator);
7924
7925 if (y >= tree_view->priv->height)
7926 y = tree_view->priv->height - 1;
7927
7928 tree_view->priv->cursor_offset =
7929 pspp_sheet_view_find_offset (tree_view, y, &cursor_node);
7930
7931 if (tree_view->priv->cursor_offset > BACKGROUND_HEIGHT (tree_view))
7932 {
7933 cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
7934 tree_view->priv->cursor_offset -= BACKGROUND_HEIGHT (tree_view);
7935 }
7936
7937 y -= tree_view->priv->cursor_offset;
7938 cursor_path = _pspp_sheet_view_find_path (tree_view, cursor_node);
7939
7940 start_cursor_node = cursor_node;
7941
7942 if (! search_first_focusable_path (tree_view, &cursor_path,
7943 (count != -1),
7944 &cursor_node))
7945 {
7946 /* It looks like we reached the end of the view without finding
7947 * a focusable row. We will step backwards to find the last
7948 * focusable row.
7949 */
7950 cursor_node = start_cursor_node;
7951 cursor_path = _pspp_sheet_view_find_path (tree_view, cursor_node);
7952
7953 search_first_focusable_path (tree_view, &cursor_path,
7954 (count == -1),
7955 &cursor_node);
7956 }
7957
7958 if (!cursor_path)
7959 goto cleanup;
7960
7961 /* update y */
7962 y = pspp_sheet_view_node_find_offset (tree_view, cursor_node);
7963
7964 pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
7965
7966 y -= window_y;
7967 pspp_sheet_view_scroll_to_point (tree_view, -1, y);
7968 pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
7969 _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
7970
7971 if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
7972 gtk_widget_error_bell (GTK_WIDGET (tree_view));
7973
7974 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
7975
7976 cleanup:
7977 gtk_tree_path_free (old_cursor_path);
7978 gtk_tree_path_free (cursor_path);
7979 }
7980
7981 static void
7982 pspp_sheet_view_move_cursor_left_right (PsppSheetView *tree_view,
7983 gint count)
7984 {
7985 int cursor_node = -1;
7986 GtkTreePath *cursor_path = NULL;
7987 PsppSheetViewColumn *column;
7988 GtkTreeIter iter;
7989 GList *list;
7990 gboolean found_column = FALSE;
7991 gboolean rtl;
7992
7993 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
7994
7995 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
7996 return;
7997
7998 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7999 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8000 else
8001 return;
8002
8003 _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
8004 if (cursor_node < 0)
8005 return;
8006 if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
8007 {
8008 gtk_tree_path_free (cursor_path);
8009 return;
8010 }
8011 gtk_tree_path_free (cursor_path);
8012
8013 list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
8014 if (tree_view->priv->focus_column)
8015 {
8016 for (; list; list = (rtl ? list->prev : list->next))
8017 {
8018 if (list->data == tree_view->priv->focus_column)
8019 break;
8020 }
8021 }
8022
8023 while (list)
8024 {
8025 gboolean left, right;
8026
8027 column = list->data;
8028 if (column->visible == FALSE)
8029 goto loop_end;
8030
8031 pspp_sheet_view_column_cell_set_cell_data (column,
8032 tree_view->priv->model,
8033 &iter);
8034
8035 if (rtl)
8036 {
8037 right = list->prev ? TRUE : FALSE;
8038 left = list->next ? TRUE : FALSE;
8039 }
8040 else
8041 {
8042 left = list->prev ? TRUE : FALSE;
8043 right = list->next ? TRUE : FALSE;
8044 }
8045
8046 if (_pspp_sheet_view_column_cell_focus (column, count, left, right))
8047 {
8048 tree_view->priv->focus_column = column;
8049 found_column = TRUE;
8050 break;
8051 }
8052 loop_end:
8053 if (count == 1)
8054 list = rtl ? list->prev : list->next;
8055 else
8056 list = rtl ? list->next : list->prev;
8057 }
8058
8059 if (found_column)
8060 {
8061 _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
8062 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
8063 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8064 }
8065 else
8066 {
8067 gtk_widget_error_bell (GTK_WIDGET (tree_view));
8068 }
8069
8070 pspp_sheet_view_clamp_column_visible (tree_view,
8071 tree_view->priv->focus_column, TRUE);
8072 }
8073
8074 static void
8075 pspp_sheet_view_move_cursor_start_end (PsppSheetView *tree_view,
8076 gint count)
8077 {
8078 int cursor_node;
8079 GtkTreePath *path;
8080 GtkTreePath *old_path;
8081
8082 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8083 return;
8084
8085 g_return_if_fail (tree_view->priv->row_count > 0);
8086
8087 pspp_sheet_view_get_cursor (tree_view, &old_path, NULL);
8088
8089 if (count == -1)
8090 {
8091 /* Now go forward to find the first focusable row. */
8092 path = _pspp_sheet_view_find_path (tree_view, 0);
8093 search_first_focusable_path (tree_view, &path,
8094 TRUE, &cursor_node);
8095 }
8096 else
8097 {
8098 /* Now go backwards to find last focusable row. */
8099 path = _pspp_sheet_view_find_path (tree_view, tree_view->priv->row_count - 1);
8100 search_first_focusable_path (tree_view, &path,
8101 FALSE, &cursor_node);
8102 }
8103
8104 if (!path)
8105 goto cleanup;
8106
8107 if (gtk_tree_path_compare (old_path, path))
8108 {
8109 pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE);
8110 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8111 }
8112 else
8113 {
8114 gtk_widget_error_bell (GTK_WIDGET (tree_view));
8115 }
8116
8117 cleanup:
8118 gtk_tree_path_free (old_path);
8119 gtk_tree_path_free (path);
8120 }
8121
8122 static gboolean
8123 pspp_sheet_view_real_select_all (PsppSheetView *tree_view)
8124 {
8125 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8126 return FALSE;
8127
8128 if (tree_view->priv->selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
8129 tree_view->priv->selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
8130 return FALSE;
8131
8132 pspp_sheet_selection_select_all (tree_view->priv->selection);
8133
8134 return TRUE;
8135 }
8136
8137 static gboolean
8138 pspp_sheet_view_real_unselect_all (PsppSheetView *tree_view)
8139 {
8140 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8141 return FALSE;
8142
8143 if (tree_view->priv->selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
8144 tree_view->priv->selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
8145 return FALSE;
8146
8147 pspp_sheet_selection_unselect_all (tree_view->priv->selection);
8148
8149 return TRUE;
8150 }
8151
8152 static gboolean
8153 pspp_sheet_view_real_select_cursor_row (PsppSheetView *tree_view,
8154 gboolean start_editing)
8155 {
8156 int new_node = -1;
8157 int cursor_node = -1;
8158 GtkTreePath *cursor_path = NULL;
8159 GtkTreeSelectMode mode = 0;
8160
8161 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8162 return FALSE;
8163
8164 if (tree_view->priv->cursor)
8165 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8166
8167 if (cursor_path == NULL)
8168 return FALSE;
8169
8170 _pspp_sheet_view_find_node (tree_view, cursor_path,
8171 &cursor_node);
8172
8173 if (cursor_node < 0)
8174 {
8175 gtk_tree_path_free (cursor_path);
8176 return FALSE;
8177 }
8178
8179 if (!tree_view->priv->shift_pressed && start_editing &&
8180 tree_view->priv->focus_column)
8181 {
8182 if (pspp_sheet_view_start_editing (tree_view, cursor_path))
8183 {
8184 gtk_tree_path_free (cursor_path);
8185 return TRUE;
8186 }
8187 }
8188
8189 if (tree_view->priv->ctrl_pressed)
8190 mode |= GTK_TREE_SELECT_MODE_TOGGLE;
8191 if (tree_view->priv->shift_pressed)
8192 mode |= GTK_TREE_SELECT_MODE_EXTEND;
8193
8194 _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
8195 cursor_node,
8196 cursor_path,
8197 mode,
8198 FALSE);
8199
8200 /* We bail out if the original (tree, node) don't exist anymore after
8201 * handling the selection-changed callback. We do return TRUE because
8202 * the key press has been handled at this point.
8203 */
8204 _pspp_sheet_view_find_node (tree_view, cursor_path, &new_node);
8205
8206 if (cursor_node != new_node)
8207 return FALSE;
8208
8209 pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
8210
8211 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8212 _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
8213
8214 if (!tree_view->priv->shift_pressed)
8215 pspp_sheet_view_row_activated (tree_view, cursor_path,
8216 tree_view->priv->focus_column);
8217
8218 gtk_tree_path_free (cursor_path);
8219
8220 return TRUE;
8221 }
8222
8223 static gboolean
8224 pspp_sheet_view_real_toggle_cursor_row (PsppSheetView *tree_view)
8225 {
8226 int new_node = -1;
8227 int cursor_node = -1;
8228 GtkTreePath *cursor_path = NULL;
8229
8230 if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8231 return FALSE;
8232
8233 cursor_path = NULL;
8234 if (tree_view->priv->cursor)
8235 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
8236
8237 if (cursor_path == NULL)
8238 return FALSE;
8239
8240 _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
8241 if (cursor_node < 0)
8242 {
8243 gtk_tree_path_free (cursor_path);
8244 return FALSE;
8245 }
8246
8247 _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
8248 cursor_node,
8249 cursor_path,
8250 GTK_TREE_SELECT_MODE_TOGGLE,
8251 FALSE);
8252
8253 /* We bail out if the original (tree, node) don't exist anymore after
8254 * handling the selection-changed callback. We do return TRUE because
8255 * the key press has been handled at this point.
8256 */
8257 _pspp_sheet_view_find_node (tree_view, cursor_path, &new_node);
8258
8259 if (cursor_node != new_node)
8260 return FALSE;
8261
8262 pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
8263
8264 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
8265 pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
8266 gtk_tree_path_free (cursor_path);
8267
8268 return TRUE;
8269 }
8270
8271 static gboolean
8272 pspp_sheet_view_search_entry_flush_timeout (PsppSheetView *tree_view)
8273 {
8274 pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
8275 tree_view->priv->typeselect_flush_timeout = 0;
8276
8277 return FALSE;
8278 }
8279
8280 /* Cut and paste from gtkwindow.c */
8281 static void
8282 send_focus_change (GtkWidget *widget,
8283 gboolean in)
8284 {
8285 GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
8286
8287 g_object_ref (widget);
8288
8289 if (in)
8290 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
8291 else
8292 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
8293
8294 fevent->focus_change.type = GDK_FOCUS_CHANGE;
8295 fevent->focus_change.window = g_object_ref (widget->window);
8296 fevent->focus_change.in = in;
8297
8298 gtk_widget_event (widget, fevent);
8299
8300 g_object_notify (G_OBJECT (widget), "has-focus");
8301
8302 g_object_unref (widget);
8303 gdk_event_free (fevent);
8304 }
8305
8306 static void
8307 pspp_sheet_view_ensure_interactive_directory (PsppSheetView *tree_view)
8308 {
8309 GtkWidget *frame, *vbox, *toplevel;
8310 GdkScreen *screen;
8311
8312 if (tree_view->priv->search_custom_entry_set)
8313 return;
8314
8315 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
8316 screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
8317
8318 if (tree_view->priv->search_window != NULL)
8319 {
8320 if (GTK_WINDOW (toplevel)->group)
8321 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
8322 GTK_WINDOW (tree_view->priv->search_window));
8323 else if (GTK_WINDOW (tree_view->priv->search_window)->group)
8324 gtk_window_group_remove_window (GTK_WINDOW (tree_view->priv->search_window)->group,
8325 GTK_WINDOW (tree_view->priv->search_window));
8326 gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
8327 return;
8328 }
8329
8330 tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
8331 gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
8332
8333 if (GTK_WINDOW (toplevel)->group)
8334 gtk_window_group_add_window (GTK_WINDOW (toplevel)->group,
8335 GTK_WINDOW (tree_view->priv->search_window));
8336
8337 gtk_window_set_type_hint (GTK_WINDOW (tree_view->priv->search_window),
8338 GDK_WINDOW_TYPE_HINT_UTILITY);
8339 gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
8340 g_signal_connect (tree_view->priv->search_window, "delete-event",
8341 G_CALLBACK (pspp_sheet_view_search_delete_event),
8342 tree_view);
8343 g_signal_connect (tree_view->priv->search_window, "key-press-event",
8344 G_CALLBACK (pspp_sheet_view_search_key_press_event),
8345 tree_view);
8346 g_signal_connect (tree_view->priv->search_window, "button-press-event",
8347 G_CALLBACK (pspp_sheet_view_search_button_press_event),
8348 tree_view);
8349 g_signal_connect (tree_view->priv->search_window, "scroll-event",
8350 G_CALLBACK (pspp_sheet_view_search_scroll_event),
8351 tree_view);
8352
8353 frame = gtk_frame_new (NULL);
8354 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
8355 gtk_widget_show (frame);
8356 gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window), frame);
8357
8358 vbox = gtk_vbox_new (FALSE, 0);
8359 gtk_widget_show (vbox);
8360 gtk_container_add (GTK_CONTAINER (frame), vbox);
8361 gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
8362
8363 /* add entry */
8364 tree_view->priv->search_entry = gtk_entry_new ();
8365 gtk_widget_show (tree_view->priv->search_entry);
8366 g_signal_connect (tree_view->priv->search_entry, "populate-popup",
8367 G_CALLBACK (pspp_sheet_view_search_disable_popdown),
8368 tree_view);
8369 g_signal_connect (tree_view->priv->search_entry,
8370 "activate", G_CALLBACK (pspp_sheet_view_search_activate),
8371 tree_view);
8372 g_signal_connect (GTK_ENTRY (tree_view->priv->search_entry)->im_context,
8373 "preedit-changed",
8374 G_CALLBACK (pspp_sheet_view_search_preedit_changed),
8375 tree_view);
8376 gtk_container_add (GTK_CONTAINER (vbox),
8377 tree_view->priv->search_entry);
8378
8379 gtk_widget_realize (tree_view->priv->search_entry);
8380 }
8381
8382 /* Pops up the interactive search entry. If keybinding is TRUE then the user
8383 * started this by typing the start_interactive_search keybinding. Otherwise, it came from
8384 */
8385 static gboolean
8386 pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view,
8387 gboolean keybinding)
8388 {
8389 /* We only start interactive search if we have focus or the columns
8390 * have focus. If one of our children have focus, we don't want to
8391 * start the search.
8392 */
8393 GList *list;
8394 gboolean found_focus = FALSE;
8395 GtkWidgetClass *entry_parent_class;
8396
8397 if (!tree_view->priv->enable_search && !keybinding)
8398 return FALSE;
8399
8400 if (tree_view->priv->search_custom_entry_set)
8401 return FALSE;
8402
8403 if (tree_view->priv->search_window != NULL &&
8404 gtk_widget_get_visible (tree_view->priv->search_window))
8405 return TRUE;
8406
8407 for (list = tree_view->priv->columns; list; list = list->next)
8408 {
8409 PsppSheetViewColumn *column;
8410
8411 column = list->data;
8412 if (! column->visible)
8413 continue;
8414
8415 if (column->button && gtk_widget_has_focus (column->button))
8416 {
8417 found_focus = TRUE;
8418 break;
8419 }
8420 }
8421
8422 if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
8423 found_focus = TRUE;
8424
8425 if (!found_focus)
8426 return FALSE;
8427
8428 if (tree_view->priv->search_column < 0)
8429 return FALSE;
8430
8431 pspp_sheet_view_ensure_interactive_directory (tree_view);
8432
8433 if (keybinding)
8434 gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
8435
8436 /* done, show it */
8437 tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
8438 gtk_widget_show (tree_view->priv->search_window);
8439 if (tree_view->priv->search_entry_changed_id == 0)
8440 {
8441 tree_view->priv->search_entry_changed_id =
8442 g_signal_connect (tree_view->priv->search_entry, "changed",
8443 G_CALLBACK (pspp_sheet_view_search_init),
8444 tree_view);
8445 }
8446
8447 tree_view->priv->typeselect_flush_timeout =
8448 gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
8449 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
8450 tree_view);
8451
8452 /* Grab focus will select all the text. We don't want that to happen, so we
8453 * call the parent instance and bypass the selection change. This is probably
8454 * really non-kosher. */
8455 entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (tree_view->priv->search_entry));
8456 (entry_parent_class->grab_focus) (tree_view->priv->search_entry);
8457
8458 /* send focus-in event */
8459 send_focus_change (tree_view->priv->search_entry, TRUE);
8460
8461 /* search first matching iter */
8462 pspp_sheet_view_search_init (tree_view->priv->search_entry, tree_view);
8463
8464 return TRUE;
8465 }
8466
8467 static gboolean
8468 pspp_sheet_view_start_interactive_search (PsppSheetView *tree_view)
8469 {
8470 return pspp_sheet_view_real_start_interactive_search (tree_view, TRUE);
8471 }
8472
8473 /* this function returns the new width of the column being resized given
8474 * the column and x position of the cursor; the x cursor position is passed
8475 * in as a pointer and automagicly corrected if it's beyond min/max limits
8476 */
8477 static gint
8478 pspp_sheet_view_new_column_width (PsppSheetView *tree_view,
8479 gint i,
8480 gint *x)
8481 {
8482 PsppSheetViewColumn *column;
8483 gint width;
8484 gboolean rtl;
8485
8486 /* first translate the x position from widget->window
8487 * to clist->clist_window
8488 */
8489 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
8490 column = g_list_nth (tree_view->priv->columns, i)->data;
8491 width = rtl ? (column->allocation.x + column->allocation.width - *x) : (*x - column->allocation.x);
8492
8493 /* Clamp down the value */
8494 if (column->min_width == -1)
8495 width = MAX (column->button_request, width);
8496 else
8497 width = MAX (column->min_width, width);
8498 if (column->max_width != -1)
8499 width = MIN (width, column->max_width);
8500
8501 *x = rtl ? (column->allocation.x + column->allocation.width - width) : (column->allocation.x + width);
8502
8503 return width;
8504 }
8505
8506
8507 /* FIXME this adjust_allocation is a big cut-and-paste from
8508 * GtkCList, needs to be some "official" way to do this
8509 * factored out.
8510 */
8511 typedef struct
8512 {
8513 GdkWindow *window;
8514 int dx;
8515 int dy;
8516 } ScrollData;
8517
8518 /* The window to which widget->window is relative */
8519 #define ALLOCATION_WINDOW(widget) \
8520 (!gtk_widget_get_has_window (widget) ? \
8521 (widget)->window : \
8522 gdk_window_get_parent ((widget)->window))
8523
8524 static void
8525 adjust_allocation_recurse (GtkWidget *widget,
8526 gpointer data)
8527 {
8528 ScrollData *scroll_data = data;
8529
8530 /* Need to really size allocate instead of just poking
8531 * into widget->allocation if the widget is not realized.
8532 * FIXME someone figure out why this was.
8533 */
8534 if (!gtk_widget_get_realized (widget))
8535 {
8536 if (gtk_widget_get_visible (widget))
8537 {
8538 GdkRectangle tmp_rectangle = widget->allocation;
8539 tmp_rectangle.x += scroll_data->dx;
8540 tmp_rectangle.y += scroll_data->dy;
8541
8542 gtk_widget_size_allocate (widget, &tmp_rectangle);
8543 }
8544 }
8545 else
8546 {
8547 if (ALLOCATION_WINDOW (widget) == scroll_data->window)
8548 {
8549 widget->allocation.x += scroll_data->dx;
8550 widget->allocation.y += scroll_data->dy;
8551
8552 if (GTK_IS_CONTAINER (widget))
8553 gtk_container_forall (GTK_CONTAINER (widget),
8554 adjust_allocation_recurse,
8555 data);
8556 }
8557 }
8558 }
8559
8560 static void
8561 adjust_allocation (GtkWidget *widget,
8562 int dx,
8563 int dy)
8564 {
8565 ScrollData scroll_data;
8566
8567 if (gtk_widget_get_realized (widget))
8568 scroll_data.window = ALLOCATION_WINDOW (widget);
8569 else
8570 scroll_data.window = NULL;
8571
8572 scroll_data.dx = dx;
8573 scroll_data.dy = dy;
8574
8575 adjust_allocation_recurse (widget, &scroll_data);
8576 }
8577
8578 void
8579 pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column);
8580
8581 /* Callbacks */
8582 static void
8583 pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment,
8584 PsppSheetView *tree_view)
8585 {
8586 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8587 {
8588 GList *list;
8589 gint dy;
8590
8591 gdk_window_move (tree_view->priv->bin_window,
8592 - tree_view->priv->hadjustment->value,
8593 TREE_VIEW_HEADER_HEIGHT (tree_view));
8594 gdk_window_move (tree_view->priv->header_window,
8595 - tree_view->priv->hadjustment->value,
8596 0);
8597 dy = tree_view->priv->dy - (int) tree_view->priv->vadjustment->value;
8598 if (dy)
8599 {
8600 update_prelight (tree_view,
8601 tree_view->priv->event_last_x,
8602 tree_view->priv->event_last_y - dy);
8603
8604 if (tree_view->priv->edited_column &&
8605 GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
8606 {
8607 GList *list;
8608 GtkWidget *widget;
8609 PsppSheetViewChild *child = NULL;
8610
8611 widget = GTK_WIDGET (tree_view->priv->edited_column->editable_widget);
8612 adjust_allocation (widget, 0, dy);
8613
8614 for (list = tree_view->priv->children; list; list = list->next)
8615 {
8616 child = (PsppSheetViewChild *)list->data;
8617 if (child->widget == widget)
8618 {
8619 child->y += dy;
8620 break;
8621 }
8622 }
8623 }
8624 }
8625 gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
8626
8627 if (tree_view->priv->dy != (int) tree_view->priv->vadjustment->value)
8628 {
8629 /* update our dy and top_row */
8630 tree_view->priv->dy = (int) tree_view->priv->vadjustment->value;
8631
8632 if (!tree_view->priv->in_top_row_to_dy)
8633 pspp_sheet_view_dy_to_top_row (tree_view);
8634 }
8635
8636 for (list = tree_view->priv->columns; list; list = list->next)
8637 {
8638 PsppSheetViewColumn *column = list->data;
8639 GtkAllocation *allocation = &column->allocation;
8640
8641 if (span_intersects (allocation->x, allocation->width,
8642 tree_view->priv->hadjustment->value,
8643 GTK_WIDGET (tree_view)->allocation.width))
8644 {
8645 pspp_sheet_view_column_set_need_button (column, TRUE);
8646 if (!column->button)
8647 pspp_sheet_view_column_update_button (column);
8648 }
8649 }
8650 }
8651 }
8652
8653
8654
8655 /* Public methods
8656 */
8657
8658 /**
8659 * pspp_sheet_view_new:
8660 *
8661 * Creates a new #PsppSheetView widget.
8662 *
8663 * Return value: A newly created #PsppSheetView widget.
8664 **/
8665 GtkWidget *
8666 pspp_sheet_view_new (void)
8667 {
8668 return g_object_new (PSPP_TYPE_SHEET_VIEW, NULL);
8669 }
8670
8671 /**
8672 * pspp_sheet_view_new_with_model:
8673 * @model: the model.
8674 *
8675 * Creates a new #PsppSheetView widget with the model initialized to @model.
8676 *
8677 * Return value: A newly created #PsppSheetView widget.
8678 **/
8679 GtkWidget *
8680 pspp_sheet_view_new_with_model (GtkTreeModel *model)
8681 {
8682 return g_object_new (PSPP_TYPE_SHEET_VIEW, "model", model, NULL);
8683 }
8684
8685 /* Public Accessors
8686 */
8687
8688 /**
8689 * pspp_sheet_view_get_model:
8690 * @tree_view: a #PsppSheetView
8691 *
8692 * Returns the model the #PsppSheetView is based on. Returns %NULL if the
8693 * model is unset.
8694 *
8695 * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
8696 **/
8697 GtkTreeModel *
8698 pspp_sheet_view_get_model (PsppSheetView *tree_view)
8699 {
8700 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
8701
8702 return tree_view->priv->model;
8703 }
8704
8705 /**
8706 * pspp_sheet_view_set_model:
8707 * @tree_view: A #GtkTreeNode.
8708 * @model: (allow-none): The model.
8709 *
8710 * Sets the model for a #PsppSheetView. If the @tree_view already has a model
8711 * set, it will remove it before setting the new model. If @model is %NULL,
8712 * then it will unset the old model.
8713 **/
8714 void
8715 pspp_sheet_view_set_model (PsppSheetView *tree_view,
8716 GtkTreeModel *model)
8717 {
8718 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
8719 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
8720
8721 if (model == tree_view->priv->model)
8722 return;
8723
8724 if (tree_view->priv->scroll_to_path)
8725 {
8726 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
8727 tree_view->priv->scroll_to_path = NULL;
8728 }
8729
8730 if (tree_view->priv->model)
8731 {
8732 GList *tmplist = tree_view->priv->columns;
8733
8734 if (tree_view->priv->selected)
8735 range_tower_set0 (tree_view->priv->selected, 0, ULONG_MAX);
8736 pspp_sheet_view_stop_editing (tree_view, TRUE);
8737
8738 g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8739 pspp_sheet_view_row_changed,
8740 tree_view);
8741 g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8742 pspp_sheet_view_row_inserted,
8743 tree_view);
8744 g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8745 pspp_sheet_view_row_deleted,
8746 tree_view);
8747 g_signal_handlers_disconnect_by_func (tree_view->priv->model,
8748 pspp_sheet_view_rows_reordered,
8749 tree_view);
8750
8751 for (; tmplist; tmplist = tmplist->next)
8752 _pspp_sheet_view_column_unset_model (tmplist->data,
8753 tree_view->priv->model);
8754
8755 tree_view->priv->prelight_node = -1;
8756
8757 gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
8758 tree_view->priv->drag_dest_row = NULL;
8759 gtk_tree_row_reference_free (tree_view->priv->cursor);
8760 tree_view->priv->cursor = NULL;
8761 gtk_tree_row_reference_free (tree_view->priv->anchor);
8762 tree_view->priv->anchor = NULL;
8763 gtk_tree_row_reference_free (tree_view->priv->top_row);
8764 tree_view->priv->top_row = NULL;
8765 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
8766 tree_view->priv->scroll_to_path = NULL;
8767
8768 tree_view->priv->scroll_to_column = NULL;
8769
8770 g_object_unref (tree_view->priv->model);
8771
8772 tree_view->priv->search_column = -1;
8773 tree_view->priv->fixed_height = -1;
8774 tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
8775 tree_view->priv->last_button_x = -1;
8776 tree_view->priv->last_button_y = -1;
8777 }
8778
8779 tree_view->priv->model = model;
8780
8781 if (tree_view->priv->model)
8782 {
8783 gint i;
8784 GtkTreeModelFlags flags;
8785
8786 if (tree_view->priv->search_column == -1)
8787 {
8788 for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
8789 {
8790 GType type = gtk_tree_model_get_column_type (model, i);
8791
8792 if (g_value_type_transformable (type, G_TYPE_STRING))
8793 {
8794 tree_view->priv->search_column = i;
8795 break;
8796 }
8797 }
8798 }
8799
8800 g_object_ref (tree_view->priv->model);
8801 g_signal_connect (tree_view->priv->model,
8802 "row-changed",
8803 G_CALLBACK (pspp_sheet_view_row_changed),
8804 tree_view);
8805 g_signal_connect (tree_view->priv->model,
8806 "row-inserted",
8807 G_CALLBACK (pspp_sheet_view_row_inserted),
8808 tree_view);
8809 g_signal_connect (tree_view->priv->model,
8810 "row-deleted",
8811 G_CALLBACK (pspp_sheet_view_row_deleted),
8812 tree_view);
8813 g_signal_connect (tree_view->priv->model,
8814 "rows-reordered",
8815 G_CALLBACK (pspp_sheet_view_rows_reordered),
8816 tree_view);
8817
8818 flags = gtk_tree_model_get_flags (tree_view->priv->model);
8819
8820 tree_view->priv->row_count = gtk_tree_model_iter_n_children (tree_view->priv->model, NULL);
8821
8822 /* FIXME: do I need to do this? pspp_sheet_view_create_buttons (tree_view); */
8823 install_presize_handler (tree_view);
8824 }
8825
8826 g_object_notify (G_OBJECT (tree_view), "model");
8827
8828 if (tree_view->priv->selection)
8829 _pspp_sheet_selection_emit_changed (tree_view->priv->selection);
8830
8831 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8832 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
8833 }
8834
8835 /**
8836 * pspp_sheet_view_get_selection:
8837 * @tree_view: A #PsppSheetView.
8838 *
8839 * Gets the #PsppSheetSelection associated with @tree_view.
8840 *
8841 * Return value: A #PsppSheetSelection object.
8842 **/
8843 PsppSheetSelection *
8844 pspp_sheet_view_get_selection (PsppSheetView *tree_view)
8845 {
8846 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
8847
8848 return tree_view->priv->selection;
8849 }
8850
8851 /**
8852 * pspp_sheet_view_get_hadjustment:
8853 * @tree_view: A #PsppSheetView
8854 *
8855 * Gets the #GtkAdjustment currently being used for the horizontal aspect.
8856 *
8857 * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8858 * used.
8859 **/
8860 GtkAdjustment *
8861 pspp_sheet_view_get_hadjustment (PsppSheetView *tree_view)
8862 {
8863 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
8864
8865 if (tree_view->priv->hadjustment == NULL)
8866 pspp_sheet_view_set_hadjustment (tree_view, NULL);
8867
8868 return tree_view->priv->hadjustment;
8869 }
8870
8871 /**
8872 * pspp_sheet_view_set_hadjustment:
8873 * @tree_view: A #PsppSheetView
8874 * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
8875 *
8876 * Sets the #GtkAdjustment for the current horizontal aspect.
8877 **/
8878 void
8879 pspp_sheet_view_set_hadjustment (PsppSheetView *tree_view,
8880 GtkAdjustment *adjustment)
8881 {
8882 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
8883
8884 pspp_sheet_view_set_adjustments (tree_view,
8885 adjustment,
8886 tree_view->priv->vadjustment);
8887
8888 g_object_notify (G_OBJECT (tree_view), "hadjustment");
8889 }
8890
8891 /**
8892 * pspp_sheet_view_get_vadjustment:
8893 * @tree_view: A #PsppSheetView
8894 *
8895 * Gets the #GtkAdjustment currently being used for the vertical aspect.
8896 *
8897 * Return value: A #GtkAdjustment object, or %NULL if none is currently being
8898 * used.
8899 **/
8900 GtkAdjustment *
8901 pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
8902 {
8903 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
8904
8905 if (tree_view->priv->vadjustment == NULL)
8906 pspp_sheet_view_set_vadjustment (tree_view, NULL);
8907
8908 return tree_view->priv->vadjustment;
8909 }
8910
8911 /**
8912 * pspp_sheet_view_set_vadjustment:
8913 * @tree_view: A #PsppSheetView
8914 * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
8915 *
8916 * Sets the #GtkAdjustment for the current vertical aspect.
8917 **/
8918 void
8919 pspp_sheet_view_set_vadjustment (PsppSheetView *tree_view,
8920 GtkAdjustment *adjustment)
8921 {
8922 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
8923
8924 pspp_sheet_view_set_adjustments (tree_view,
8925 tree_view->priv->hadjustment,
8926 adjustment);
8927
8928 g_object_notify (G_OBJECT (tree_view), "vadjustment");
8929 }
8930
8931 /* Column and header operations */
8932
8933 /**
8934 * pspp_sheet_view_get_headers_visible:
8935 * @tree_view: A #PsppSheetView.
8936 *
8937 * Returns %TRUE if the headers on the @tree_view are visible.
8938 *
8939 * Return value: Whether the headers are visible or not.
8940 **/
8941 gboolean
8942 pspp_sheet_view_get_headers_visible (PsppSheetView *tree_view)
8943 {
8944 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
8945
8946 return PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
8947 }
8948
8949 /**
8950 * pspp_sheet_view_set_headers_visible:
8951 * @tree_view: A #PsppSheetView.
8952 * @headers_visible: %TRUE if the headers are visible
8953 *
8954 * Sets the visibility state of the headers.
8955 **/
8956 void
8957 pspp_sheet_view_set_headers_visible (PsppSheetView *tree_view,
8958 gboolean headers_visible)
8959 {
8960 gint x, y;
8961 GList *list;
8962 PsppSheetViewColumn *column;
8963
8964 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
8965
8966 headers_visible = !! headers_visible;
8967
8968 if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE) == headers_visible)
8969 return;
8970
8971 if (headers_visible)
8972 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
8973 else
8974 PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
8975
8976 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
8977 {
8978 gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
8979 if (headers_visible)
8980 {
8981 gdk_window_move_resize (tree_view->priv->bin_window, x, y + TREE_VIEW_HEADER_HEIGHT (tree_view), tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.height - + TREE_VIEW_HEADER_HEIGHT (tree_view));
8982
8983 if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
8984 pspp_sheet_view_map_buttons (tree_view);
8985 }
8986 else
8987 {
8988 gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
8989
8990 for (list = tree_view->priv->columns; list; list = list->next)
8991 {
8992 column = list->data;
8993 if (column->button)
8994 gtk_widget_unmap (column->button);
8995 }
8996 gdk_window_hide (tree_view->priv->header_window);
8997 }
8998 }
8999
9000 tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
9001 tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
9002 tree_view->priv->vadjustment->lower = 0;
9003 tree_view->priv->vadjustment->upper = tree_view->priv->height;
9004 gtk_adjustment_changed (tree_view->priv->vadjustment);
9005
9006 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9007
9008 g_object_notify (G_OBJECT (tree_view), "headers-visible");
9009 }
9010
9011 /**
9012 * pspp_sheet_view_columns_autosize:
9013 * @tree_view: A #PsppSheetView.
9014 *
9015 * Resizes all columns to their optimal width. Only works after the
9016 * treeview has been realized.
9017 **/
9018 void
9019 pspp_sheet_view_columns_autosize (PsppSheetView *tree_view)
9020 {
9021 gboolean dirty = FALSE;
9022 GList *list;
9023 PsppSheetViewColumn *column;
9024
9025 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9026
9027 for (list = tree_view->priv->columns; list; list = list->next)
9028 {
9029 column = list->data;
9030 _pspp_sheet_view_column_cell_set_dirty (column);
9031 dirty = TRUE;
9032 }
9033
9034 if (dirty)
9035 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9036 }
9037
9038 /**
9039 * pspp_sheet_view_set_headers_clickable:
9040 * @tree_view: A #PsppSheetView.
9041 * @setting: %TRUE if the columns are clickable.
9042 *
9043 * Allow the column title buttons to be clicked.
9044 **/
9045 void
9046 pspp_sheet_view_set_headers_clickable (PsppSheetView *tree_view,
9047 gboolean setting)
9048 {
9049 GList *list;
9050
9051 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9052
9053 for (list = tree_view->priv->columns; list; list = list->next)
9054 pspp_sheet_view_column_set_clickable (PSPP_SHEET_VIEW_COLUMN (list->data), setting);
9055
9056 g_object_notify (G_OBJECT (tree_view), "headers-clickable");
9057 }
9058
9059
9060 /**
9061 * pspp_sheet_view_get_headers_clickable:
9062 * @tree_view: A #PsppSheetView.
9063 *
9064 * Returns whether all header columns are clickable.
9065 *
9066 * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
9067 *
9068 * Since: 2.10
9069 **/
9070 gboolean
9071 pspp_sheet_view_get_headers_clickable (PsppSheetView *tree_view)
9072 {
9073 GList *list;
9074
9075 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
9076
9077 for (list = tree_view->priv->columns; list; list = list->next)
9078 if (!PSPP_SHEET_VIEW_COLUMN (list->data)->clickable)
9079 return FALSE;
9080
9081 return TRUE;
9082 }
9083
9084 /**
9085 * pspp_sheet_view_set_rules_hint
9086 * @tree_view: a #PsppSheetView
9087 * @setting: %TRUE if the tree requires reading across rows
9088 *
9089 * This function tells GTK+ that the user interface for your
9090 * application requires users to read across tree rows and associate
9091 * cells with one another. By default, GTK+ will then render the tree
9092 * with alternating row colors. Do <emphasis>not</emphasis> use it
9093 * just because you prefer the appearance of the ruled tree; that's a
9094 * question for the theme. Some themes will draw tree rows in
9095 * alternating colors even when rules are turned off, and users who
9096 * prefer that appearance all the time can choose those themes. You
9097 * should call this function only as a <emphasis>semantic</emphasis>
9098 * hint to the theme engine that your tree makes alternating colors
9099 * useful from a functional standpoint (since it has lots of columns,
9100 * generally).
9101 *
9102 **/
9103 void
9104 pspp_sheet_view_set_rules_hint (PsppSheetView *tree_view,
9105 gboolean setting)
9106 {
9107 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9108
9109 setting = setting != FALSE;
9110
9111 if (tree_view->priv->has_rules != setting)
9112 {
9113 tree_view->priv->has_rules = setting;
9114 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
9115 }
9116
9117 g_object_notify (G_OBJECT (tree_view), "rules-hint");
9118 }
9119
9120 /**
9121 * pspp_sheet_view_get_rules_hint
9122 * @tree_view: a #PsppSheetView
9123 *
9124 * Gets the setting set by pspp_sheet_view_set_rules_hint().
9125 *
9126 * Return value: %TRUE if rules are useful for the user of this tree
9127 **/
9128 gboolean
9129 pspp_sheet_view_get_rules_hint (PsppSheetView *tree_view)
9130 {
9131 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
9132
9133 return tree_view->priv->has_rules;
9134 }
9135
9136 /* Public Column functions
9137 */
9138
9139 /**
9140 * pspp_sheet_view_append_column:
9141 * @tree_view: A #PsppSheetView.
9142 * @column: The #PsppSheetViewColumn to add.
9143 *
9144 * Appends @column to the list of columns.
9145 *
9146 * Return value: The number of columns in @tree_view after appending.
9147 **/
9148 gint
9149 pspp_sheet_view_append_column (PsppSheetView *tree_view,
9150 PsppSheetViewColumn *column)
9151 {
9152 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
9153 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
9154 g_return_val_if_fail (column->tree_view == NULL, -1);
9155
9156 return pspp_sheet_view_insert_column (tree_view, column, -1);
9157 }
9158
9159
9160 /**
9161 * pspp_sheet_view_remove_column:
9162 * @tree_view: A #PsppSheetView.
9163 * @column: The #PsppSheetViewColumn to remove.
9164 *
9165 * Removes @column from @tree_view.
9166 *
9167 * Return value: The number of columns in @tree_view after removing.
9168 **/
9169 gint
9170 pspp_sheet_view_remove_column (PsppSheetView *tree_view,
9171 PsppSheetViewColumn *column)
9172 {
9173 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
9174 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
9175 g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
9176
9177 if (tree_view->priv->focus_column == column)
9178 tree_view->priv->focus_column = NULL;
9179
9180 if (tree_view->priv->edited_column == column)
9181 {
9182 pspp_sheet_view_stop_editing (tree_view, TRUE);
9183
9184 /* no need to, but just to be sure ... */
9185 tree_view->priv->edited_column = NULL;
9186 }
9187
9188 _pspp_sheet_view_column_unset_tree_view (column);
9189
9190 tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
9191 tree_view->priv->n_columns--;
9192
9193 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9194 {
9195 GList *list;
9196
9197 _pspp_sheet_view_column_unrealize_button (column);
9198 for (list = tree_view->priv->columns; list; list = list->next)
9199 {
9200 PsppSheetViewColumn *tmp_column;
9201
9202 tmp_column = PSPP_SHEET_VIEW_COLUMN (list->data);
9203 if (tmp_column->visible)
9204 _pspp_sheet_view_column_cell_set_dirty (tmp_column);
9205 }
9206
9207 if (tree_view->priv->n_columns == 0 &&
9208 pspp_sheet_view_get_headers_visible (tree_view))
9209 gdk_window_hide (tree_view->priv->header_window);
9210
9211 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9212 }
9213
9214 g_object_unref (column);
9215 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9216
9217 return tree_view->priv->n_columns;
9218 }
9219
9220 /**
9221 * pspp_sheet_view_insert_column:
9222 * @tree_view: A #PsppSheetView.
9223 * @column: The #PsppSheetViewColumn to be inserted.
9224 * @position: The position to insert @column in.
9225 *
9226 * This inserts the @column into the @tree_view at @position. If @position is
9227 * -1, then the column is inserted at the end.
9228 *
9229 * Return value: The number of columns in @tree_view after insertion.
9230 **/
9231 gint
9232 pspp_sheet_view_insert_column (PsppSheetView *tree_view,
9233 PsppSheetViewColumn *column,
9234 gint position)
9235 {
9236 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
9237 g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
9238 g_return_val_if_fail (column->tree_view == NULL, -1);
9239
9240 g_object_ref_sink (column);
9241
9242 if (tree_view->priv->n_columns == 0 &&
9243 gtk_widget_get_realized (GTK_WIDGET (tree_view)) &&
9244 pspp_sheet_view_get_headers_visible (tree_view))
9245 {
9246 gdk_window_show (tree_view->priv->header_window);
9247 }
9248
9249 tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
9250 column, position);
9251 tree_view->priv->n_columns++;
9252
9253 _pspp_sheet_view_column_set_tree_view (column, tree_view);
9254
9255 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9256 {
9257 GList *list;
9258
9259 _pspp_sheet_view_column_realize_button (column);
9260
9261 for (list = tree_view->priv->columns; list; list = list->next)
9262 {
9263 column = PSPP_SHEET_VIEW_COLUMN (list->data);
9264 if (column->visible)
9265 _pspp_sheet_view_column_cell_set_dirty (column);
9266 }
9267 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9268 }
9269
9270 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9271
9272 return tree_view->priv->n_columns;
9273 }
9274
9275 /**
9276 * pspp_sheet_view_insert_column_with_attributes:
9277 * @tree_view: A #PsppSheetView
9278 * @position: The position to insert the new column in.
9279 * @title: The title to set the header to.
9280 * @cell: The #GtkCellRenderer.
9281 * @Varargs: A %NULL-terminated list of attributes.
9282 *
9283 * Creates a new #PsppSheetViewColumn and inserts it into the @tree_view at
9284 * @position. If @position is -1, then the newly created column is inserted at
9285 * the end. The column is initialized with the attributes given.
9286 *
9287 * Return value: The number of columns in @tree_view after insertion.
9288 **/
9289 gint
9290 pspp_sheet_view_insert_column_with_attributes (PsppSheetView *tree_view,
9291 gint position,
9292 const gchar *title,
9293 GtkCellRenderer *cell,
9294 ...)
9295 {
9296 PsppSheetViewColumn *column;
9297 gchar *attribute;
9298 va_list args;
9299 gint column_id;
9300
9301 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
9302
9303 column = pspp_sheet_view_column_new ();
9304 pspp_sheet_view_column_set_title (column, title);
9305 pspp_sheet_view_column_pack_start (column, cell, TRUE);
9306
9307 va_start (args, cell);
9308
9309 attribute = va_arg (args, gchar *);
9310
9311 while (attribute != NULL)
9312 {
9313 column_id = va_arg (args, gint);
9314 pspp_sheet_view_column_add_attribute (column, cell, attribute, column_id);
9315 attribute = va_arg (args, gchar *);
9316 }
9317
9318 va_end (args);
9319
9320 pspp_sheet_view_insert_column (tree_view, column, position);
9321
9322 return tree_view->priv->n_columns;
9323 }
9324
9325 /**
9326 * pspp_sheet_view_insert_column_with_data_func:
9327 * @tree_view: a #PsppSheetView
9328 * @position: Position to insert, -1 for append
9329 * @title: column title
9330 * @cell: cell renderer for column
9331 * @func: function to set attributes of cell renderer
9332 * @data: data for @func
9333 * @dnotify: destroy notifier for @data
9334 *
9335 * Convenience function that inserts a new column into the #PsppSheetView
9336 * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
9337 * attributes (normally using data from the model). See also
9338 * pspp_sheet_view_column_set_cell_data_func(), pspp_sheet_view_column_pack_start().
9339 *
9340 * Return value: number of columns in the tree view post-insert
9341 **/
9342 gint
9343 pspp_sheet_view_insert_column_with_data_func (PsppSheetView *tree_view,
9344 gint position,
9345 const gchar *title,
9346 GtkCellRenderer *cell,
9347 PsppSheetCellDataFunc func,
9348 gpointer data,
9349 GDestroyNotify dnotify)
9350 {
9351 PsppSheetViewColumn *column;
9352
9353 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
9354
9355 column = pspp_sheet_view_column_new ();
9356 pspp_sheet_view_column_set_title (column, title);
9357 pspp_sheet_view_column_pack_start (column, cell, TRUE);
9358 pspp_sheet_view_column_set_cell_data_func (column, cell, func, data, dnotify);
9359
9360 pspp_sheet_view_insert_column (tree_view, column, position);
9361
9362 return tree_view->priv->n_columns;
9363 }
9364
9365 /**
9366 * pspp_sheet_view_get_column:
9367 * @tree_view: A #PsppSheetView.
9368 * @n: The position of the column, counting from 0.
9369 *
9370 * Gets the #PsppSheetViewColumn at the given position in the #tree_view.
9371 *
9372 * Return value: The #PsppSheetViewColumn, or %NULL if the position is outside the
9373 * range of columns.
9374 **/
9375 PsppSheetViewColumn *
9376 pspp_sheet_view_get_column (PsppSheetView *tree_view,
9377 gint n)
9378 {
9379 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
9380
9381 if (n < 0 || n >= tree_view->priv->n_columns)
9382 return NULL;
9383
9384 if (tree_view->priv->columns == NULL)
9385 return NULL;
9386
9387 return PSPP_SHEET_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
9388 }
9389
9390 /**
9391 * pspp_sheet_view_get_columns:
9392 * @tree_view: A #PsppSheetView
9393 *
9394 * Returns a #GList of all the #PsppSheetViewColumn s currently in @tree_view.
9395 * The returned list must be freed with g_list_free ().
9396 *
9397 * Return value: (element-type PsppSheetViewColumn) (transfer container): A list of #PsppSheetViewColumn s
9398 **/
9399 GList *
9400 pspp_sheet_view_get_columns (PsppSheetView *tree_view)
9401 {
9402 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
9403
9404 return g_list_copy (tree_view->priv->columns);
9405 }
9406
9407 /**
9408 * pspp_sheet_view_move_column_after:
9409 * @tree_view: A #PsppSheetView
9410 * @column: The #PsppSheetViewColumn to be moved.
9411 * @base_column: (allow-none): The #PsppSheetViewColumn to be moved relative to, or %NULL.
9412 *
9413 * Moves @column to be after to @base_column. If @base_column is %NULL, then
9414 * @column is placed in the first position.
9415 **/
9416 void
9417 pspp_sheet_view_move_column_after (PsppSheetView *tree_view,
9418 PsppSheetViewColumn *column,
9419 PsppSheetViewColumn *base_column)
9420 {
9421 GList *column_list_el, *base_el = NULL;
9422
9423 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9424
9425 column_list_el = g_list_find (tree_view->priv->columns, column);
9426 g_return_if_fail (column_list_el != NULL);
9427
9428 if (base_column)
9429 {
9430 base_el = g_list_find (tree_view->priv->columns, base_column);
9431 g_return_if_fail (base_el != NULL);
9432 }
9433
9434 if (column_list_el->prev == base_el)
9435 return;
9436
9437 tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
9438 if (base_el == NULL)
9439 {
9440 column_list_el->prev = NULL;
9441 column_list_el->next = tree_view->priv->columns;
9442 if (column_list_el->next)
9443 column_list_el->next->prev = column_list_el;
9444 tree_view->priv->columns = column_list_el;
9445 }
9446 else
9447 {
9448 column_list_el->prev = base_el;
9449 column_list_el->next = base_el->next;
9450 if (column_list_el->next)
9451 column_list_el->next->prev = column_list_el;
9452 base_el->next = column_list_el;
9453 }
9454
9455 if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
9456 {
9457 gtk_widget_queue_resize (GTK_WIDGET (tree_view));
9458 pspp_sheet_view_size_allocate_columns (GTK_WIDGET (tree_view), NULL);
9459 }
9460
9461 g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
9462 }
9463
9464 /**
9465 * pspp_sheet_view_set_column_drag_function:
9466 * @tree_view: A #PsppSheetView.
9467 * @func: (allow-none): A function to determine which columns are reorderable, or %NULL.
9468 * @user_data: (allow-none): User data to be passed to @func, or %NULL
9469 * @destroy: (allow-none): Destroy notifier for @user_data, or %NULL
9470 *
9471 * Sets a user function for determining where a column may be dropped when
9472 * dragged. This function is called on every column pair in turn at the
9473 * beginning of a column drag to determine where a drop can take place. The
9474 * arguments passed to @func are: the @tree_view, the #PsppSheetViewColumn being
9475 * dragged, the two #PsppSheetViewColumn s determining the drop spot, and
9476 * @user_data. If either of the #PsppSheetViewColumn arguments for the drop spot
9477 * are %NULL, then they indicate an edge. If @func is set to be %NULL, then
9478 * @tree_view reverts to the default behavior of allowing all columns to be
9479 * dropped everywhere.
9480 **/
9481 void
9482 pspp_sheet_view_set_column_drag_function (PsppSheetView *tree_view,
9483 PsppSheetViewColumnDropFunc func,
9484 gpointer user_data,
9485 GDestroyNotify destroy)
9486 {
9487 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9488
9489 if (tree_view->priv->column_drop_func_data_destroy)
9490 tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
9491
9492 tree_view->priv->column_drop_func = func;
9493 tree_view->priv->column_drop_func_data = user_data;
9494 tree_view->priv->column_drop_func_data_destroy = destroy;
9495 }
9496
9497 /**
9498 * pspp_sheet_view_scroll_to_point:
9499 * @tree_view: a #PsppSheetView
9500 * @tree_x: X coordinate of new top-left pixel of visible area, or -1
9501 * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
9502 *
9503 * Scrolls the tree view such that the top-left corner of the visible
9504 * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
9505 * in tree coordinates. The @tree_view must be realized before
9506 * this function is called. If it isn't, you probably want to be
9507 * using pspp_sheet_view_scroll_to_cell().
9508 *
9509 * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
9510 **/
9511 void
9512 pspp_sheet_view_scroll_to_point (PsppSheetView *tree_view,
9513 gint tree_x,
9514 gint tree_y)
9515 {
9516 GtkAdjustment *hadj;
9517 GtkAdjustment *vadj;
9518
9519 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9520 g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
9521
9522 hadj = tree_view->priv->hadjustment;
9523 vadj = tree_view->priv->vadjustment;
9524
9525 if (tree_x != -1)
9526 gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper - hadj->page_size));
9527 if (tree_y != -1)
9528 gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper - vadj->page_size));
9529 }
9530
9531 /**
9532 * pspp_sheet_view_scroll_to_cell:
9533 * @tree_view: A #PsppSheetView.
9534 * @path: (allow-none): The path of the row to move to, or %NULL.
9535 * @column: (allow-none): The #PsppSheetViewColumn to move horizontally to, or %NULL.
9536 * @use_align: whether to use alignment arguments, or %FALSE.
9537 * @row_align: The vertical alignment of the row specified by @path.
9538 * @col_align: The horizontal alignment of the column specified by @column.
9539 *
9540 * Moves the alignments of @tree_view to the position specified by @column and
9541 * @path. If @column is %NULL, then no horizontal scrolling occurs. Likewise,
9542 * if @path is %NULL no vertical scrolling occurs. At a minimum, one of @column
9543 * or @path need to be non-%NULL. @row_align determines where the row is
9544 * placed, and @col_align determines where @column is placed. Both are expected
9545 * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
9546 * right/bottom alignment, 0.5 means center.
9547 *
9548 * If @use_align is %FALSE, then the alignment arguments are ignored, and the
9549 * tree does the minimum amount of work to scroll the cell onto the screen.
9550 * This means that the cell will be scrolled to the edge closest to its current
9551 * position. If the cell is currently visible on the screen, nothing is done.
9552 *
9553 * This function only works if the model is set, and @path is a valid row on the
9554 * model. If the model changes before the @tree_view is realized, the centered
9555 * path will be modified to reflect this change.
9556 **/
9557 void
9558 pspp_sheet_view_scroll_to_cell (PsppSheetView *tree_view,
9559 GtkTreePath *path,
9560 PsppSheetViewColumn *column,
9561 gboolean use_align,
9562 gfloat row_align,
9563 gfloat col_align)
9564 {
9565 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9566 g_return_if_fail (tree_view->priv->model != NULL);
9567 g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
9568 g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
9569 g_return_if_fail (path != NULL || column != NULL);
9570
9571 #if 0
9572 g_print ("pspp_sheet_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
9573 gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
9574 #endif
9575 row_align = CLAMP (row_align, 0.0, 1.0);
9576 col_align = CLAMP (col_align, 0.0, 1.0);
9577
9578
9579 /* Note: Despite the benefits that come from having one code path for the
9580 * scrolling code, we short-circuit validate_visible_area's immplementation as
9581 * it is much slower than just going to the point.
9582 */
9583 if (!gtk_widget_get_visible (GTK_WIDGET (tree_view)) ||
9584 !gtk_widget_get_realized (GTK_WIDGET (tree_view))
9585 /* XXX || GTK_WIDGET_ALLOC_NEEDED (tree_view) */)
9586 {
9587 if (tree_view->priv->scroll_to_path)
9588 gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
9589
9590 tree_view->priv->scroll_to_path = NULL;
9591 tree_view->priv->scroll_to_column = NULL;
9592
9593 if (path)
9594 tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
9595 if (column)
9596 tree_view->priv->scroll_to_column = column;
9597 tree_view->priv->scroll_to_use_align = use_align;
9598 tree_view->priv->scroll_to_row_align = row_align;
9599 tree_view->priv->scroll_to_col_align = col_align;
9600
9601 install_presize_handler (tree_view);
9602 }
9603 else
9604 {
9605 GdkRectangle cell_rect;
9606 GdkRectangle vis_rect;
9607 gint dest_x, dest_y;
9608
9609 pspp_sheet_view_get_background_area (tree_view, path, column, &cell_rect);
9610 pspp_sheet_view_get_visible_rect (tree_view, &vis_rect);
9611
9612 cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, cell_rect.y);
9613
9614 dest_x = vis_rect.x;
9615 dest_y = vis_rect.y;
9616
9617 if (column)
9618 {
9619 if (use_align)
9620 {
9621 dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
9622 }
9623 else
9624 {
9625 if (cell_rect.x < vis_rect.x)
9626 dest_x = cell_rect.x;
9627 if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
9628 dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
9629 }
9630 }
9631
9632 if (path)
9633 {
9634 if (use_align)
9635 {
9636 dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
9637 dest_y = MAX (dest_y, 0);
9638 }
9639 else
9640 {
9641 if (cell_rect.y < vis_rect.y)
9642 dest_y = cell_rect.y;
9643 if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
9644 dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
9645 }
9646 }
9647
9648 pspp_sheet_view_scroll_to_point (tree_view, dest_x, dest_y);
9649 }
9650 }
9651
9652 /**
9653 * pspp_sheet_view_row_activated:
9654 * @tree_view: A #PsppSheetView
9655 * @path: The #GtkTreePath to be activated.
9656 * @column: The #PsppSheetViewColumn to be activated.
9657 *
9658 * Activates the cell determined by @path and @column.
9659 **/
9660 void
9661 pspp_sheet_view_row_activated (PsppSheetView *tree_view,
9662 GtkTreePath *path,
9663 PsppSheetViewColumn *column)
9664 {
9665 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9666
9667 g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
9668 }
9669
9670
9671 /**
9672 * pspp_sheet_view_get_reorderable:
9673 * @tree_view: a #PsppSheetView
9674 *
9675 * Retrieves whether the user can reorder the tree via drag-and-drop. See
9676 * pspp_sheet_view_set_reorderable().
9677 *
9678 * Return value: %TRUE if the tree can be reordered.
9679 **/
9680 gboolean
9681 pspp_sheet_view_get_reorderable (PsppSheetView *tree_view)
9682 {
9683 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
9684
9685 return tree_view->priv->reorderable;
9686 }
9687
9688 /**
9689 * pspp_sheet_view_set_reorderable:
9690 * @tree_view: A #PsppSheetView.
9691 * @reorderable: %TRUE, if the tree can be reordered.
9692 *
9693 * This function is a convenience function to allow you to reorder
9694 * models that support the #GtkDragSourceIface and the
9695 * #GtkDragDestIface. Both #GtkTreeStore and #GtkListStore support
9696 * these. If @reorderable is %TRUE, then the user can reorder the
9697 * model by dragging and dropping rows. The developer can listen to
9698 * these changes by connecting to the model's row_inserted and
9699 * row_deleted signals. The reordering is implemented by setting up
9700 * the tree view as a drag source and destination. Therefore, drag and
9701 * drop can not be used in a reorderable view for any other purpose.
9702 *
9703 * This function does not give you any degree of control over the order -- any
9704 * reordering is allowed. If more control is needed, you should probably
9705 * handle drag and drop manually.
9706 **/
9707 void
9708 pspp_sheet_view_set_reorderable (PsppSheetView *tree_view,
9709 gboolean reorderable)
9710 {
9711 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9712
9713 reorderable = reorderable != FALSE;
9714
9715 if (tree_view->priv->reorderable == reorderable)
9716 return;
9717
9718 if (reorderable)
9719 {
9720 const GtkTargetEntry row_targets[] = {
9721 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
9722 };
9723
9724 pspp_sheet_view_enable_model_drag_source (tree_view,
9725 GDK_BUTTON1_MASK,
9726 row_targets,
9727 G_N_ELEMENTS (row_targets),
9728 GDK_ACTION_MOVE);
9729 pspp_sheet_view_enable_model_drag_dest (tree_view,
9730 row_targets,
9731 G_N_ELEMENTS (row_targets),
9732 GDK_ACTION_MOVE);
9733 }
9734 else
9735 {
9736 pspp_sheet_view_unset_rows_drag_source (tree_view);
9737 pspp_sheet_view_unset_rows_drag_dest (tree_view);
9738 }
9739
9740 tree_view->priv->reorderable = reorderable;
9741
9742 g_object_notify (G_OBJECT (tree_view), "reorderable");
9743 }
9744
9745 /* If CLEAR_AND_SELECT is true, then the row will be selected and, unless Shift
9746 is pressed, other rows will be unselected.
9747
9748 If CLAMP_NODE is true, then the sheetview will scroll to make the row
9749 visible. */
9750 static void
9751 pspp_sheet_view_real_set_cursor (PsppSheetView *tree_view,
9752 GtkTreePath *path,
9753 gboolean clear_and_select,
9754 gboolean clamp_node)
9755 {
9756 int node = -1;
9757
9758 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
9759 {
9760 GtkTreePath *cursor_path;
9761 cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
9762 pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
9763 gtk_tree_path_free (cursor_path);
9764 }
9765
9766 gtk_tree_row_reference_free (tree_view->priv->cursor);
9767 tree_view->priv->cursor = NULL;
9768
9769 _pspp_sheet_view_find_node (tree_view, path, &node);
9770 tree_view->priv->cursor =
9771 gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
9772 tree_view->priv->model,
9773 path);
9774
9775 if (tree_view->priv->row_count > 0)
9776 {
9777 int new_node = -1;
9778
9779 if (clear_and_select && !tree_view->priv->ctrl_pressed)
9780 {
9781 GtkTreeSelectMode mode = 0;
9782
9783 if (tree_view->priv->ctrl_pressed)
9784 mode |= GTK_TREE_SELECT_MODE_TOGGLE;
9785 if (tree_view->priv->shift_pressed)
9786 mode |= GTK_TREE_SELECT_MODE_EXTEND;
9787
9788 _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
9789 node, path, mode,
9790 FALSE);
9791 }
9792
9793 /* We have to re-find tree and node here again, somebody might have
9794 * cleared the node or the whole tree in the PsppSheetSelection::changed
9795 * callback. If the nodes differ we bail out here.
9796 */
9797 _pspp_sheet_view_find_node (tree_view, path, &new_node);
9798
9799 if (node != new_node)
9800 return;
9801
9802 if (clamp_node)
9803 {
9804 pspp_sheet_view_clamp_node_visible (tree_view, node);
9805 _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
9806 }
9807 }
9808
9809 g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
9810 }
9811
9812 /**
9813 * pspp_sheet_view_get_cursor:
9814 * @tree_view: A #PsppSheetView
9815 * @path: (allow-none): A pointer to be filled with the current cursor path, or %NULL
9816 * @focus_column: (allow-none): A pointer to be filled with the current focus column, or %NULL
9817 *
9818 * Fills in @path and @focus_column with the current path and focus column. If
9819 * the cursor isn't currently set, then *@path will be %NULL. If no column
9820 * currently has focus, then *@focus_column will be %NULL.
9821 *
9822 * The returned #GtkTreePath must be freed with gtk_tree_path_free() when
9823 * you are done with it.
9824 **/
9825 void
9826 pspp_sheet_view_get_cursor (PsppSheetView *tree_view,
9827 GtkTreePath **path,
9828 PsppSheetViewColumn **focus_column)
9829 {
9830 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9831
9832 if (path)
9833 {
9834 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
9835 *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
9836 else
9837 *path = NULL;
9838 }
9839
9840 if (focus_column)
9841 {
9842 *focus_column = tree_view->priv->focus_column;
9843 }
9844 }
9845
9846 /**
9847 * pspp_sheet_view_set_cursor:
9848 * @tree_view: A #PsppSheetView
9849 * @path: A #GtkTreePath
9850 * @focus_column: (allow-none): A #PsppSheetViewColumn, or %NULL
9851 * @start_editing: %TRUE if the specified cell should start being edited.
9852 *
9853 * Sets the current keyboard focus to be at @path, and selects it. This is
9854 * useful when you want to focus the user's attention on a particular row. If
9855 * @focus_column is not %NULL, then focus is given to the column specified by
9856 * it. Additionally, if @focus_column is specified, and @start_editing is
9857 * %TRUE, then editing should be started in the specified cell.
9858 * This function is often followed by @gtk_widget_grab_focus (@tree_view)
9859 * in order to give keyboard focus to the widget. Please note that editing
9860 * can only happen when the widget is realized.
9861 *
9862 * If @path is invalid for @model, the current cursor (if any) will be unset
9863 * and the function will return without failing.
9864 **/
9865 void
9866 pspp_sheet_view_set_cursor (PsppSheetView *tree_view,
9867 GtkTreePath *path,
9868 PsppSheetViewColumn *focus_column,
9869 gboolean start_editing)
9870 {
9871 pspp_sheet_view_set_cursor_on_cell (tree_view, path, focus_column,
9872 NULL, start_editing);
9873 }
9874
9875 /**
9876 * pspp_sheet_view_set_cursor_on_cell:
9877 * @tree_view: A #PsppSheetView
9878 * @path: A #GtkTreePath
9879 * @focus_column: (allow-none): A #PsppSheetViewColumn, or %NULL
9880 * @focus_cell: (allow-none): A #GtkCellRenderer, or %NULL
9881 * @start_editing: %TRUE if the specified cell should start being edited.
9882 *
9883 * Sets the current keyboard focus to be at @path, and selects it. This is
9884 * useful when you want to focus the user's attention on a particular row. If
9885 * @focus_column is not %NULL, then focus is given to the column specified by
9886 * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
9887 * contains 2 or more editable or activatable cells, then focus is given to
9888 * the cell specified by @focus_cell. Additionally, if @focus_column is
9889 * specified, and @start_editing is %TRUE, then editing should be started in
9890 * the specified cell. This function is often followed by
9891 * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
9892 * widget. Please note that editing can only happen when the widget is
9893 * realized.
9894 *
9895 * If @path is invalid for @model, the current cursor (if any) will be unset
9896 * and the function will return without failing.
9897 *
9898 * Since: 2.2
9899 **/
9900 void
9901 pspp_sheet_view_set_cursor_on_cell (PsppSheetView *tree_view,
9902 GtkTreePath *path,
9903 PsppSheetViewColumn *focus_column,
9904 GtkCellRenderer *focus_cell,
9905 gboolean start_editing)
9906 {
9907 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
9908 g_return_if_fail (path != NULL);
9909 g_return_if_fail (focus_column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (focus_column));
9910
9911 if (!tree_view->priv->model)
9912 return;
9913
9914 if (focus_cell)
9915 {
9916 g_return_if_fail (focus_column);
9917 g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
9918 }
9919
9920 /* cancel the current editing, if it exists */
9921 if (tree_view->priv->edited_column &&
9922 tree_view->priv->edited_column->editable_widget)
9923 pspp_sheet_view_stop_editing (tree_view, TRUE);
9924
9925 pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE);
9926
9927 if (focus_column && focus_column->visible)
9928 {
9929 GList *list;
9930 gboolean column_in_tree = FALSE;
9931
9932 for (list = tree_view->priv->columns; list; list = list->next)
9933 if (list->data == focus_column)
9934 {
9935 column_in_tree = TRUE;
9936 break;
9937 }
9938 g_return_if_fail (column_in_tree);
9939 tree_view->priv->focus_column = focus_column;
9940 if (focus_cell)
9941 pspp_sheet_view_column_focus_cell (focus_column, focus_cell);
9942 if (start_editing)
9943 pspp_sheet_view_start_editing (tree_view, path);
9944
9945 pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
9946 pspp_sheet_selection_select_column (tree_view->priv->selection, focus_column);
9947
9948 }
9949 }
9950
9951 /**
9952 * pspp_sheet_view_get_bin_window:
9953 * @tree_view: A #PsppSheetView
9954 *
9955 * Returns the window that @tree_view renders to. This is used primarily to
9956 * compare to <literal>event->window</literal> to confirm that the event on
9957 * @tree_view is on the right window.
9958 *
9959 * Return value: A #GdkWindow, or %NULL when @tree_view hasn't been realized yet
9960 **/
9961 GdkWindow *
9962 pspp_sheet_view_get_bin_window (PsppSheetView *tree_view)
9963 {
9964 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
9965
9966 return tree_view->priv->bin_window;
9967 }
9968
9969 /**
9970 * pspp_sheet_view_get_path_at_pos:
9971 * @tree_view: A #PsppSheetView.
9972 * @x: The x position to be identified (relative to bin_window).
9973 * @y: The y position to be identified (relative to bin_window).
9974 * @path: (out) (allow-none): A pointer to a #GtkTreePath pointer to be filled in, or %NULL
9975 * @column: (out) (allow-none): A pointer to a #PsppSheetViewColumn pointer to be filled in, or %NULL
9976 * @cell_x: (out) (allow-none): A pointer where the X coordinate relative to the cell can be placed, or %NULL
9977 * @cell_y: (out) (allow-none): A pointer where the Y coordinate relative to the cell can be placed, or %NULL
9978 *
9979 * Finds the path at the point (@x, @y), relative to bin_window coordinates
9980 * (please see pspp_sheet_view_get_bin_window()).
9981 * That is, @x and @y are relative to an events coordinates. @x and @y must
9982 * come from an event on the @tree_view only where <literal>event->window ==
9983 * pspp_sheet_view_get_bin_window (<!-- -->)</literal>. It is primarily for
9984 * things like popup menus. If @path is non-%NULL, then it will be filled
9985 * with the #GtkTreePath at that point. This path should be freed with
9986 * gtk_tree_path_free(). If @column is non-%NULL, then it will be filled
9987 * with the column at that point. @cell_x and @cell_y return the coordinates
9988 * relative to the cell background (i.e. the @background_area passed to
9989 * gtk_cell_renderer_render()). This function is only meaningful if
9990 * @tree_view is realized. Therefore this function will always return %FALSE
9991 * if @tree_view is not realized or does not have a model.
9992 *
9993 * For converting widget coordinates (eg. the ones you get from
9994 * GtkWidget::query-tooltip), please see
9995 * pspp_sheet_view_convert_widget_to_bin_window_coords().
9996 *
9997 * Return value: %TRUE if a row exists at that coordinate.
9998 **/
9999 gboolean
10000 pspp_sheet_view_get_path_at_pos (PsppSheetView *tree_view,
10001 gint x,
10002 gint y,
10003 GtkTreePath **path,
10004 PsppSheetViewColumn **column,
10005 gint *cell_x,
10006 gint *cell_y)
10007 {
10008 int node;
10009 gint y_offset;
10010
10011 g_return_val_if_fail (tree_view != NULL, FALSE);
10012
10013 if (path)
10014 *path = NULL;
10015 if (column)
10016 *column = NULL;
10017
10018 if (tree_view->priv->bin_window == NULL)
10019 return FALSE;
10020
10021 if (tree_view->priv->row_count == 0)
10022 return FALSE;
10023
10024 if (x > tree_view->priv->hadjustment->upper)
10025 return FALSE;
10026
10027 if (x < 0 || y < 0)
10028 return FALSE;
10029
10030 if (column || cell_x)
10031 {
10032 PsppSheetViewColumn *tmp_column;
10033 PsppSheetViewColumn *last_column = NULL;
10034 GList *list;
10035 gint remaining_x = x;
10036 gboolean found = FALSE;
10037 gboolean rtl;
10038
10039 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
10040 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
10041 list;
10042 list = (rtl ? list->prev : list->next))
10043 {
10044 tmp_column = list->data;
10045
10046 if (tmp_column->visible == FALSE)
10047 continue;
10048
10049 last_column = tmp_column;
10050 if (remaining_x <= tmp_column->width)
10051 {
10052 found = TRUE;
10053
10054 if (column)
10055 *column = tmp_column;
10056
10057 if (cell_x)
10058 *cell_x = remaining_x;
10059
10060 break;
10061 }
10062 remaining_x -= tmp_column->width;
10063 }
10064
10065 /* If found is FALSE and there is a last_column, then it the remainder
10066 * space is in that area
10067 */
10068 if (!found)
10069 {
10070 if (last_column)
10071 {
10072 if (column)
10073 *column = last_column;
10074
10075 if (cell_x)
10076 *cell_x = last_column->width + remaining_x;
10077 }
10078 else
10079 {
10080 return FALSE;
10081 }
10082 }
10083 }
10084
10085 y_offset = pspp_sheet_view_find_offset (tree_view,
10086 TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
10087 &node);
10088
10089 if (node < 0)
10090 return FALSE;
10091
10092 if (cell_y)
10093 *cell_y = y_offset;
10094
10095 if (path)
10096 *path = _pspp_sheet_view_find_path (tree_view, node);
10097
10098 return TRUE;
10099 }
10100
10101 /* Computes 'cell_area' from 'background_area', which must be the background
10102 area for a cell. Set 'subtract_focus_rect' to TRUE to compute the cell area
10103 as passed to a GtkCellRenderer's "render" function, or to FALSE to compute
10104 the cell area as passed to _pspp_sheet_view_column_cell_render().
10105
10106 'column' is required to properly adjust 'cell_area->x' and
10107 'cell_area->width'. It may be set to NULL if these values are not of
10108 interest. In this case 'cell_area->x' and 'cell_area->width' will be
10109 returned as 0. */
10110 static void
10111 pspp_sheet_view_adjust_cell_area (PsppSheetView *tree_view,
10112 PsppSheetViewColumn *column,
10113 const GdkRectangle *background_area,
10114 gboolean subtract_focus_rect,
10115 GdkRectangle *cell_area)
10116 {
10117 gint vertical_separator;
10118 gint horizontal_separator;
10119
10120 *cell_area = *background_area;
10121
10122 gtk_widget_style_get (GTK_WIDGET (tree_view),
10123 "vertical-separator", &vertical_separator,
10124 "horizontal-separator", &horizontal_separator,
10125 NULL);
10126 cell_area->x += horizontal_separator / 2;
10127 cell_area->y += vertical_separator / 2;
10128 cell_area->width -= horizontal_separator;
10129 cell_area->height -= vertical_separator;
10130
10131 if (subtract_focus_rect)
10132 {
10133 int focus_line_width;
10134
10135 gtk_widget_style_get (GTK_WIDGET (tree_view),
10136 "focus-line-width", &focus_line_width,
10137 NULL);
10138 cell_area->x += focus_line_width;
10139 cell_area->y += focus_line_width;
10140 cell_area->width -= 2 * focus_line_width;
10141 cell_area->height -= 2 * focus_line_width;
10142 }
10143
10144 if (tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_NONE)
10145 {
10146 gint grid_line_width;
10147 gtk_widget_style_get (GTK_WIDGET (tree_view),
10148 "grid-line-width", &grid_line_width,
10149 NULL);
10150
10151 if ((tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
10152 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH)
10153 && column != NULL)
10154 {
10155 PsppSheetViewColumn *first_column, *last_column;
10156 GList *list;
10157
10158 /* Find the last visible column. */
10159 last_column = NULL;
10160 for (list = g_list_last (tree_view->priv->columns);
10161 list;
10162 list = list->prev)
10163 {
10164 PsppSheetViewColumn *c = list->data;
10165 if (c->visible)
10166 {
10167 last_column = c;
10168 break;
10169 }
10170 }
10171
10172 /* Find the first visible column. */
10173 first_column = NULL;
10174 for (list = g_list_first (tree_view->priv->columns);
10175 list;
10176 list = list->next)
10177 {
10178 PsppSheetViewColumn *c = list->data;
10179 if (c->visible)
10180 {
10181 first_column = c;
10182 break;
10183 }
10184 }
10185
10186 if (column == first_column)
10187 {
10188 cell_area->width -= grid_line_width / 2;
10189 }
10190 else if (column == last_column)
10191 {
10192 cell_area->x += grid_line_width / 2;
10193 cell_area->width -= grid_line_width / 2;
10194 }
10195 else
10196 {
10197 cell_area->x += grid_line_width / 2;
10198 cell_area->width -= grid_line_width;
10199 }
10200 }
10201
10202 if (tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
10203 || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH)
10204 {
10205 cell_area->y += grid_line_width / 2;
10206 cell_area->height -= grid_line_width;
10207 }
10208 }
10209
10210 if (column == NULL)
10211 {
10212 cell_area->x = 0;
10213 cell_area->width = 0;
10214 }
10215 }
10216
10217 /**
10218 * pspp_sheet_view_get_cell_area:
10219 * @tree_view: a #PsppSheetView
10220 * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10221 * @column: (allow-none): a #PsppSheetViewColumn for the column, or %NULL to get only vertical coordinates
10222 * @rect: rectangle to fill with cell rect
10223 *
10224 * Fills the bounding rectangle in bin_window coordinates for the cell at the
10225 * row specified by @path and the column specified by @column. If @path is
10226 * %NULL, or points to a path not currently displayed, the @y and @height fields
10227 * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10228 * fields will be filled with 0. The sum of all cell rects does not cover the
10229 * entire tree; there are extra pixels in between rows, for example. The
10230 * returned rectangle is equivalent to the @cell_area passed to
10231 * gtk_cell_renderer_render(). This function is only valid if @tree_view is
10232 * realized.
10233 **/
10234 void
10235 pspp_sheet_view_get_cell_area (PsppSheetView *tree_view,
10236 GtkTreePath *path,
10237 PsppSheetViewColumn *column,
10238 GdkRectangle *rect)
10239 {
10240 GdkRectangle background_area;
10241
10242 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10243 g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
10244 g_return_if_fail (rect != NULL);
10245 g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view);
10246 g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
10247
10248 pspp_sheet_view_get_background_area (tree_view, path, column,
10249 &background_area);
10250 pspp_sheet_view_adjust_cell_area (tree_view, column, &background_area,
10251 FALSE, rect);
10252 }
10253
10254 /**
10255 * pspp_sheet_view_get_background_area:
10256 * @tree_view: a #PsppSheetView
10257 * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
10258 * @column: (allow-none): a #PsppSheetViewColumn for the column, or %NULL to get only vertical coordiantes
10259 * @rect: rectangle to fill with cell background rect
10260 *
10261 * Fills the bounding rectangle in bin_window coordinates for the cell at the
10262 * row specified by @path and the column specified by @column. If @path is
10263 * %NULL, or points to a node not found in the tree, the @y and @height fields of
10264 * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
10265 * fields will be filled with 0. The returned rectangle is equivalent to the
10266 * @background_area passed to gtk_cell_renderer_render(). These background
10267 * areas tile to cover the entire bin window. Contrast with the @cell_area,
10268 * returned by pspp_sheet_view_get_cell_area(), which returns only the cell
10269 * itself, excluding surrounding borders.
10270 *
10271 **/
10272 void
10273 pspp_sheet_view_get_background_area (PsppSheetView *tree_view,
10274 GtkTreePath *path,
10275 PsppSheetViewColumn *column,
10276 GdkRectangle *rect)
10277 {
10278 int node = -1;
10279
10280 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10281 g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
10282 g_return_if_fail (rect != NULL);
10283
10284 rect->x = 0;
10285 rect->y = 0;
10286 rect->width = 0;
10287 rect->height = 0;
10288
10289 if (path)
10290 {
10291 /* Get vertical coords */
10292
10293 _pspp_sheet_view_find_node (tree_view, path, &node);
10294 if (node < 0)
10295 return;
10296
10297 rect->y = BACKGROUND_FIRST_PIXEL (tree_view, node);
10298
10299 rect->height = ROW_HEIGHT (tree_view);
10300 }
10301
10302 if (column)
10303 {
10304 gint x2 = 0;
10305
10306 pspp_sheet_view_get_background_xrange (tree_view, column, &rect->x, &x2);
10307 rect->width = x2 - rect->x;
10308 }
10309 }
10310
10311 /**
10312 * pspp_sheet_view_get_visible_rect:
10313 * @tree_view: a #PsppSheetView
10314 * @visible_rect: rectangle to fill
10315 *
10316 * Fills @visible_rect with the currently-visible region of the
10317 * buffer, in tree coordinates. Convert to bin_window coordinates with
10318 * pspp_sheet_view_convert_tree_to_bin_window_coords().
10319 * Tree coordinates start at 0,0 for row 0 of the tree, and cover the entire
10320 * scrollable area of the tree.
10321 **/
10322 void
10323 pspp_sheet_view_get_visible_rect (PsppSheetView *tree_view,
10324 GdkRectangle *visible_rect)
10325 {
10326 GtkWidget *widget;
10327
10328 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10329
10330 widget = GTK_WIDGET (tree_view);
10331
10332 if (visible_rect)
10333 {
10334 visible_rect->x = tree_view->priv->hadjustment->value;
10335 visible_rect->y = tree_view->priv->vadjustment->value;
10336 visible_rect->width = widget->allocation.width;
10337 visible_rect->height = widget->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
10338 }
10339 }
10340
10341 /**
10342 * pspp_sheet_view_widget_to_tree_coords:
10343 * @tree_view: a #PsppSheetView
10344 * @wx: X coordinate relative to bin_window
10345 * @wy: Y coordinate relative to bin_window
10346 * @tx: return location for tree X coordinate
10347 * @ty: return location for tree Y coordinate
10348 *
10349 * Converts bin_window coordinates to coordinates for the
10350 * tree (the full scrollable area of the tree).
10351 *
10352 * Deprecated: 2.12: Due to historial reasons the name of this function is
10353 * incorrect. For converting coordinates relative to the widget to
10354 * bin_window coordinates, please see
10355 * pspp_sheet_view_convert_widget_to_bin_window_coords().
10356 *
10357 **/
10358 void
10359 pspp_sheet_view_widget_to_tree_coords (PsppSheetView *tree_view,
10360 gint wx,
10361 gint wy,
10362 gint *tx,
10363 gint *ty)
10364 {
10365 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10366
10367 if (tx)
10368 *tx = wx + tree_view->priv->hadjustment->value;
10369 if (ty)
10370 *ty = wy + tree_view->priv->dy;
10371 }
10372
10373 /**
10374 * pspp_sheet_view_tree_to_widget_coords:
10375 * @tree_view: a #PsppSheetView
10376 * @tx: tree X coordinate
10377 * @ty: tree Y coordinate
10378 * @wx: return location for X coordinate relative to bin_window
10379 * @wy: return location for Y coordinate relative to bin_window
10380 *
10381 * Converts tree coordinates (coordinates in full scrollable area of the tree)
10382 * to bin_window coordinates.
10383 *
10384 * Deprecated: 2.12: Due to historial reasons the name of this function is
10385 * incorrect. For converting bin_window coordinates to coordinates relative
10386 * to bin_window, please see
10387 * pspp_sheet_view_convert_bin_window_to_widget_coords().
10388 *
10389 **/
10390 void
10391 pspp_sheet_view_tree_to_widget_coords (PsppSheetView *tree_view,
10392 gint tx,
10393 gint ty,
10394 gint *wx,
10395 gint *wy)
10396 {
10397 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10398
10399 if (wx)
10400 *wx = tx - tree_view->priv->hadjustment->value;
10401 if (wy)
10402 *wy = ty - tree_view->priv->dy;
10403 }
10404
10405
10406 /**
10407 * pspp_sheet_view_convert_widget_to_tree_coords:
10408 * @tree_view: a #PsppSheetView
10409 * @wx: X coordinate relative to the widget
10410 * @wy: Y coordinate relative to the widget
10411 * @tx: return location for tree X coordinate
10412 * @ty: return location for tree Y coordinate
10413 *
10414 * Converts widget coordinates to coordinates for the
10415 * tree (the full scrollable area of the tree).
10416 *
10417 * Since: 2.12
10418 **/
10419 void
10420 pspp_sheet_view_convert_widget_to_tree_coords (PsppSheetView *tree_view,
10421 gint wx,
10422 gint wy,
10423 gint *tx,
10424 gint *ty)
10425 {
10426 gint x, y;
10427
10428 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10429
10430 pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view,
10431 wx, wy,
10432 &x, &y);
10433 pspp_sheet_view_convert_bin_window_to_tree_coords (tree_view,
10434 x, y,
10435 tx, ty);
10436 }
10437
10438 /**
10439 * pspp_sheet_view_convert_tree_to_widget_coords:
10440 * @tree_view: a #PsppSheetView
10441 * @tx: X coordinate relative to the tree
10442 * @ty: Y coordinate relative to the tree
10443 * @wx: return location for widget X coordinate
10444 * @wy: return location for widget Y coordinate
10445 *
10446 * Converts tree coordinates (coordinates in full scrollable area of the tree)
10447 * to widget coordinates.
10448 *
10449 * Since: 2.12
10450 **/
10451 void
10452 pspp_sheet_view_convert_tree_to_widget_coords (PsppSheetView *tree_view,
10453 gint tx,
10454 gint ty,
10455 gint *wx,
10456 gint *wy)
10457 {
10458 gint x, y;
10459
10460 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10461
10462 pspp_sheet_view_convert_tree_to_bin_window_coords (tree_view,
10463 tx, ty,
10464 &x, &y);
10465 pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
10466 x, y,
10467 wx, wy);
10468 }
10469
10470 /**
10471 * pspp_sheet_view_convert_widget_to_bin_window_coords:
10472 * @tree_view: a #PsppSheetView
10473 * @wx: X coordinate relative to the widget
10474 * @wy: Y coordinate relative to the widget
10475 * @bx: return location for bin_window X coordinate
10476 * @by: return location for bin_window Y coordinate
10477 *
10478 * Converts widget coordinates to coordinates for the bin_window
10479 * (see pspp_sheet_view_get_bin_window()).
10480 *
10481 * Since: 2.12
10482 **/
10483 void
10484 pspp_sheet_view_convert_widget_to_bin_window_coords (PsppSheetView *tree_view,
10485 gint wx,
10486 gint wy,
10487 gint *bx,
10488 gint *by)
10489 {
10490 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10491
10492 if (bx)
10493 *bx = wx + tree_view->priv->hadjustment->value;
10494 if (by)
10495 *by = wy - TREE_VIEW_HEADER_HEIGHT (tree_view);
10496 }
10497
10498 /**
10499 * pspp_sheet_view_convert_bin_window_to_widget_coords:
10500 * @tree_view: a #PsppSheetView
10501 * @bx: bin_window X coordinate
10502 * @by: bin_window Y coordinate
10503 * @wx: return location for widget X coordinate
10504 * @wy: return location for widget Y coordinate
10505 *
10506 * Converts bin_window coordinates (see pspp_sheet_view_get_bin_window())
10507 * to widget relative coordinates.
10508 *
10509 * Since: 2.12
10510 **/
10511 void
10512 pspp_sheet_view_convert_bin_window_to_widget_coords (PsppSheetView *tree_view,
10513 gint bx,
10514 gint by,
10515 gint *wx,
10516 gint *wy)
10517 {
10518 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10519
10520 if (wx)
10521 *wx = bx - tree_view->priv->hadjustment->value;
10522 if (wy)
10523 *wy = by + TREE_VIEW_HEADER_HEIGHT (tree_view);
10524 }
10525
10526 /**
10527 * pspp_sheet_view_convert_tree_to_bin_window_coords:
10528 * @tree_view: a #PsppSheetView
10529 * @tx: tree X coordinate
10530 * @ty: tree Y coordinate
10531 * @bx: return location for X coordinate relative to bin_window
10532 * @by: return location for Y coordinate relative to bin_window
10533 *
10534 * Converts tree coordinates (coordinates in full scrollable area of the tree)
10535 * to bin_window coordinates.
10536 *
10537 * Since: 2.12
10538 **/
10539 void
10540 pspp_sheet_view_convert_tree_to_bin_window_coords (PsppSheetView *tree_view,
10541 gint tx,
10542 gint ty,
10543 gint *bx,
10544 gint *by)
10545 {
10546 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10547
10548 if (bx)
10549 *bx = tx;
10550 if (by)
10551 *by = ty - tree_view->priv->dy;
10552 }
10553
10554 /**
10555 * pspp_sheet_view_convert_bin_window_to_tree_coords:
10556 * @tree_view: a #PsppSheetView
10557 * @bx: X coordinate relative to bin_window
10558 * @by: Y coordinate relative to bin_window
10559 * @tx: return location for tree X coordinate
10560 * @ty: return location for tree Y coordinate
10561 *
10562 * Converts bin_window coordinates to coordinates for the
10563 * tree (the full scrollable area of the tree).
10564 *
10565 * Since: 2.12
10566 **/
10567 void
10568 pspp_sheet_view_convert_bin_window_to_tree_coords (PsppSheetView *tree_view,
10569 gint bx,
10570 gint by,
10571 gint *tx,
10572 gint *ty)
10573 {
10574 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10575
10576 if (tx)
10577 *tx = bx;
10578 if (ty)
10579 *ty = by + tree_view->priv->dy;
10580 }
10581
10582
10583
10584 /**
10585 * pspp_sheet_view_get_visible_range:
10586 * @tree_view: A #PsppSheetView
10587 * @start_path: (allow-none): Return location for start of region, or %NULL.
10588 * @end_path: (allow-none): Return location for end of region, or %NULL.
10589 *
10590 * Sets @start_path and @end_path to be the first and last visible path.
10591 * Note that there may be invisible paths in between.
10592 *
10593 * The paths should be freed with gtk_tree_path_free() after use.
10594 *
10595 * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
10596 *
10597 * Since: 2.8
10598 **/
10599 gboolean
10600 pspp_sheet_view_get_visible_range (PsppSheetView *tree_view,
10601 GtkTreePath **start_path,
10602 GtkTreePath **end_path)
10603 {
10604 int node;
10605 gboolean retval;
10606
10607 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
10608
10609 if (!tree_view->priv->row_count)
10610 return FALSE;
10611
10612 retval = TRUE;
10613
10614 if (start_path)
10615 {
10616 pspp_sheet_view_find_offset (tree_view,
10617 TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
10618 &node);
10619 if (node >= 0)
10620 *start_path = _pspp_sheet_view_find_path (tree_view, node);
10621 else
10622 retval = FALSE;
10623 }
10624
10625 if (end_path)
10626 {
10627 gint y;
10628
10629 if (tree_view->priv->height < tree_view->priv->vadjustment->page_size)
10630 y = tree_view->priv->height - 1;
10631 else
10632 y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, tree_view->priv->vadjustment->page_size) - 1;
10633
10634 pspp_sheet_view_find_offset (tree_view, y, &node);
10635 if (node >= 0)
10636 *end_path = _pspp_sheet_view_find_path (tree_view, node);
10637 else
10638 retval = FALSE;
10639 }
10640
10641 return retval;
10642 }
10643
10644 static void
10645 unset_reorderable (PsppSheetView *tree_view)
10646 {
10647 if (tree_view->priv->reorderable)
10648 {
10649 tree_view->priv->reorderable = FALSE;
10650 g_object_notify (G_OBJECT (tree_view), "reorderable");
10651 }
10652 }
10653
10654 /**
10655 * pspp_sheet_view_enable_model_drag_source:
10656 * @tree_view: a #PsppSheetView
10657 * @start_button_mask: Mask of allowed buttons to start drag
10658 * @targets: the table of targets that the drag will support
10659 * @n_targets: the number of items in @targets
10660 * @actions: the bitmask of possible actions for a drag from this
10661 * widget
10662 *
10663 * Turns @tree_view into a drag source for automatic DND. Calling this
10664 * method sets #PsppSheetView:reorderable to %FALSE.
10665 **/
10666 void
10667 pspp_sheet_view_enable_model_drag_source (PsppSheetView *tree_view,
10668 GdkModifierType start_button_mask,
10669 const GtkTargetEntry *targets,
10670 gint n_targets,
10671 GdkDragAction actions)
10672 {
10673 TreeViewDragInfo *di;
10674
10675 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10676
10677 gtk_drag_source_set (GTK_WIDGET (tree_view),
10678 0,
10679 targets,
10680 n_targets,
10681 actions);
10682
10683 di = ensure_info (tree_view);
10684
10685 di->start_button_mask = start_button_mask;
10686 di->source_actions = actions;
10687 di->source_set = TRUE;
10688
10689 unset_reorderable (tree_view);
10690 }
10691
10692 /**
10693 * pspp_sheet_view_enable_model_drag_dest:
10694 * @tree_view: a #PsppSheetView
10695 * @targets: the table of targets that the drag will support
10696 * @n_targets: the number of items in @targets
10697 * @actions: the bitmask of possible actions for a drag from this
10698 * widget
10699 *
10700 * Turns @tree_view into a drop destination for automatic DND. Calling
10701 * this method sets #PsppSheetView:reorderable to %FALSE.
10702 **/
10703 void
10704 pspp_sheet_view_enable_model_drag_dest (PsppSheetView *tree_view,
10705 const GtkTargetEntry *targets,
10706 gint n_targets,
10707 GdkDragAction actions)
10708 {
10709 TreeViewDragInfo *di;
10710
10711 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10712
10713 gtk_drag_dest_set (GTK_WIDGET (tree_view),
10714 0,
10715 targets,
10716 n_targets,
10717 actions);
10718
10719 di = ensure_info (tree_view);
10720 di->dest_set = TRUE;
10721
10722 unset_reorderable (tree_view);
10723 }
10724
10725 /**
10726 * pspp_sheet_view_unset_rows_drag_source:
10727 * @tree_view: a #PsppSheetView
10728 *
10729 * Undoes the effect of
10730 * pspp_sheet_view_enable_model_drag_source(). Calling this method sets
10731 * #PsppSheetView:reorderable to %FALSE.
10732 **/
10733 void
10734 pspp_sheet_view_unset_rows_drag_source (PsppSheetView *tree_view)
10735 {
10736 TreeViewDragInfo *di;
10737
10738 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10739
10740 di = get_info (tree_view);
10741
10742 if (di)
10743 {
10744 if (di->source_set)
10745 {
10746 gtk_drag_source_unset (GTK_WIDGET (tree_view));
10747 di->source_set = FALSE;
10748 }
10749
10750 if (!di->dest_set && !di->source_set)
10751 remove_info (tree_view);
10752 }
10753
10754 unset_reorderable (tree_view);
10755 }
10756
10757 /**
10758 * pspp_sheet_view_unset_rows_drag_dest:
10759 * @tree_view: a #PsppSheetView
10760 *
10761 * Undoes the effect of
10762 * pspp_sheet_view_enable_model_drag_dest(). Calling this method sets
10763 * #PsppSheetView:reorderable to %FALSE.
10764 **/
10765 void
10766 pspp_sheet_view_unset_rows_drag_dest (PsppSheetView *tree_view)
10767 {
10768 TreeViewDragInfo *di;
10769
10770 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10771
10772 di = get_info (tree_view);
10773
10774 if (di)
10775 {
10776 if (di->dest_set)
10777 {
10778 gtk_drag_dest_unset (GTK_WIDGET (tree_view));
10779 di->dest_set = FALSE;
10780 }
10781
10782 if (!di->dest_set && !di->source_set)
10783 remove_info (tree_view);
10784 }
10785
10786 unset_reorderable (tree_view);
10787 }
10788
10789 /**
10790 * pspp_sheet_view_set_drag_dest_row:
10791 * @tree_view: a #PsppSheetView
10792 * @path: (allow-none): The path of the row to highlight, or %NULL.
10793 * @pos: Specifies whether to drop before, after or into the row
10794 *
10795 * Sets the row that is highlighted for feedback.
10796 **/
10797 void
10798 pspp_sheet_view_set_drag_dest_row (PsppSheetView *tree_view,
10799 GtkTreePath *path,
10800 PsppSheetViewDropPosition pos)
10801 {
10802 GtkTreePath *current_dest;
10803
10804 /* Note; this function is exported to allow a custom DND
10805 * implementation, so it can't touch TreeViewDragInfo
10806 */
10807
10808 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10809
10810 current_dest = NULL;
10811
10812 if (tree_view->priv->drag_dest_row)
10813 {
10814 current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
10815 gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
10816 }
10817
10818 /* special case a drop on an empty model */
10819 tree_view->priv->empty_view_drop = 0;
10820
10821 if (pos == PSPP_SHEET_VIEW_DROP_BEFORE && path
10822 && gtk_tree_path_get_depth (path) == 1
10823 && gtk_tree_path_get_indices (path)[0] == 0)
10824 {
10825 gint n_children;
10826
10827 n_children = gtk_tree_model_iter_n_children (tree_view->priv->model,
10828 NULL);
10829
10830 if (!n_children)
10831 tree_view->priv->empty_view_drop = 1;
10832 }
10833
10834 tree_view->priv->drag_dest_pos = pos;
10835
10836 if (path)
10837 {
10838 tree_view->priv->drag_dest_row =
10839 gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
10840 pspp_sheet_view_queue_draw_path (tree_view, path, NULL);
10841 }
10842 else
10843 tree_view->priv->drag_dest_row = NULL;
10844
10845 if (current_dest)
10846 {
10847 int node, new_node;
10848
10849 _pspp_sheet_view_find_node (tree_view, current_dest, &node);
10850 _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
10851
10852 if (node >= 0)
10853 {
10854 new_node = pspp_sheet_view_node_next (tree_view, node);
10855 if (new_node >= 0)
10856 _pspp_sheet_view_queue_draw_node (tree_view, new_node, NULL);
10857
10858 new_node = pspp_sheet_view_node_prev (tree_view, node);
10859 if (new_node >= 0)
10860 _pspp_sheet_view_queue_draw_node (tree_view, new_node, NULL);
10861 }
10862 gtk_tree_path_free (current_dest);
10863 }
10864 }
10865
10866 /**
10867 * pspp_sheet_view_get_drag_dest_row:
10868 * @tree_view: a #PsppSheetView
10869 * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
10870 * @pos: (allow-none): Return location for the drop position, or %NULL
10871 *
10872 * Gets information about the row that is highlighted for feedback.
10873 **/
10874 void
10875 pspp_sheet_view_get_drag_dest_row (PsppSheetView *tree_view,
10876 GtkTreePath **path,
10877 PsppSheetViewDropPosition *pos)
10878 {
10879 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
10880
10881 if (path)
10882 {
10883 if (tree_view->priv->drag_dest_row)
10884 *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
10885 else
10886 {
10887 if (tree_view->priv->empty_view_drop)
10888 *path = gtk_tree_path_new_from_indices (0, -1);
10889 else
10890 *path = NULL;
10891 }
10892 }
10893
10894 if (pos)
10895 *pos = tree_view->priv->drag_dest_pos;
10896 }
10897
10898 /**
10899 * pspp_sheet_view_get_dest_row_at_pos:
10900 * @tree_view: a #PsppSheetView
10901 * @drag_x: the position to determine the destination row for
10902 * @drag_y: the position to determine the destination row for
10903 * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
10904 * @pos: (allow-none): Return location for the drop position, or %NULL
10905 *
10906 * Determines the destination row for a given position. @drag_x and
10907 * @drag_y are expected to be in widget coordinates. This function is only
10908 * meaningful if @tree_view is realized. Therefore this function will always
10909 * return %FALSE if @tree_view is not realized or does not have a model.
10910 *
10911 * Return value: whether there is a row at the given position, %TRUE if this
10912 * is indeed the case.
10913 **/
10914 gboolean
10915 pspp_sheet_view_get_dest_row_at_pos (PsppSheetView *tree_view,
10916 gint drag_x,
10917 gint drag_y,
10918 GtkTreePath **path,
10919 PsppSheetViewDropPosition *pos)
10920 {
10921 gint cell_y;
10922 gint bin_x, bin_y;
10923 gdouble offset_into_row;
10924 gdouble third;
10925 GdkRectangle cell;
10926 PsppSheetViewColumn *column = NULL;
10927 GtkTreePath *tmp_path = NULL;
10928
10929 /* Note; this function is exported to allow a custom DND
10930 * implementation, so it can't touch TreeViewDragInfo
10931 */
10932
10933 g_return_val_if_fail (tree_view != NULL, FALSE);
10934 g_return_val_if_fail (drag_x >= 0, FALSE);
10935 g_return_val_if_fail (drag_y >= 0, FALSE);
10936
10937 if (path)
10938 *path = NULL;
10939
10940 if (tree_view->priv->bin_window == NULL)
10941 return FALSE;
10942
10943 if (tree_view->priv->row_count == 0)
10944 return FALSE;
10945
10946 /* If in the top third of a row, we drop before that row; if
10947 * in the bottom third, drop after that row; if in the middle,
10948 * and the row has children, drop into the row.
10949 */
10950 pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view, drag_x, drag_y,
10951 &bin_x, &bin_y);
10952
10953 if (!pspp_sheet_view_get_path_at_pos (tree_view,
10954 bin_x,
10955 bin_y,
10956 &tmp_path,
10957 &column,
10958 NULL,
10959 &cell_y))
10960 return FALSE;
10961
10962 pspp_sheet_view_get_background_area (tree_view, tmp_path, column,
10963 &cell);
10964
10965 offset_into_row = cell_y;
10966
10967 if (path)
10968 *path = tmp_path;
10969 else
10970 gtk_tree_path_free (tmp_path);
10971
10972 tmp_path = NULL;
10973
10974 third = cell.height / 3.0;
10975
10976 if (pos)
10977 {
10978 if (offset_into_row < third)
10979 {
10980 *pos = PSPP_SHEET_VIEW_DROP_BEFORE;
10981 }
10982 else if (offset_into_row < (cell.height / 2.0))
10983 {
10984 *pos = PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE;
10985 }
10986 else if (offset_into_row < third * 2.0)
10987 {
10988 *pos = PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER;
10989 }
10990 else
10991 {
10992 *pos = PSPP_SHEET_VIEW_DROP_AFTER;
10993 }
10994 }
10995
10996 return TRUE;
10997 }
10998
10999
11000
11001 /* KEEP IN SYNC WITH PSPP_SHEET_VIEW_BIN_EXPOSE */
11002 /**
11003 * pspp_sheet_view_create_row_drag_icon:
11004 * @tree_view: a #PsppSheetView
11005 * @path: a #GtkTreePath in @tree_view
11006 *
11007 * Creates a #GdkPixmap representation of the row at @path.
11008 * This image is used for a drag icon.
11009 *
11010 * Return value: a newly-allocated pixmap of the drag icon.
11011 **/
11012 GdkPixmap *
11013 pspp_sheet_view_create_row_drag_icon (PsppSheetView *tree_view,
11014 GtkTreePath *path)
11015 {
11016 GtkTreeIter iter;
11017 int node;
11018 gint cell_offset;
11019 GList *list;
11020 GdkRectangle background_area;
11021 GdkRectangle expose_area;
11022 GtkWidget *widget;
11023 gint depth;
11024 /* start drawing inside the black outline */
11025 gint x = 1, y = 1;
11026 GdkDrawable *drawable;
11027 gint bin_window_width;
11028 gboolean rtl;
11029
11030 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
11031 g_return_val_if_fail (path != NULL, NULL);
11032
11033 widget = GTK_WIDGET (tree_view);
11034
11035 if (!gtk_widget_get_realized (widget))
11036 return NULL;
11037
11038 depth = gtk_tree_path_get_depth (path);
11039
11040 _pspp_sheet_view_find_node (tree_view,
11041 path,
11042 &node);
11043
11044 if (node < 0)
11045 return NULL;
11046
11047 if (!gtk_tree_model_get_iter (tree_view->priv->model,
11048 &iter,
11049 path))
11050 return NULL;
11051
11052 cell_offset = x;
11053
11054 background_area.y = y;
11055 background_area.height = ROW_HEIGHT (tree_view);
11056
11057 gdk_drawable_get_size (tree_view->priv->bin_window,
11058 &bin_window_width, NULL);
11059
11060 drawable = gdk_pixmap_new (tree_view->priv->bin_window,
11061 bin_window_width + 2,
11062 background_area.height + 2,
11063 -1);
11064
11065 expose_area.x = 0;
11066 expose_area.y = 0;
11067 expose_area.width = bin_window_width + 2;
11068 expose_area.height = background_area.height + 2;
11069
11070 gdk_draw_rectangle (drawable,
11071 widget->style->base_gc [gtk_widget_get_state (widget)],
11072 TRUE,
11073 0, 0,
11074 bin_window_width + 2,
11075 background_area.height + 2);
11076
11077 rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
11078
11079 for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
11080 list;
11081 list = (rtl ? list->prev : list->next))
11082 {
11083 PsppSheetViewColumn *column = list->data;
11084 GdkRectangle cell_area;
11085 gint vertical_separator;
11086
11087 if (!column->visible)
11088 continue;
11089
11090 pspp_sheet_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter);
11091
11092 background_area.x = cell_offset;
11093 background_area.width = column->width;
11094
11095 gtk_widget_style_get (widget,
11096 "vertical-separator", &vertical_separator,
11097 NULL);
11098
11099 cell_area = background_area;
11100
11101 cell_area.y += vertical_separator / 2;
11102 cell_area.height -= vertical_separator;
11103
11104 if (pspp_sheet_view_column_cell_is_visible (column))
11105 _pspp_sheet_view_column_cell_render (column,
11106 drawable,
11107 &background_area,
11108 &cell_area,
11109 &expose_area,
11110 0);
11111 cell_offset += column->width;
11112 }
11113
11114 gdk_draw_rectangle (drawable,
11115 widget->style->black_gc,
11116 FALSE,
11117 0, 0,
11118 bin_window_width + 1,
11119 background_area.height + 1);
11120
11121 return drawable;
11122 }
11123
11124
11125 /**
11126 * pspp_sheet_view_set_destroy_count_func:
11127 * @tree_view: A #PsppSheetView
11128 * @func: (allow-none): Function to be called when a view row is destroyed, or %NULL
11129 * @data: (allow-none): User data to be passed to @func, or %NULL
11130 * @destroy: (allow-none): Destroy notifier for @data, or %NULL
11131 *
11132 * This function should almost never be used. It is meant for private use by
11133 * ATK for determining the number of visible children that are removed when a row is deleted.
11134 **/
11135 void
11136 pspp_sheet_view_set_destroy_count_func (PsppSheetView *tree_view,
11137 PsppSheetDestroyCountFunc func,
11138 gpointer data,
11139 GDestroyNotify destroy)
11140 {
11141 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11142
11143 if (tree_view->priv->destroy_count_destroy)
11144 tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
11145
11146 tree_view->priv->destroy_count_func = func;
11147 tree_view->priv->destroy_count_data = data;
11148 tree_view->priv->destroy_count_destroy = destroy;
11149 }
11150
11151
11152 /*
11153 * Interactive search
11154 */
11155
11156 /**
11157 * pspp_sheet_view_set_enable_search:
11158 * @tree_view: A #PsppSheetView
11159 * @enable_search: %TRUE, if the user can search interactively
11160 *
11161 * If @enable_search is set, then the user can type in text to search through
11162 * the tree interactively (this is sometimes called "typeahead find").
11163 *
11164 * Note that even if this is %FALSE, the user can still initiate a search
11165 * using the "start-interactive-search" key binding.
11166 */
11167 void
11168 pspp_sheet_view_set_enable_search (PsppSheetView *tree_view,
11169 gboolean enable_search)
11170 {
11171 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11172
11173 enable_search = !!enable_search;
11174
11175 if (tree_view->priv->enable_search != enable_search)
11176 {
11177 tree_view->priv->enable_search = enable_search;
11178 g_object_notify (G_OBJECT (tree_view), "enable-search");
11179 }
11180 }
11181
11182 /**
11183 * pspp_sheet_view_get_enable_search:
11184 * @tree_view: A #PsppSheetView
11185 *
11186 * Returns whether or not the tree allows to start interactive searching
11187 * by typing in text.
11188 *
11189 * Return value: whether or not to let the user search interactively
11190 */
11191 gboolean
11192 pspp_sheet_view_get_enable_search (PsppSheetView *tree_view)
11193 {
11194 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
11195
11196 return tree_view->priv->enable_search;
11197 }
11198
11199
11200 /**
11201 * pspp_sheet_view_get_search_column:
11202 * @tree_view: A #PsppSheetView
11203 *
11204 * Gets the column searched on by the interactive search code.
11205 *
11206 * Return value: the column the interactive search code searches in.
11207 */
11208 gint
11209 pspp_sheet_view_get_search_column (PsppSheetView *tree_view)
11210 {
11211 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
11212
11213 return (tree_view->priv->search_column);
11214 }
11215
11216 /**
11217 * pspp_sheet_view_set_search_column:
11218 * @tree_view: A #PsppSheetView
11219 * @column: the column of the model to search in, or -1 to disable searching
11220 *
11221 * Sets @column as the column where the interactive search code should
11222 * search in for the current model.
11223 *
11224 * If the search column is set, users can use the "start-interactive-search"
11225 * key binding to bring up search popup. The enable-search property controls
11226 * whether simply typing text will also start an interactive search.
11227 *
11228 * Note that @column refers to a column of the current model. The search
11229 * column is reset to -1 when the model is changed.
11230 */
11231 void
11232 pspp_sheet_view_set_search_column (PsppSheetView *tree_view,
11233 gint column)
11234 {
11235 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11236 g_return_if_fail (column >= -1);
11237
11238 if (tree_view->priv->search_column == column)
11239 return;
11240
11241 tree_view->priv->search_column = column;
11242 g_object_notify (G_OBJECT (tree_view), "search-column");
11243 }
11244
11245 /**
11246 * pspp_sheet_view_get_search_equal_func:
11247 * @tree_view: A #PsppSheetView
11248 *
11249 * Returns the compare function currently in use.
11250 *
11251 * Return value: the currently used compare function for the search code.
11252 */
11253
11254 PsppSheetViewSearchEqualFunc
11255 pspp_sheet_view_get_search_equal_func (PsppSheetView *tree_view)
11256 {
11257 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
11258
11259 return tree_view->priv->search_equal_func;
11260 }
11261
11262 /**
11263 * pspp_sheet_view_set_search_equal_func:
11264 * @tree_view: A #PsppSheetView
11265 * @search_equal_func: the compare function to use during the search
11266 * @search_user_data: (allow-none): user data to pass to @search_equal_func, or %NULL
11267 * @search_destroy: (allow-none): Destroy notifier for @search_user_data, or %NULL
11268 *
11269 * Sets the compare function for the interactive search capabilities; note
11270 * that somewhat like strcmp() returning 0 for equality
11271 * #PsppSheetViewSearchEqualFunc returns %FALSE on matches.
11272 **/
11273 void
11274 pspp_sheet_view_set_search_equal_func (PsppSheetView *tree_view,
11275 PsppSheetViewSearchEqualFunc search_equal_func,
11276 gpointer search_user_data,
11277 GDestroyNotify search_destroy)
11278 {
11279 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11280 g_return_if_fail (search_equal_func != NULL);
11281
11282 if (tree_view->priv->search_destroy)
11283 tree_view->priv->search_destroy (tree_view->priv->search_user_data);
11284
11285 tree_view->priv->search_equal_func = search_equal_func;
11286 tree_view->priv->search_user_data = search_user_data;
11287 tree_view->priv->search_destroy = search_destroy;
11288 if (tree_view->priv->search_equal_func == NULL)
11289 tree_view->priv->search_equal_func = pspp_sheet_view_search_equal_func;
11290 }
11291
11292 /**
11293 * pspp_sheet_view_get_search_entry:
11294 * @tree_view: A #PsppSheetView
11295 *
11296 * Returns the #GtkEntry which is currently in use as interactive search
11297 * entry for @tree_view. In case the built-in entry is being used, %NULL
11298 * will be returned.
11299 *
11300 * Return value: the entry currently in use as search entry.
11301 *
11302 * Since: 2.10
11303 */
11304 GtkEntry *
11305 pspp_sheet_view_get_search_entry (PsppSheetView *tree_view)
11306 {
11307 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
11308
11309 if (tree_view->priv->search_custom_entry_set)
11310 return GTK_ENTRY (tree_view->priv->search_entry);
11311
11312 return NULL;
11313 }
11314
11315 /**
11316 * pspp_sheet_view_set_search_entry:
11317 * @tree_view: A #PsppSheetView
11318 * @entry: (allow-none): the entry the interactive search code of @tree_view should use or %NULL
11319 *
11320 * Sets the entry which the interactive search code will use for this
11321 * @tree_view. This is useful when you want to provide a search entry
11322 * in our interface at all time at a fixed position. Passing %NULL for
11323 * @entry will make the interactive search code use the built-in popup
11324 * entry again.
11325 *
11326 * Since: 2.10
11327 */
11328 void
11329 pspp_sheet_view_set_search_entry (PsppSheetView *tree_view,
11330 GtkEntry *entry)
11331 {
11332 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11333 g_return_if_fail (entry == NULL || GTK_IS_ENTRY (entry));
11334
11335 if (tree_view->priv->search_custom_entry_set)
11336 {
11337 if (tree_view->priv->search_entry_changed_id)
11338 {
11339 g_signal_handler_disconnect (tree_view->priv->search_entry,
11340 tree_view->priv->search_entry_changed_id);
11341 tree_view->priv->search_entry_changed_id = 0;
11342 }
11343 g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,
11344 G_CALLBACK (pspp_sheet_view_search_key_press_event),
11345 tree_view);
11346
11347 g_object_unref (tree_view->priv->search_entry);
11348 }
11349 else if (tree_view->priv->search_window)
11350 {
11351 gtk_widget_destroy (tree_view->priv->search_window);
11352
11353 tree_view->priv->search_window = NULL;
11354 }
11355
11356 if (entry)
11357 {
11358 tree_view->priv->search_entry = g_object_ref (entry);
11359 tree_view->priv->search_custom_entry_set = TRUE;
11360
11361 if (tree_view->priv->search_entry_changed_id == 0)
11362 {
11363 tree_view->priv->search_entry_changed_id =
11364 g_signal_connect (tree_view->priv->search_entry, "changed",
11365 G_CALLBACK (pspp_sheet_view_search_init),
11366 tree_view);
11367 }
11368
11369 g_signal_connect (tree_view->priv->search_entry, "key-press-event",
11370 G_CALLBACK (pspp_sheet_view_search_key_press_event),
11371 tree_view);
11372
11373 pspp_sheet_view_search_init (tree_view->priv->search_entry, tree_view);
11374 }
11375 else
11376 {
11377 tree_view->priv->search_entry = NULL;
11378 tree_view->priv->search_custom_entry_set = FALSE;
11379 }
11380 }
11381
11382 /**
11383 * pspp_sheet_view_set_search_position_func:
11384 * @tree_view: A #PsppSheetView
11385 * @func: (allow-none): the function to use to position the search dialog, or %NULL
11386 * to use the default search position function
11387 * @data: (allow-none): user data to pass to @func, or %NULL
11388 * @destroy: (allow-none): Destroy notifier for @data, or %NULL
11389 *
11390 * Sets the function to use when positioning the search dialog.
11391 *
11392 * Since: 2.10
11393 **/
11394 void
11395 pspp_sheet_view_set_search_position_func (PsppSheetView *tree_view,
11396 PsppSheetViewSearchPositionFunc func,
11397 gpointer user_data,
11398 GDestroyNotify destroy)
11399 {
11400 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11401
11402 if (tree_view->priv->search_position_destroy)
11403 tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
11404
11405 tree_view->priv->search_position_func = func;
11406 tree_view->priv->search_position_user_data = user_data;
11407 tree_view->priv->search_position_destroy = destroy;
11408 if (tree_view->priv->search_position_func == NULL)
11409 tree_view->priv->search_position_func = pspp_sheet_view_search_position_func;
11410 }
11411
11412 /**
11413 * pspp_sheet_view_get_search_position_func:
11414 * @tree_view: A #PsppSheetView
11415 *
11416 * Returns the positioning function currently in use.
11417 *
11418 * Return value: the currently used function for positioning the search dialog.
11419 *
11420 * Since: 2.10
11421 */
11422 PsppSheetViewSearchPositionFunc
11423 pspp_sheet_view_get_search_position_func (PsppSheetView *tree_view)
11424 {
11425 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
11426
11427 return tree_view->priv->search_position_func;
11428 }
11429
11430
11431 static void
11432 pspp_sheet_view_search_dialog_hide (GtkWidget *search_dialog,
11433 PsppSheetView *tree_view)
11434 {
11435 if (tree_view->priv->disable_popdown)
11436 return;
11437
11438 if (tree_view->priv->search_entry_changed_id)
11439 {
11440 g_signal_handler_disconnect (tree_view->priv->search_entry,
11441 tree_view->priv->search_entry_changed_id);
11442 tree_view->priv->search_entry_changed_id = 0;
11443 }
11444 if (tree_view->priv->typeselect_flush_timeout)
11445 {
11446 g_source_remove (tree_view->priv->typeselect_flush_timeout);
11447 tree_view->priv->typeselect_flush_timeout = 0;
11448 }
11449
11450 if (gtk_widget_get_visible (search_dialog))
11451 {
11452 /* send focus-in event */
11453 send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), FALSE);
11454 gtk_widget_hide (search_dialog);
11455 gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
11456 send_focus_change (GTK_WIDGET (tree_view), TRUE);
11457 }
11458 }
11459
11460 static void
11461 pspp_sheet_view_search_position_func (PsppSheetView *tree_view,
11462 GtkWidget *search_dialog,
11463 gpointer user_data)
11464 {
11465 gint x, y;
11466 gint tree_x, tree_y;
11467 gint tree_width, tree_height;
11468 GdkWindow *tree_window = GTK_WIDGET (tree_view)->window;
11469 GdkScreen *screen = gdk_drawable_get_screen (tree_window);
11470 GtkRequisition requisition;
11471 gint monitor_num;
11472 GdkRectangle monitor;
11473
11474 monitor_num = gdk_screen_get_monitor_at_window (screen, tree_window);
11475 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
11476
11477 gtk_widget_realize (search_dialog);
11478
11479 gdk_window_get_origin (tree_window, &tree_x, &tree_y);
11480 gdk_drawable_get_size (tree_window,
11481 &tree_width,
11482 &tree_height);
11483 gtk_widget_size_request (search_dialog, &requisition);
11484
11485 if (tree_x + tree_width > gdk_screen_get_width (screen))
11486 x = gdk_screen_get_width (screen) - requisition.width;
11487 else if (tree_x + tree_width - requisition.width < 0)
11488 x = 0;
11489 else
11490 x = tree_x + tree_width - requisition.width;
11491
11492 if (tree_y + tree_height + requisition.height > gdk_screen_get_height (screen))
11493 y = gdk_screen_get_height (screen) - requisition.height;
11494 else if (tree_y + tree_height < 0) /* isn't really possible ... */
11495 y = 0;
11496 else
11497 y = tree_y + tree_height;
11498
11499 gtk_window_move (GTK_WINDOW (search_dialog), x, y);
11500 }
11501
11502 static void
11503 pspp_sheet_view_search_disable_popdown (GtkEntry *entry,
11504 GtkMenu *menu,
11505 gpointer data)
11506 {
11507 PsppSheetView *tree_view = (PsppSheetView *)data;
11508
11509 tree_view->priv->disable_popdown = 1;
11510 g_signal_connect (menu, "hide",
11511 G_CALLBACK (pspp_sheet_view_search_enable_popdown), data);
11512 }
11513
11514 /* Because we're visible but offscreen, we just set a flag in the preedit
11515 * callback.
11516 */
11517 static void
11518 pspp_sheet_view_search_preedit_changed (GtkIMContext *im_context,
11519 PsppSheetView *tree_view)
11520 {
11521 tree_view->priv->imcontext_changed = 1;
11522 if (tree_view->priv->typeselect_flush_timeout)
11523 {
11524 g_source_remove (tree_view->priv->typeselect_flush_timeout);
11525 tree_view->priv->typeselect_flush_timeout =
11526 gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
11527 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
11528 tree_view);
11529 }
11530
11531 }
11532
11533 static void
11534 pspp_sheet_view_search_activate (GtkEntry *entry,
11535 PsppSheetView *tree_view)
11536 {
11537 GtkTreePath *path;
11538 int node;
11539
11540 pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window,
11541 tree_view);
11542
11543 /* If we have a row selected and it's the cursor row, we activate
11544 * the row XXX */
11545 if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
11546 {
11547 path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
11548
11549 _pspp_sheet_view_find_node (tree_view, path, &node);
11550
11551 if (node >= 0 && pspp_sheet_view_node_is_selected (tree_view, node))
11552 pspp_sheet_view_row_activated (tree_view, path, tree_view->priv->focus_column);
11553
11554 gtk_tree_path_free (path);
11555 }
11556 }
11557
11558 static gboolean
11559 pspp_sheet_view_real_search_enable_popdown (gpointer data)
11560 {
11561 PsppSheetView *tree_view = (PsppSheetView *)data;
11562
11563 tree_view->priv->disable_popdown = 0;
11564
11565 return FALSE;
11566 }
11567
11568 static void
11569 pspp_sheet_view_search_enable_popdown (GtkWidget *widget,
11570 gpointer data)
11571 {
11572 gdk_threads_add_timeout_full (G_PRIORITY_HIGH, 200, pspp_sheet_view_real_search_enable_popdown, g_object_ref (data), g_object_unref);
11573 }
11574
11575 static gboolean
11576 pspp_sheet_view_search_delete_event (GtkWidget *widget,
11577 GdkEventAny *event,
11578 PsppSheetView *tree_view)
11579 {
11580 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11581
11582 pspp_sheet_view_search_dialog_hide (widget, tree_view);
11583
11584 return TRUE;
11585 }
11586
11587 static gboolean
11588 pspp_sheet_view_search_button_press_event (GtkWidget *widget,
11589 GdkEventButton *event,
11590 PsppSheetView *tree_view)
11591 {
11592 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11593
11594 pspp_sheet_view_search_dialog_hide (widget, tree_view);
11595
11596 if (event->window == tree_view->priv->bin_window)
11597 pspp_sheet_view_button_press (GTK_WIDGET (tree_view), event);
11598
11599 return TRUE;
11600 }
11601
11602 static gboolean
11603 pspp_sheet_view_search_scroll_event (GtkWidget *widget,
11604 GdkEventScroll *event,
11605 PsppSheetView *tree_view)
11606 {
11607 gboolean retval = FALSE;
11608
11609 if (event->direction == GDK_SCROLL_UP)
11610 {
11611 pspp_sheet_view_search_move (widget, tree_view, TRUE);
11612 retval = TRUE;
11613 }
11614 else if (event->direction == GDK_SCROLL_DOWN)
11615 {
11616 pspp_sheet_view_search_move (widget, tree_view, FALSE);
11617 retval = TRUE;
11618 }
11619
11620 /* renew the flush timeout */
11621 if (retval && tree_view->priv->typeselect_flush_timeout
11622 && !tree_view->priv->search_custom_entry_set)
11623 {
11624 g_source_remove (tree_view->priv->typeselect_flush_timeout);
11625 tree_view->priv->typeselect_flush_timeout =
11626 gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
11627 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
11628 tree_view);
11629 }
11630
11631 return retval;
11632 }
11633
11634 static gboolean
11635 pspp_sheet_view_search_key_press_event (GtkWidget *widget,
11636 GdkEventKey *event,
11637 PsppSheetView *tree_view)
11638 {
11639 gboolean retval = FALSE;
11640
11641 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11642 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
11643
11644 /* close window and cancel the search */
11645 if (!tree_view->priv->search_custom_entry_set
11646 && (event->keyval == GDK_Escape ||
11647 event->keyval == GDK_Tab ||
11648 event->keyval == GDK_KP_Tab ||
11649 event->keyval == GDK_ISO_Left_Tab))
11650 {
11651 pspp_sheet_view_search_dialog_hide (widget, tree_view);
11652 return TRUE;
11653 }
11654
11655 /* select previous matching iter */
11656 if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
11657 {
11658 if (!pspp_sheet_view_search_move (widget, tree_view, TRUE))
11659 gtk_widget_error_bell (widget);
11660
11661 retval = TRUE;
11662 }
11663
11664 if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK))
11665 && (event->keyval == GDK_g || event->keyval == GDK_G))
11666 {
11667 if (!pspp_sheet_view_search_move (widget, tree_view, TRUE))
11668 gtk_widget_error_bell (widget);
11669
11670 retval = TRUE;
11671 }
11672
11673 /* select next matching iter */
11674 if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
11675 {
11676 if (!pspp_sheet_view_search_move (widget, tree_view, FALSE))
11677 gtk_widget_error_bell (widget);
11678
11679 retval = TRUE;
11680 }
11681
11682 if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == GTK_DEFAULT_ACCEL_MOD_MASK)
11683 && (event->keyval == GDK_g || event->keyval == GDK_G))
11684 {
11685 if (!pspp_sheet_view_search_move (widget, tree_view, FALSE))
11686 gtk_widget_error_bell (widget);
11687
11688 retval = TRUE;
11689 }
11690
11691 /* renew the flush timeout */
11692 if (retval && tree_view->priv->typeselect_flush_timeout
11693 && !tree_view->priv->search_custom_entry_set)
11694 {
11695 g_source_remove (tree_view->priv->typeselect_flush_timeout);
11696 tree_view->priv->typeselect_flush_timeout =
11697 gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
11698 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
11699 tree_view);
11700 }
11701
11702 return retval;
11703 }
11704
11705 /* this function returns FALSE if there is a search string but
11706 * nothing was found, and TRUE otherwise.
11707 */
11708 static gboolean
11709 pspp_sheet_view_search_move (GtkWidget *window,
11710 PsppSheetView *tree_view,
11711 gboolean up)
11712 {
11713 gboolean ret;
11714 gint len;
11715 gint count = 0;
11716 const gchar *text;
11717 GtkTreeIter iter;
11718 GtkTreeModel *model;
11719 PsppSheetSelection *selection;
11720
11721 text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
11722
11723 g_return_val_if_fail (text != NULL, FALSE);
11724
11725 len = strlen (text);
11726
11727 if (up && tree_view->priv->selected_iter == 1)
11728 return strlen (text) < 1;
11729
11730 len = strlen (text);
11731
11732 if (len < 1)
11733 return TRUE;
11734
11735 model = pspp_sheet_view_get_model (tree_view);
11736 selection = pspp_sheet_view_get_selection (tree_view);
11737
11738 /* search */
11739 pspp_sheet_selection_unselect_all (selection);
11740 if (!gtk_tree_model_get_iter_first (model, &iter))
11741 return TRUE;
11742
11743 ret = pspp_sheet_view_search_iter (model, selection, &iter, text,
11744 &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
11745
11746 if (ret)
11747 {
11748 /* found */
11749 tree_view->priv->selected_iter += up?(-1):(1);
11750 return TRUE;
11751 }
11752 else
11753 {
11754 /* return to old iter */
11755 count = 0;
11756 gtk_tree_model_get_iter_first (model, &iter);
11757 pspp_sheet_view_search_iter (model, selection,
11758 &iter, text,
11759 &count, tree_view->priv->selected_iter);
11760 return FALSE;
11761 }
11762 }
11763
11764 static gboolean
11765 pspp_sheet_view_search_equal_func (GtkTreeModel *model,
11766 gint column,
11767 const gchar *key,
11768 GtkTreeIter *iter,
11769 gpointer search_data)
11770 {
11771 gboolean retval = TRUE;
11772 const gchar *str;
11773 gchar *normalized_string;
11774 gchar *normalized_key;
11775 gchar *case_normalized_string = NULL;
11776 gchar *case_normalized_key = NULL;
11777 GValue value = {0,};
11778 GValue transformed = {0,};
11779
11780 gtk_tree_model_get_value (model, iter, column, &value);
11781
11782 g_value_init (&transformed, G_TYPE_STRING);
11783
11784 if (!g_value_transform (&value, &transformed))
11785 {
11786 g_value_unset (&value);
11787 return TRUE;
11788 }
11789
11790 g_value_unset (&value);
11791
11792 str = g_value_get_string (&transformed);
11793 if (!str)
11794 {
11795 g_value_unset (&transformed);
11796 return TRUE;
11797 }
11798
11799 normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
11800 normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
11801
11802 if (normalized_string && normalized_key)
11803 {
11804 case_normalized_string = g_utf8_casefold (normalized_string, -1);
11805 case_normalized_key = g_utf8_casefold (normalized_key, -1);
11806
11807 if (strncmp (case_normalized_key, case_normalized_string, strlen (case_normalized_key)) == 0)
11808 retval = FALSE;
11809 }
11810
11811 g_value_unset (&transformed);
11812 g_free (normalized_key);
11813 g_free (normalized_string);
11814 g_free (case_normalized_key);
11815 g_free (case_normalized_string);
11816
11817 return retval;
11818 }
11819
11820 static gboolean
11821 pspp_sheet_view_search_iter (GtkTreeModel *model,
11822 PsppSheetSelection *selection,
11823 GtkTreeIter *iter,
11824 const gchar *text,
11825 gint *count,
11826 gint n)
11827 {
11828 int node = -1;
11829 GtkTreePath *path;
11830
11831 PsppSheetView *tree_view = pspp_sheet_selection_get_tree_view (selection);
11832
11833 path = gtk_tree_model_get_path (model, iter);
11834 _pspp_sheet_view_find_node (tree_view, path, &node);
11835
11836 do
11837 {
11838 gboolean done = FALSE;
11839
11840 if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
11841 {
11842 (*count)++;
11843 if (*count == n)
11844 {
11845 pspp_sheet_view_scroll_to_cell (tree_view, path, NULL,
11846 TRUE, 0.5, 0.0);
11847 pspp_sheet_selection_select_iter (selection, iter);
11848 pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE);
11849
11850 if (path)
11851 gtk_tree_path_free (path);
11852
11853 return TRUE;
11854 }
11855 }
11856
11857
11858 do
11859 {
11860 node = pspp_sheet_view_node_next (tree_view, node);
11861
11862 if (node >= 0)
11863 {
11864 gboolean has_next;
11865
11866 has_next = gtk_tree_model_iter_next (model, iter);
11867
11868 done = TRUE;
11869 gtk_tree_path_next (path);
11870
11871 /* sanity check */
11872 TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
11873 }
11874 else
11875 {
11876 if (path)
11877 gtk_tree_path_free (path);
11878
11879 /* we've run out of tree, done with this func */
11880 return FALSE;
11881 }
11882 }
11883 while (!done);
11884 }
11885 while (1);
11886
11887 return FALSE;
11888 }
11889
11890 static void
11891 pspp_sheet_view_search_init (GtkWidget *entry,
11892 PsppSheetView *tree_view)
11893 {
11894 gint ret;
11895 gint count = 0;
11896 const gchar *text;
11897 GtkTreeIter iter;
11898 GtkTreeModel *model;
11899 PsppSheetSelection *selection;
11900
11901 g_return_if_fail (GTK_IS_ENTRY (entry));
11902 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
11903
11904 text = gtk_entry_get_text (GTK_ENTRY (entry));
11905
11906 model = pspp_sheet_view_get_model (tree_view);
11907 selection = pspp_sheet_view_get_selection (tree_view);
11908
11909 /* search */
11910 pspp_sheet_selection_unselect_all (selection);
11911 if (tree_view->priv->typeselect_flush_timeout
11912 && !tree_view->priv->search_custom_entry_set)
11913 {
11914 g_source_remove (tree_view->priv->typeselect_flush_timeout);
11915 tree_view->priv->typeselect_flush_timeout =
11916 gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
11917 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
11918 tree_view);
11919 }
11920
11921 if (*text == '\0')
11922 return;
11923
11924 if (!gtk_tree_model_get_iter_first (model, &iter))
11925 return;
11926
11927 ret = pspp_sheet_view_search_iter (model, selection,
11928 &iter, text,
11929 &count, 1);
11930
11931 if (ret)
11932 tree_view->priv->selected_iter = 1;
11933 }
11934
11935 static void
11936 pspp_sheet_view_remove_widget (GtkCellEditable *cell_editable,
11937 PsppSheetView *tree_view)
11938 {
11939 if (tree_view->priv->edited_column == NULL)
11940 return;
11941
11942 _pspp_sheet_view_column_stop_editing (tree_view->priv->edited_column);
11943 tree_view->priv->edited_column = NULL;
11944
11945 if (gtk_widget_has_focus (GTK_WIDGET (cell_editable)))
11946 gtk_widget_grab_focus (GTK_WIDGET (tree_view));
11947
11948 g_signal_handlers_disconnect_by_func (cell_editable,
11949 pspp_sheet_view_remove_widget,
11950 tree_view);
11951 g_signal_handlers_disconnect_by_func (cell_editable,
11952 pspp_sheet_view_editable_button_press_event,
11953 tree_view);
11954 g_signal_handlers_disconnect_by_func (cell_editable,
11955 pspp_sheet_view_editable_clicked,
11956 tree_view);
11957
11958 gtk_container_remove (GTK_CONTAINER (tree_view),
11959 GTK_WIDGET (cell_editable));
11960
11961 /* FIXME should only redraw a single node */
11962 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
11963 }
11964
11965 static gboolean
11966 pspp_sheet_view_start_editing (PsppSheetView *tree_view,
11967 GtkTreePath *cursor_path)
11968 {
11969 GtkTreeIter iter;
11970 GdkRectangle background_area;
11971 GdkRectangle cell_area;
11972 GtkCellEditable *editable_widget = NULL;
11973 gchar *path_string;
11974 guint flags = 0; /* can be 0, as the flags are primarily for rendering */
11975 gint retval = FALSE;
11976 int cursor_node;
11977
11978 g_assert (tree_view->priv->focus_column);
11979
11980 if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
11981 return FALSE;
11982
11983 _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
11984 if (cursor_node < 0)
11985 return FALSE;
11986
11987 path_string = gtk_tree_path_to_string (cursor_path);
11988 gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
11989
11990 pspp_sheet_view_column_cell_set_cell_data (tree_view->priv->focus_column,
11991 tree_view->priv->model,
11992 &iter);
11993 pspp_sheet_view_get_background_area (tree_view,
11994 cursor_path,
11995 tree_view->priv->focus_column,
11996 &background_area);
11997 pspp_sheet_view_get_cell_area (tree_view,
11998 cursor_path,
11999 tree_view->priv->focus_column,
12000 &cell_area);
12001
12002 if (_pspp_sheet_view_column_cell_event (tree_view->priv->focus_column,
12003 &editable_widget,
12004 NULL,
12005 path_string,
12006 &background_area,
12007 &cell_area,
12008 flags))
12009 {
12010 retval = TRUE;
12011 if (editable_widget != NULL)
12012 {
12013 gint left, right;
12014 GdkRectangle area;
12015 GtkCellRenderer *cell;
12016
12017 area = cell_area;
12018 cell = _pspp_sheet_view_column_get_edited_cell (tree_view->priv->focus_column);
12019
12020 _pspp_sheet_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
12021
12022 area.x += left;
12023 area.width -= right + left;
12024
12025 pspp_sheet_view_real_start_editing (tree_view,
12026 tree_view->priv->focus_column,
12027 cursor_path,
12028 editable_widget,
12029 &area,
12030 NULL,
12031 flags);
12032 }
12033
12034 }
12035 g_free (path_string);
12036 return retval;
12037 }
12038
12039 static gboolean
12040 pspp_sheet_view_editable_button_press_event (GtkWidget *widget,
12041 GdkEventButton *event,
12042 PsppSheetView *sheet_view)
12043 {
12044 gint node;
12045
12046 node = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
12047 "pspp-sheet-view-node"));
12048 return pspp_sheet_view_row_head_clicked (sheet_view,
12049 node,
12050 sheet_view->priv->edited_column,
12051 event);
12052 }
12053
12054 static void
12055 pspp_sheet_view_editable_clicked (GtkButton *button,
12056 PsppSheetView *sheet_view)
12057 {
12058 pspp_sheet_view_editable_button_press_event (GTK_WIDGET (button), NULL,
12059 sheet_view);
12060 }
12061
12062 static void
12063 pspp_sheet_view_real_start_editing (PsppSheetView *tree_view,
12064 PsppSheetViewColumn *column,
12065 GtkTreePath *path,
12066 GtkCellEditable *cell_editable,
12067 GdkRectangle *cell_area,
12068 GdkEvent *event,
12069 guint flags)
12070 {
12071 PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection);
12072 gint pre_val = tree_view->priv->vadjustment->value;
12073 GtkRequisition requisition;
12074
12075 tree_view->priv->edited_column = column;
12076 _pspp_sheet_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
12077
12078 pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE);
12079 cell_area->y += pre_val - (int)tree_view->priv->vadjustment->value;
12080
12081 pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
12082 pspp_sheet_selection_select_column (tree_view->priv->selection, column);
12083 tree_view->priv->anchor_column = column;
12084
12085 gtk_widget_size_request (GTK_WIDGET (cell_editable), &requisition);
12086
12087 PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
12088
12089 if (requisition.height < cell_area->height)
12090 {
12091 gint diff = cell_area->height - requisition.height;
12092 pspp_sheet_view_put (tree_view,
12093 GTK_WIDGET (cell_editable),
12094 cell_area->x, cell_area->y + diff/2,
12095 cell_area->width, requisition.height);
12096 }
12097 else
12098 {
12099 pspp_sheet_view_put (tree_view,
12100 GTK_WIDGET (cell_editable),
12101 cell_area->x, cell_area->y,
12102 cell_area->width, cell_area->height);
12103 }
12104
12105 gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
12106 (GdkEvent *)event);
12107
12108 gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
12109 g_signal_connect (cell_editable, "remove-widget",
12110 G_CALLBACK (pspp_sheet_view_remove_widget), tree_view);
12111 if (mode == PSPP_SHEET_SELECTION_RECTANGLE && column->row_head &&
12112 GTK_IS_BUTTON (cell_editable))
12113 {
12114 g_signal_connect (cell_editable, "button-press-event",
12115 G_CALLBACK (pspp_sheet_view_editable_button_press_event),
12116 tree_view);
12117 g_object_set_data (G_OBJECT (cell_editable), "pspp-sheet-view-node",
12118 GINT_TO_POINTER (gtk_tree_path_get_indices (path)[0]));
12119 g_signal_connect (cell_editable, "clicked",
12120 G_CALLBACK (pspp_sheet_view_editable_clicked),
12121 tree_view);
12122 }
12123 }
12124
12125 void
12126 pspp_sheet_view_stop_editing (PsppSheetView *tree_view,
12127 gboolean cancel_editing)
12128 {
12129 PsppSheetViewColumn *column;
12130 GtkCellRenderer *cell;
12131
12132 if (tree_view->priv->edited_column == NULL)
12133 return;
12134
12135 /*
12136 * This is very evil. We need to do this, because
12137 * gtk_cell_editable_editing_done may trigger pspp_sheet_view_row_changed
12138 * later on. If pspp_sheet_view_row_changed notices
12139 * tree_view->priv->edited_column != NULL, it'll call
12140 * pspp_sheet_view_stop_editing again. Bad things will happen then.
12141 *
12142 * Please read that again if you intend to modify anything here.
12143 */
12144
12145 column = tree_view->priv->edited_column;
12146 tree_view->priv->edited_column = NULL;
12147
12148 cell = _pspp_sheet_view_column_get_edited_cell (column);
12149 gtk_cell_renderer_stop_editing (cell, cancel_editing);
12150
12151 if (!cancel_editing)
12152 gtk_cell_editable_editing_done (column->editable_widget);
12153
12154 tree_view->priv->edited_column = column;
12155
12156 gtk_cell_editable_remove_widget (column->editable_widget);
12157 }
12158
12159
12160 /**
12161 * pspp_sheet_view_set_hover_selection:
12162 * @tree_view: a #PsppSheetView
12163 * @hover: %TRUE to enable hover selection mode
12164 *
12165 * Enables of disables the hover selection mode of @tree_view.
12166 * Hover selection makes the selected row follow the pointer.
12167 * Currently, this works only for the selection modes
12168 * %PSPP_SHEET_SELECTION_SINGLE and %PSPP_SHEET_SELECTION_BROWSE.
12169 *
12170 * Since: 2.6
12171 **/
12172 void
12173 pspp_sheet_view_set_hover_selection (PsppSheetView *tree_view,
12174 gboolean hover)
12175 {
12176 hover = hover != FALSE;
12177
12178 if (hover != tree_view->priv->hover_selection)
12179 {
12180 tree_view->priv->hover_selection = hover;
12181
12182 g_object_notify (G_OBJECT (tree_view), "hover-selection");
12183 }
12184 }
12185
12186 /**
12187 * pspp_sheet_view_get_hover_selection:
12188 * @tree_view: a #PsppSheetView
12189 *
12190 * Returns whether hover selection mode is turned on for @tree_view.
12191 *
12192 * Return value: %TRUE if @tree_view is in hover selection mode
12193 *
12194 * Since: 2.6
12195 **/
12196 gboolean
12197 pspp_sheet_view_get_hover_selection (PsppSheetView *tree_view)
12198 {
12199 return tree_view->priv->hover_selection;
12200 }
12201
12202 /**
12203 * pspp_sheet_view_set_rubber_banding:
12204 * @tree_view: a #PsppSheetView
12205 * @enable: %TRUE to enable rubber banding
12206 *
12207 * Enables or disables rubber banding in @tree_view. If the selection mode is
12208 * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE, rubber
12209 * banding will allow the user to select multiple rows by dragging the mouse.
12210 *
12211 * Since: 2.10
12212 **/
12213 void
12214 pspp_sheet_view_set_rubber_banding (PsppSheetView *tree_view,
12215 gboolean enable)
12216 {
12217 enable = enable != FALSE;
12218
12219 if (enable != tree_view->priv->rubber_banding_enable)
12220 {
12221 tree_view->priv->rubber_banding_enable = enable;
12222
12223 g_object_notify (G_OBJECT (tree_view), "rubber-banding");
12224 }
12225 }
12226
12227 /**
12228 * pspp_sheet_view_get_rubber_banding:
12229 * @tree_view: a #PsppSheetView
12230 *
12231 * Returns whether rubber banding is turned on for @tree_view. If the
12232 * selection mode is #PSPP_SHEET_SELECTION_MULTIPLE or
12233 * #PSPP_SHEET_SELECTION_RECTANGLE, rubber banding will allow the user to
12234 * select multiple rows by dragging the mouse.
12235 *
12236 * Return value: %TRUE if rubber banding in @tree_view is enabled.
12237 *
12238 * Since: 2.10
12239 **/
12240 gboolean
12241 pspp_sheet_view_get_rubber_banding (PsppSheetView *tree_view)
12242 {
12243 return tree_view->priv->rubber_banding_enable;
12244 }
12245
12246 /**
12247 * pspp_sheet_view_is_rubber_banding_active:
12248 * @tree_view: a #PsppSheetView
12249 *
12250 * Returns whether a rubber banding operation is currently being done
12251 * in @tree_view.
12252 *
12253 * Return value: %TRUE if a rubber banding operation is currently being
12254 * done in @tree_view.
12255 *
12256 * Since: 2.12
12257 **/
12258 gboolean
12259 pspp_sheet_view_is_rubber_banding_active (PsppSheetView *tree_view)
12260 {
12261 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
12262
12263 if (tree_view->priv->rubber_banding_enable
12264 && tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
12265 return TRUE;
12266
12267 return FALSE;
12268 }
12269
12270 static void
12271 pspp_sheet_view_grab_notify (GtkWidget *widget,
12272 gboolean was_grabbed)
12273 {
12274 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
12275
12276 tree_view->priv->in_grab = !was_grabbed;
12277
12278 if (!was_grabbed)
12279 {
12280 tree_view->priv->pressed_button = -1;
12281
12282 if (tree_view->priv->rubber_band_status)
12283 pspp_sheet_view_stop_rubber_band (tree_view);
12284 }
12285 }
12286
12287 static void
12288 pspp_sheet_view_state_changed (GtkWidget *widget,
12289 GtkStateType previous_state)
12290 {
12291 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
12292
12293 if (gtk_widget_get_realized (widget))
12294 {
12295 gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
12296 gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
12297 }
12298
12299 gtk_widget_queue_draw (widget);
12300 }
12301
12302 /**
12303 * pspp_sheet_view_get_grid_lines:
12304 * @tree_view: a #PsppSheetView
12305 *
12306 * Returns which grid lines are enabled in @tree_view.
12307 *
12308 * Return value: a #PsppSheetViewGridLines value indicating which grid lines
12309 * are enabled.
12310 *
12311 * Since: 2.10
12312 */
12313 PsppSheetViewGridLines
12314 pspp_sheet_view_get_grid_lines (PsppSheetView *tree_view)
12315 {
12316 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
12317
12318 return tree_view->priv->grid_lines;
12319 }
12320
12321 /**
12322 * pspp_sheet_view_set_grid_lines:
12323 * @tree_view: a #PsppSheetView
12324 * @grid_lines: a #PsppSheetViewGridLines value indicating which grid lines to
12325 * enable.
12326 *
12327 * Sets which grid lines to draw in @tree_view.
12328 *
12329 * Since: 2.10
12330 */
12331 void
12332 pspp_sheet_view_set_grid_lines (PsppSheetView *tree_view,
12333 PsppSheetViewGridLines grid_lines)
12334 {
12335 PsppSheetViewPrivate *priv;
12336 GtkWidget *widget;
12337 PsppSheetViewGridLines old_grid_lines;
12338
12339 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
12340
12341 priv = tree_view->priv;
12342 widget = GTK_WIDGET (tree_view);
12343
12344 old_grid_lines = priv->grid_lines;
12345 priv->grid_lines = grid_lines;
12346
12347 if (gtk_widget_get_realized (widget))
12348 {
12349 if (grid_lines == PSPP_SHEET_VIEW_GRID_LINES_NONE &&
12350 priv->grid_line_gc)
12351 {
12352 g_object_unref (priv->grid_line_gc);
12353 priv->grid_line_gc = NULL;
12354 }
12355
12356 if (grid_lines != PSPP_SHEET_VIEW_GRID_LINES_NONE &&
12357 !priv->grid_line_gc)
12358 {
12359 gint line_width;
12360
12361 gtk_widget_style_get (widget,
12362 "grid-line-width", &line_width,
12363 NULL);
12364
12365 priv->grid_line_gc = gdk_gc_new (widget->window);
12366 gdk_gc_copy (priv->grid_line_gc, widget->style->black_gc);
12367 }
12368 }
12369
12370 if (old_grid_lines != grid_lines)
12371 {
12372 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
12373
12374 g_object_notify (G_OBJECT (tree_view), "enable-grid-lines");
12375 }
12376 }
12377
12378 /**
12379 * pspp_sheet_view_get_special_cells:
12380 * @tree_view: a #PsppSheetView
12381 *
12382 * Returns which grid lines are enabled in @tree_view.
12383 *
12384 * Return value: a #PsppSheetViewSpecialCells value indicating whether rows in
12385 * the sheet view contain special cells.
12386 */
12387 PsppSheetViewSpecialCells
12388 pspp_sheet_view_get_special_cells (PsppSheetView *tree_view)
12389 {
12390 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
12391
12392 return tree_view->priv->special_cells;
12393 }
12394
12395 /**
12396 * pspp_sheet_view_set_special_cells:
12397 * @tree_view: a #PsppSheetView
12398 * @special_cells: a #PsppSheetViewSpecialCells value indicating whether rows in
12399 * the sheet view contain special cells.
12400 *
12401 * Sets whether rows in the sheet view contain special cells, controlling the
12402 * rendering of row selections.
12403 */
12404 void
12405 pspp_sheet_view_set_special_cells (PsppSheetView *tree_view,
12406 PsppSheetViewSpecialCells special_cells)
12407 {
12408 PsppSheetViewPrivate *priv;
12409 GtkWidget *widget;
12410
12411 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
12412
12413 priv = tree_view->priv;
12414 widget = GTK_WIDGET (tree_view);
12415
12416 if (priv->special_cells != special_cells)
12417 {
12418 priv->special_cells = special_cells;
12419 gtk_widget_queue_draw (GTK_WIDGET (tree_view));
12420 g_object_notify (G_OBJECT (tree_view), "special-cells");
12421 }
12422 }
12423
12424 int
12425 pspp_sheet_view_get_fixed_height (const PsppSheetView *tree_view)
12426 {
12427 /* XXX (re)calculate fixed_height if necessary */
12428 return tree_view->priv->fixed_height;
12429 }
12430
12431 void
12432 pspp_sheet_view_set_fixed_height (PsppSheetView *tree_view,
12433 int fixed_height)
12434 {
12435 g_return_if_fail (fixed_height > 0);
12436
12437 if (tree_view->priv->fixed_height != fixed_height)
12438 {
12439 tree_view->priv->fixed_height = fixed_height;
12440 g_object_notify (G_OBJECT (tree_view), "fixed-height");
12441 }
12442 if (!tree_view->priv->fixed_height_set)
12443 {
12444 tree_view->priv->fixed_height_set = TRUE;
12445 g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
12446 }
12447 }
12448
12449 /**
12450 * pspp_sheet_view_set_tooltip_row:
12451 * @tree_view: a #PsppSheetView
12452 * @tooltip: a #GtkTooltip
12453 * @path: a #GtkTreePath
12454 *
12455 * Sets the tip area of @tooltip to be the area covered by the row at @path.
12456 * See also pspp_sheet_view_set_tooltip_column() for a simpler alternative.
12457 * See also gtk_tooltip_set_tip_area().
12458 *
12459 * Since: 2.12
12460 */
12461 void
12462 pspp_sheet_view_set_tooltip_row (PsppSheetView *tree_view,
12463 GtkTooltip *tooltip,
12464 GtkTreePath *path)
12465 {
12466 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
12467 g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
12468
12469 pspp_sheet_view_set_tooltip_cell (tree_view, tooltip, path, NULL, NULL);
12470 }
12471
12472 /**
12473 * pspp_sheet_view_set_tooltip_cell:
12474 * @tree_view: a #PsppSheetView
12475 * @tooltip: a #GtkTooltip
12476 * @path: (allow-none): a #GtkTreePath or %NULL
12477 * @column: (allow-none): a #PsppSheetViewColumn or %NULL
12478 * @cell: (allow-none): a #GtkCellRenderer or %NULL
12479 *
12480 * Sets the tip area of @tooltip to the area @path, @column and @cell have
12481 * in common. For example if @path is %NULL and @column is set, the tip
12482 * area will be set to the full area covered by @column. See also
12483 * gtk_tooltip_set_tip_area().
12484 *
12485 * See also pspp_sheet_view_set_tooltip_column() for a simpler alternative.
12486 *
12487 * Since: 2.12
12488 */
12489 void
12490 pspp_sheet_view_set_tooltip_cell (PsppSheetView *tree_view,
12491 GtkTooltip *tooltip,
12492 GtkTreePath *path,
12493 PsppSheetViewColumn *column,
12494 GtkCellRenderer *cell)
12495 {
12496 GdkRectangle rect;
12497
12498 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
12499 g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
12500 g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
12501 g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
12502
12503 /* Determine x values. */
12504 if (column && cell)
12505 {
12506 GdkRectangle tmp;
12507 gint start, width;
12508
12509 pspp_sheet_view_get_cell_area (tree_view, path, column, &tmp);
12510 pspp_sheet_view_column_cell_get_position (column, cell, &start, &width);
12511
12512 pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
12513 tmp.x + start, 0,
12514 &rect.x, NULL);
12515 rect.width = width;
12516 }
12517 else if (column)
12518 {
12519 GdkRectangle tmp;
12520
12521 pspp_sheet_view_get_background_area (tree_view, NULL, column, &tmp);
12522 pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
12523 tmp.x, 0,
12524 &rect.x, NULL);
12525 rect.width = tmp.width;
12526 }
12527 else
12528 {
12529 rect.x = 0;
12530 rect.width = GTK_WIDGET (tree_view)->allocation.width;
12531 }
12532
12533 /* Determine y values. */
12534 if (path)
12535 {
12536 GdkRectangle tmp;
12537
12538 pspp_sheet_view_get_background_area (tree_view, path, NULL, &tmp);
12539 pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
12540 0, tmp.y,
12541 NULL, &rect.y);
12542 rect.height = tmp.height;
12543 }
12544 else
12545 {
12546 rect.y = 0;
12547 rect.height = tree_view->priv->vadjustment->page_size;
12548 }
12549
12550 gtk_tooltip_set_tip_area (tooltip, &rect);
12551 }
12552
12553 /**
12554 * pspp_sheet_view_get_tooltip_context:
12555 * @tree_view: a #PsppSheetView
12556 * @x: the x coordinate (relative to widget coordinates)
12557 * @y: the y coordinate (relative to widget coordinates)
12558 * @keyboard_tip: whether this is a keyboard tooltip or not
12559 * @model: (allow-none): a pointer to receive a #GtkTreeModel or %NULL
12560 * @path: (allow-none): a pointer to receive a #GtkTreePath or %NULL
12561 * @iter: (allow-none): a pointer to receive a #GtkTreeIter or %NULL
12562 *
12563 * This function is supposed to be used in a #GtkWidget::query-tooltip
12564 * signal handler for #PsppSheetView. The @x, @y and @keyboard_tip values
12565 * which are received in the signal handler, should be passed to this
12566 * function without modification.
12567 *
12568 * The return value indicates whether there is a tree view row at the given
12569 * coordinates (%TRUE) or not (%FALSE) for mouse tooltips. For keyboard
12570 * tooltips the row returned will be the cursor row. When %TRUE, then any of
12571 * @model, @path and @iter which have been provided will be set to point to
12572 * that row and the corresponding model. @x and @y will always be converted
12573 * to be relative to @tree_view's bin_window if @keyboard_tooltip is %FALSE.
12574 *
12575 * Return value: whether or not the given tooltip context points to a row.
12576 *
12577 * Since: 2.12
12578 */
12579 gboolean
12580 pspp_sheet_view_get_tooltip_context (PsppSheetView *tree_view,
12581 gint *x,
12582 gint *y,
12583 gboolean keyboard_tip,
12584 GtkTreeModel **model,
12585 GtkTreePath **path,
12586 GtkTreeIter *iter)
12587 {
12588 GtkTreePath *tmppath = NULL;
12589
12590 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
12591 g_return_val_if_fail (x != NULL, FALSE);
12592 g_return_val_if_fail (y != NULL, FALSE);
12593
12594 if (keyboard_tip)
12595 {
12596 pspp_sheet_view_get_cursor (tree_view, &tmppath, NULL);
12597
12598 if (!tmppath)
12599 return FALSE;
12600 }
12601 else
12602 {
12603 pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view, *x, *y,
12604 x, y);
12605
12606 if (!pspp_sheet_view_get_path_at_pos (tree_view, *x, *y,
12607 &tmppath, NULL, NULL, NULL))
12608 return FALSE;
12609 }
12610
12611 if (model)
12612 *model = pspp_sheet_view_get_model (tree_view);
12613
12614 if (iter)
12615 gtk_tree_model_get_iter (pspp_sheet_view_get_model (tree_view),
12616 iter, tmppath);
12617
12618 if (path)
12619 *path = tmppath;
12620 else
12621 gtk_tree_path_free (tmppath);
12622
12623 return TRUE;
12624 }
12625
12626 static gboolean
12627 pspp_sheet_view_set_tooltip_query_cb (GtkWidget *widget,
12628 gint x,
12629 gint y,
12630 gboolean keyboard_tip,
12631 GtkTooltip *tooltip,
12632 gpointer data)
12633 {
12634 GValue value = { 0, };
12635 GValue transformed = { 0, };
12636 GtkTreeIter iter;
12637 GtkTreePath *path;
12638 GtkTreeModel *model;
12639 PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
12640
12641 if (!pspp_sheet_view_get_tooltip_context (PSPP_SHEET_VIEW (widget),
12642 &x, &y,
12643 keyboard_tip,
12644 &model, &path, &iter))
12645 return FALSE;
12646
12647 gtk_tree_model_get_value (model, &iter,
12648 tree_view->priv->tooltip_column, &value);
12649
12650 g_value_init (&transformed, G_TYPE_STRING);
12651
12652 if (!g_value_transform (&value, &transformed))
12653 {
12654 g_value_unset (&value);
12655 gtk_tree_path_free (path);
12656
12657 return FALSE;
12658 }
12659
12660 g_value_unset (&value);
12661
12662 if (!g_value_get_string (&transformed))
12663 {
12664 g_value_unset (&transformed);
12665 gtk_tree_path_free (path);
12666
12667 return FALSE;
12668 }
12669
12670 gtk_tooltip_set_markup (tooltip, g_value_get_string (&transformed));
12671 pspp_sheet_view_set_tooltip_row (tree_view, tooltip, path);
12672
12673 gtk_tree_path_free (path);
12674 g_value_unset (&transformed);
12675
12676 return TRUE;
12677 }
12678
12679 /**
12680 * pspp_sheet_view_set_tooltip_column:
12681 * @tree_view: a #PsppSheetView
12682 * @column: an integer, which is a valid column number for @tree_view's model
12683 *
12684 * If you only plan to have simple (text-only) tooltips on full rows, you
12685 * can use this function to have #PsppSheetView handle these automatically
12686 * for you. @column should be set to the column in @tree_view's model
12687 * containing the tooltip texts, or -1 to disable this feature.
12688 *
12689 * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
12690 * @tree_view will connect a #GtkWidget::query-tooltip signal handler.
12691 *
12692 * Note that the signal handler sets the text with gtk_tooltip_set_markup(),
12693 * so &amp;, &lt;, etc have to be escaped in the text.
12694 *
12695 * Since: 2.12
12696 */
12697 void
12698 pspp_sheet_view_set_tooltip_column (PsppSheetView *tree_view,
12699 gint column)
12700 {
12701 g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
12702
12703 if (column == tree_view->priv->tooltip_column)
12704 return;
12705
12706 if (column == -1)
12707 {
12708 g_signal_handlers_disconnect_by_func (tree_view,
12709 pspp_sheet_view_set_tooltip_query_cb,
12710 NULL);
12711 gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), FALSE);
12712 }
12713 else
12714 {
12715 if (tree_view->priv->tooltip_column == -1)
12716 {
12717 g_signal_connect (tree_view, "query-tooltip",
12718 G_CALLBACK (pspp_sheet_view_set_tooltip_query_cb), NULL);
12719 gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), TRUE);
12720 }
12721 }
12722
12723 tree_view->priv->tooltip_column = column;
12724 g_object_notify (G_OBJECT (tree_view), "tooltip-column");
12725 }
12726
12727 /**
12728 * pspp_sheet_view_get_tooltip_column:
12729 * @tree_view: a #PsppSheetView
12730 *
12731 * Returns the column of @tree_view's model which is being used for
12732 * displaying tooltips on @tree_view's rows.
12733 *
12734 * Return value: the index of the tooltip column that is currently being
12735 * used, or -1 if this is disabled.
12736 *
12737 * Since: 2.12
12738 */
12739 gint
12740 pspp_sheet_view_get_tooltip_column (PsppSheetView *tree_view)
12741 {
12742 g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
12743
12744 return tree_view->priv->tooltip_column;
12745 }
12746
12747 gboolean
12748 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
12749 GValue *return_accu,
12750 const GValue *handler_return,
12751 gpointer dummy)
12752 {
12753 gboolean continue_emission;
12754 gboolean signal_handled;
12755
12756 signal_handled = g_value_get_boolean (handler_return);
12757 g_value_set_boolean (return_accu, signal_handled);
12758 continue_emission = !signal_handled;
12759
12760 return continue_emission;
12761 }
12762
12763 GType
12764 pspp_sheet_view_grid_lines_get_type (void)
12765 {
12766 static GType etype = 0;
12767 if (G_UNLIKELY(etype == 0)) {
12768 static const GEnumValue values[] = {
12769 { PSPP_SHEET_VIEW_GRID_LINES_NONE, "PSPP_SHEET_VIEW_GRID_LINES_NONE", "none" },
12770 { PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL, "PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL", "horizontal" },
12771 { PSPP_SHEET_VIEW_GRID_LINES_VERTICAL, "PSPP_SHEET_VIEW_GRID_LINES_VERTICAL", "vertical" },
12772 { PSPP_SHEET_VIEW_GRID_LINES_BOTH, "PSPP_SHEET_VIEW_GRID_LINES_BOTH", "both" },
12773 { 0, NULL, NULL }
12774 };
12775 etype = g_enum_register_static (g_intern_static_string ("PsppSheetViewGridLines"), values);
12776 }
12777 return etype;
12778 }
12779
12780 GType
12781 pspp_sheet_view_special_cells_get_type (void)
12782 {
12783 static GType etype = 0;
12784 if (G_UNLIKELY(etype == 0)) {
12785 static const GEnumValue values[] = {
12786 { PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT, "PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT", "detect" },
12787 { PSPP_SHEET_VIEW_SPECIAL_CELLS_YES, "PSPP_SHEET_VIEW_SPECIAL_CELLS_YES", "yes" },
12788 { PSPP_SHEET_VIEW_SPECIAL_CELLS_NO, "PSPP_SHEET_VIEW_SPECIAL_CELLS_NO", "no" },
12789 { 0, NULL, NULL }
12790 };
12791 etype = g_enum_register_static (g_intern_static_string ("PsppSheetViewSpecialCells"), values);
12792 }
12793 return etype;
12794 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* gtktreeview.h
17 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Library General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Library General Public License for more details.
28 *
29 * You should have received a copy of the GNU Library General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
32 * Boston, MA 02111-1307, USA.
33 */
34
35 #ifndef __PSPP_SHEET_VIEW_H__
36 #define __PSPP_SHEET_VIEW_H__
37
38 #include <gtk/gtk.h>
39 #include "ui/gui/pspp-sheet-view-column.h"
40
41 G_BEGIN_DECLS
42
43
44 typedef enum
45 {
46 PSPP_SHEET_VIEW_GRID_LINES_NONE,
47 PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL,
48 PSPP_SHEET_VIEW_GRID_LINES_VERTICAL,
49 PSPP_SHEET_VIEW_GRID_LINES_BOTH
50 } PsppSheetViewGridLines;
51
52 GType pspp_sheet_view_grid_lines_get_type (void) G_GNUC_CONST;
53 #define PSPP_TYPE_SHEET_VIEW_GRID_LINES (pspp_sheet_view_grid_lines_get_type ())
54
55 /* A "special cell" is a cell that is editable or activatable. When a row that
56 * contains a special cell is selected, the cursor is drawn around a single
57 * cell; when other rows are selected, the cursor is drawn around the entire
58 * row.
59 *
60 * With the default of "detect", whether a given row contains a special cell is
61 * detected automatically. This is the best choice most of the time. For
62 * sheet views that contain more than 100 columns, an explicit "yes" or "no"
63 * improves performance. */
64 typedef enum
65 {
66 PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT,
67 PSPP_SHEET_VIEW_SPECIAL_CELLS_YES,
68 PSPP_SHEET_VIEW_SPECIAL_CELLS_NO,
69 } PsppSheetViewSpecialCells;
70
71 GType pspp_sheet_view_special_cells_get_type (void) G_GNUC_CONST;
72 #define PSPP_TYPE_SHEET_VIEW_SPECIAL_CELLS (pspp_sheet_view_special_cells_get_type ())
73
74 typedef enum
75 {
76 /* drop before/after this row */
77 PSPP_SHEET_VIEW_DROP_BEFORE,
78 PSPP_SHEET_VIEW_DROP_AFTER,
79 /* drop as a child of this row (with fallback to before or after
80 * if into is not possible)
81 */
82 PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE,
83 PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER
84 } PsppSheetViewDropPosition;
85
86 #define PSPP_TYPE_SHEET_VIEW (pspp_sheet_view_get_type ())
87 #define PSPP_SHEET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_VIEW, PsppSheetView))
88 #define PSPP_SHEET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_VIEW, PsppSheetViewClass))
89 #define PSPP_IS_SHEET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_VIEW))
90 #define PSPP_IS_SHEET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_VIEW))
91 #define PSPP_SHEET_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_VIEW, PsppSheetViewClass))
92
93 typedef struct _PsppSheetView PsppSheetView;
94 typedef struct _PsppSheetViewClass PsppSheetViewClass;
95 typedef struct _PsppSheetViewPrivate PsppSheetViewPrivate;
96 typedef struct _PsppSheetSelection PsppSheetSelection;
97 typedef struct _PsppSheetSelectionClass PsppSheetSelectionClass;
98
99 struct _PsppSheetView
100 {
101 GtkContainer parent;
102
103 PsppSheetViewPrivate *GSEAL (priv);
104 };
105
106 struct _PsppSheetViewClass
107 {
108 GtkContainerClass parent_class;
109
110 void (* set_scroll_adjustments) (PsppSheetView *tree_view,
111 GtkAdjustment *hadjustment,
112 GtkAdjustment *vadjustment);
113 void (* row_activated) (PsppSheetView *tree_view,
114 GtkTreePath *path,
115 PsppSheetViewColumn *column);
116 void (* columns_changed) (PsppSheetView *tree_view);
117 void (* cursor_changed) (PsppSheetView *tree_view);
118
119 /* Key Binding signals */
120 gboolean (* move_cursor) (PsppSheetView *tree_view,
121 GtkMovementStep step,
122 gint count);
123 gboolean (* select_all) (PsppSheetView *tree_view);
124 gboolean (* unselect_all) (PsppSheetView *tree_view);
125 gboolean (* select_cursor_row) (PsppSheetView *tree_view,
126 gboolean start_editing);
127 gboolean (* toggle_cursor_row) (PsppSheetView *tree_view);
128 gboolean (* select_cursor_parent) (PsppSheetView *tree_view);
129 gboolean (* start_interactive_search) (PsppSheetView *tree_view);
130
131 /* Padding for future expansion */
132 void (*_gtk_reserved0) (void);
133 void (*_gtk_reserved1) (void);
134 void (*_gtk_reserved2) (void);
135 void (*_gtk_reserved3) (void);
136 void (*_gtk_reserved4) (void);
137 };
138
139
140 typedef gboolean (* PsppSheetViewColumnDropFunc) (PsppSheetView *tree_view,
141 PsppSheetViewColumn *column,
142 PsppSheetViewColumn *prev_column,
143 PsppSheetViewColumn *next_column,
144 gpointer data);
145 typedef void (* PsppSheetViewMappingFunc) (PsppSheetView *tree_view,
146 GtkTreePath *path,
147 gpointer user_data);
148 typedef gboolean (*PsppSheetViewSearchEqualFunc) (GtkTreeModel *model,
149 gint column,
150 const gchar *key,
151 GtkTreeIter *iter,
152 gpointer search_data);
153 typedef void (*PsppSheetViewSearchPositionFunc) (PsppSheetView *tree_view,
154 GtkWidget *search_dialog,
155 gpointer user_data);
156
157
158 /* Creators */
159 GType pspp_sheet_view_get_type (void) G_GNUC_CONST;
160 GtkWidget *pspp_sheet_view_new (void);
161 GtkWidget *pspp_sheet_view_new_with_model (GtkTreeModel *model);
162
163 /* Accessors */
164 GtkTreeModel *pspp_sheet_view_get_model (PsppSheetView *tree_view);
165 void pspp_sheet_view_set_model (PsppSheetView *tree_view,
166 GtkTreeModel *model);
167 PsppSheetSelection *pspp_sheet_view_get_selection (PsppSheetView *tree_view);
168 GtkAdjustment *pspp_sheet_view_get_hadjustment (PsppSheetView *tree_view);
169 void pspp_sheet_view_set_hadjustment (PsppSheetView *tree_view,
170 GtkAdjustment *adjustment);
171 GtkAdjustment *pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view);
172 void pspp_sheet_view_set_vadjustment (PsppSheetView *tree_view,
173 GtkAdjustment *adjustment);
174 gboolean pspp_sheet_view_get_headers_visible (PsppSheetView *tree_view);
175 void pspp_sheet_view_set_headers_visible (PsppSheetView *tree_view,
176 gboolean headers_visible);
177 void pspp_sheet_view_columns_autosize (PsppSheetView *tree_view);
178 gboolean pspp_sheet_view_get_headers_clickable (PsppSheetView *tree_view);
179 void pspp_sheet_view_set_headers_clickable (PsppSheetView *tree_view,
180 gboolean setting);
181 void pspp_sheet_view_set_rules_hint (PsppSheetView *tree_view,
182 gboolean setting);
183 gboolean pspp_sheet_view_get_rules_hint (PsppSheetView *tree_view);
184
185 /* Column funtions */
186 gint pspp_sheet_view_append_column (PsppSheetView *tree_view,
187 PsppSheetViewColumn *column);
188 gint pspp_sheet_view_remove_column (PsppSheetView *tree_view,
189 PsppSheetViewColumn *column);
190 gint pspp_sheet_view_insert_column (PsppSheetView *tree_view,
191 PsppSheetViewColumn *column,
192 gint position);
193 gint pspp_sheet_view_insert_column_with_attributes (PsppSheetView *tree_view,
194 gint position,
195 const gchar *title,
196 GtkCellRenderer *cell,
197 ...) G_GNUC_NULL_TERMINATED;
198 gint pspp_sheet_view_insert_column_with_data_func (PsppSheetView *tree_view,
199 gint position,
200 const gchar *title,
201 GtkCellRenderer *cell,
202 PsppSheetCellDataFunc func,
203 gpointer data,
204 GDestroyNotify dnotify);
205 PsppSheetViewColumn *pspp_sheet_view_get_column (PsppSheetView *tree_view,
206 gint n);
207 GList *pspp_sheet_view_get_columns (PsppSheetView *tree_view);
208 void pspp_sheet_view_move_column_after (PsppSheetView *tree_view,
209 PsppSheetViewColumn *column,
210 PsppSheetViewColumn *base_column);
211 void pspp_sheet_view_set_column_drag_function (PsppSheetView *tree_view,
212 PsppSheetViewColumnDropFunc func,
213 gpointer user_data,
214 GDestroyNotify destroy);
215
216 /* Actions */
217 void pspp_sheet_view_scroll_to_point (PsppSheetView *tree_view,
218 gint tree_x,
219 gint tree_y);
220 void pspp_sheet_view_scroll_to_cell (PsppSheetView *tree_view,
221 GtkTreePath *path,
222 PsppSheetViewColumn *column,
223 gboolean use_align,
224 gfloat row_align,
225 gfloat col_align);
226 void pspp_sheet_view_row_activated (PsppSheetView *tree_view,
227 GtkTreePath *path,
228 PsppSheetViewColumn *column);
229 void pspp_sheet_view_set_reorderable (PsppSheetView *tree_view,
230 gboolean reorderable);
231 gboolean pspp_sheet_view_get_reorderable (PsppSheetView *tree_view);
232 void pspp_sheet_view_set_cursor (PsppSheetView *tree_view,
233 GtkTreePath *path,
234 PsppSheetViewColumn *focus_column,
235 gboolean start_editing);
236 void pspp_sheet_view_set_cursor_on_cell (PsppSheetView *tree_view,
237 GtkTreePath *path,
238 PsppSheetViewColumn *focus_column,
239 GtkCellRenderer *focus_cell,
240 gboolean start_editing);
241 void pspp_sheet_view_get_cursor (PsppSheetView *tree_view,
242 GtkTreePath **path,
243 PsppSheetViewColumn **focus_column);
244
245
246 /* Layout information */
247 GdkWindow *pspp_sheet_view_get_bin_window (PsppSheetView *tree_view);
248 gboolean pspp_sheet_view_get_path_at_pos (PsppSheetView *tree_view,
249 gint x,
250 gint y,
251 GtkTreePath **path,
252 PsppSheetViewColumn **column,
253 gint *cell_x,
254 gint *cell_y);
255 void pspp_sheet_view_get_cell_area (PsppSheetView *tree_view,
256 GtkTreePath *path,
257 PsppSheetViewColumn *column,
258 GdkRectangle *rect);
259 void pspp_sheet_view_get_background_area (PsppSheetView *tree_view,
260 GtkTreePath *path,
261 PsppSheetViewColumn *column,
262 GdkRectangle *rect);
263 void pspp_sheet_view_get_visible_rect (PsppSheetView *tree_view,
264 GdkRectangle *visible_rect);
265
266 #ifndef GTK_DISABLE_DEPRECATED
267 void pspp_sheet_view_widget_to_tree_coords (PsppSheetView *tree_view,
268 gint wx,
269 gint wy,
270 gint *tx,
271 gint *ty);
272 void pspp_sheet_view_tree_to_widget_coords (PsppSheetView *tree_view,
273 gint tx,
274 gint ty,
275 gint *wx,
276 gint *wy);
277 #endif /* !GTK_DISABLE_DEPRECATED */
278 gboolean pspp_sheet_view_get_visible_range (PsppSheetView *tree_view,
279 GtkTreePath **start_path,
280 GtkTreePath **end_path);
281
282 /* Drag-and-Drop support */
283 void pspp_sheet_view_enable_model_drag_source (PsppSheetView *tree_view,
284 GdkModifierType start_button_mask,
285 const GtkTargetEntry *targets,
286 gint n_targets,
287 GdkDragAction actions);
288 void pspp_sheet_view_enable_model_drag_dest (PsppSheetView *tree_view,
289 const GtkTargetEntry *targets,
290 gint n_targets,
291 GdkDragAction actions);
292 void pspp_sheet_view_unset_rows_drag_source (PsppSheetView *tree_view);
293 void pspp_sheet_view_unset_rows_drag_dest (PsppSheetView *tree_view);
294
295
296 /* These are useful to implement your own custom stuff. */
297 void pspp_sheet_view_set_drag_dest_row (PsppSheetView *tree_view,
298 GtkTreePath *path,
299 PsppSheetViewDropPosition pos);
300 void pspp_sheet_view_get_drag_dest_row (PsppSheetView *tree_view,
301 GtkTreePath **path,
302 PsppSheetViewDropPosition *pos);
303 gboolean pspp_sheet_view_get_dest_row_at_pos (PsppSheetView *tree_view,
304 gint drag_x,
305 gint drag_y,
306 GtkTreePath **path,
307 PsppSheetViewDropPosition *pos);
308 GdkPixmap *pspp_sheet_view_create_row_drag_icon (PsppSheetView *tree_view,
309 GtkTreePath *path);
310
311 /* Interactive search */
312 void pspp_sheet_view_set_enable_search (PsppSheetView *tree_view,
313 gboolean enable_search);
314 gboolean pspp_sheet_view_get_enable_search (PsppSheetView *tree_view);
315 gint pspp_sheet_view_get_search_column (PsppSheetView *tree_view);
316 void pspp_sheet_view_set_search_column (PsppSheetView *tree_view,
317 gint column);
318 PsppSheetViewSearchEqualFunc pspp_sheet_view_get_search_equal_func (PsppSheetView *tree_view);
319 void pspp_sheet_view_set_search_equal_func (PsppSheetView *tree_view,
320 PsppSheetViewSearchEqualFunc search_equal_func,
321 gpointer search_user_data,
322 GDestroyNotify search_destroy);
323
324 GtkEntry *pspp_sheet_view_get_search_entry (PsppSheetView *tree_view);
325 void pspp_sheet_view_set_search_entry (PsppSheetView *tree_view,
326 GtkEntry *entry);
327 PsppSheetViewSearchPositionFunc pspp_sheet_view_get_search_position_func (PsppSheetView *tree_view);
328 void pspp_sheet_view_set_search_position_func (PsppSheetView *tree_view,
329 PsppSheetViewSearchPositionFunc func,
330 gpointer data,
331 GDestroyNotify destroy);
332
333 /* Convert between the different coordinate systems */
334 void pspp_sheet_view_convert_widget_to_tree_coords (PsppSheetView *tree_view,
335 gint wx,
336 gint wy,
337 gint *tx,
338 gint *ty);
339 void pspp_sheet_view_convert_tree_to_widget_coords (PsppSheetView *tree_view,
340 gint tx,
341 gint ty,
342 gint *wx,
343 gint *wy);
344 void pspp_sheet_view_convert_widget_to_bin_window_coords (PsppSheetView *tree_view,
345 gint wx,
346 gint wy,
347 gint *bx,
348 gint *by);
349 void pspp_sheet_view_convert_bin_window_to_widget_coords (PsppSheetView *tree_view,
350 gint bx,
351 gint by,
352 gint *wx,
353 gint *wy);
354 void pspp_sheet_view_convert_tree_to_bin_window_coords (PsppSheetView *tree_view,
355 gint tx,
356 gint ty,
357 gint *bx,
358 gint *by);
359 void pspp_sheet_view_convert_bin_window_to_tree_coords (PsppSheetView *tree_view,
360 gint bx,
361 gint by,
362 gint *tx,
363 gint *ty);
364
365 /* This function should really never be used. It is just for use by ATK.
366 */
367 typedef void (* PsppSheetDestroyCountFunc) (PsppSheetView *tree_view,
368 GtkTreePath *path,
369 gint children,
370 gpointer user_data);
371 void pspp_sheet_view_set_destroy_count_func (PsppSheetView *tree_view,
372 PsppSheetDestroyCountFunc func,
373 gpointer data,
374 GDestroyNotify destroy);
375
376 void pspp_sheet_view_set_hover_selection (PsppSheetView *tree_view,
377 gboolean hover);
378 gboolean pspp_sheet_view_get_hover_selection (PsppSheetView *tree_view);
379 void pspp_sheet_view_set_rubber_banding (PsppSheetView *tree_view,
380 gboolean enable);
381 gboolean pspp_sheet_view_get_rubber_banding (PsppSheetView *tree_view);
382
383 gboolean pspp_sheet_view_is_rubber_banding_active (PsppSheetView *tree_view);
384
385 PsppSheetViewGridLines pspp_sheet_view_get_grid_lines (PsppSheetView *tree_view);
386 void pspp_sheet_view_set_grid_lines (PsppSheetView *tree_view,
387 PsppSheetViewGridLines grid_lines);
388
389 PsppSheetViewSpecialCells pspp_sheet_view_get_special_cells (PsppSheetView *tree_view);
390 void pspp_sheet_view_set_special_cells (PsppSheetView *tree_view,
391 PsppSheetViewSpecialCells);
392
393 int pspp_sheet_view_get_fixed_height (const PsppSheetView *);
394 void pspp_sheet_view_set_fixed_height (PsppSheetView *,
395 int fixed_height);
396
397 /* Convenience functions for setting tooltips */
398 void pspp_sheet_view_set_tooltip_row (PsppSheetView *tree_view,
399 GtkTooltip *tooltip,
400 GtkTreePath *path);
401 void pspp_sheet_view_set_tooltip_cell (PsppSheetView *tree_view,
402 GtkTooltip *tooltip,
403 GtkTreePath *path,
404 PsppSheetViewColumn *column,
405 GtkCellRenderer *cell);
406 gboolean pspp_sheet_view_get_tooltip_context(PsppSheetView *tree_view,
407 gint *x,
408 gint *y,
409 gboolean keyboard_tip,
410 GtkTreeModel **model,
411 GtkTreePath **path,
412 GtkTreeIter *iter);
413 void pspp_sheet_view_set_tooltip_column (PsppSheetView *tree_view,
414 gint column);
415 gint pspp_sheet_view_get_tooltip_column (PsppSheetView *tree_view);
416
417 void pspp_sheet_view_stop_editing (PsppSheetView *tree_view,
418 gboolean cancel_editing);
419
420 G_END_DECLS
421
422
423 #endif /* __PSPP_SHEET_VIEW_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "pspp-widget-facade.h"
19
20 #include <math.h>
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 static void
26 inset_rectangle (const GdkRectangle *src,
27 const GtkBorder *inset,
28 GdkRectangle *dst)
29 {
30 dst->x = src->x + inset->left;
31 dst->y = src->y + inset->top;
32 dst->width = MAX (1, src->width - inset->left - inset->right);
33 dst->height = MAX (1, src->height - inset->top - inset->bottom);
34 }
35
36 static void
37 thicken_border (gint x, gint y, GtkBorder *border)
38 {
39 border->left += x;
40 border->right += x;
41 border->top += y;
42 border->bottom += y;
43 }
44
45 GtkStyle *
46 facade_get_style (GtkWidget *base,
47 GType type1,
48 ...)
49 {
50 GString path, class_path;
51 GType final_type;
52 GtkStyle *style;
53 va_list args;
54 GType type;
55
56 gtk_widget_path (base, NULL, &path.str, NULL);
57 path.len = path.allocated_len = strlen (path.str);
58
59 gtk_widget_class_path (base, NULL, &class_path.str, NULL);
60 class_path.len = class_path.allocated_len = strlen (class_path.str);
61
62 va_start (args, type1);
63 for (type = final_type = type1; type != 0; type = va_arg (args, GType))
64 {
65 const gchar *type_name = g_type_name (type);
66 g_string_append_printf (&path, ".%s", type_name);
67 g_string_append_printf (&class_path, ".%s", type_name);
68 final_type = type;
69 }
70 va_end (args);
71
72 style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (base),
73 path.str, class_path.str, final_type);
74
75 free (path.str);
76 free (class_path.str);
77
78 return style;
79 }
80
81 void
82 facade_hbox_get_base_size_request (gint border_width,
83 gint spacing,
84 gint n_children,
85 GtkRequisition *request)
86 {
87 request->width = border_width * 2;
88 if (n_children > 1)
89 request->width += spacing * (n_children - 1);
90
91 request->height = border_width * 2;
92 }
93
94 void
95 facade_hbox_add_child_size_request (gint hbox_border_width,
96 const GtkRequisition *child_request,
97 gint child_padding,
98 GtkRequisition *request)
99 {
100 request->width += child_request->width + child_padding * 2;
101 request->height = MAX (request->height,
102 hbox_border_width * 2 + child_request->height);
103 }
104
105 void
106 facade_arrow_get_size_request (gint xpad,
107 gint ypad,
108 GtkRequisition *request)
109 {
110 #define MIN_ARROW_SIZE 15
111 request->width = MIN_ARROW_SIZE + xpad * 2;
112 request->height = MIN_ARROW_SIZE + ypad * 2;
113 }
114
115 void
116 facade_alignment_get_size_request (gint border_width,
117 gint padding_left,
118 gint padding_right,
119 gint padding_top,
120 gint padding_bottom,
121 const GtkRequisition *child_request,
122 GtkRequisition *request)
123 {
124 request->width = (border_width * 2 + padding_left + padding_right
125 + child_request->width);
126 request->height = (border_width * 2 + padding_top + padding_bottom
127 + child_request->height);
128 }
129
130 void
131 facade_label_get_size_request (gint xpad,
132 gint ypad,
133 GtkWidget *base,
134 const char *text,
135 GtkRequisition *request)
136 {
137 PangoLayout *layout;
138
139 layout = facade_label_get_layout (base, text);
140 facade_label_get_size_request_from_layout (xpad, ypad, layout, request);
141 g_object_unref (layout);
142 }
143
144 void
145 facade_label_get_size_request_from_layout (gint xpad,
146 gint ypad,
147 PangoLayout *layout,
148 GtkRequisition *request)
149 {
150 PangoRectangle logical_rect;
151
152 pango_layout_get_extents (layout, NULL, &logical_rect);
153 request->width = xpad * 2 + PANGO_PIXELS (logical_rect.width);
154 request->height = ypad * 2 + PANGO_PIXELS (logical_rect.height);
155 }
156
157 PangoLayout *
158 facade_label_get_layout (GtkWidget *base,
159 const char *text)
160 {
161 PangoAlignment alignment;
162 PangoLayout *layout;
163 gboolean rtl;
164
165 rtl = gtk_widget_get_direction (base) == GTK_TEXT_DIR_RTL;
166 alignment = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
167
168 layout = gtk_widget_create_pango_layout (base, text);
169 pango_layout_set_alignment (layout, alignment);
170
171 return layout;
172 }
173
174 static void
175 facade_button_get_inner_border (GtkStyle *button_style,
176 GtkBorder *inner_border)
177 {
178 GtkBorder *tmp_border;
179
180 gtk_style_get (button_style, GTK_TYPE_BUTTON,
181 "inner-border", &tmp_border,
182 NULL);
183
184 if (tmp_border)
185 {
186 *inner_border = *tmp_border;
187 gtk_border_free (tmp_border);
188 }
189 else
190 {
191 static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
192 *inner_border = default_inner_border;
193 }
194 }
195
196 void
197 facade_button_get_size_request (gint border_width,
198 GtkWidget *base,
199 GtkStyle *button_style,
200 const GtkRequisition *child_request,
201 GtkRequisition *request)
202 {
203 GtkBorder inner_border;
204 gint common_width;
205 gint focus_width;
206 gint focus_pad;
207
208 gtk_style_get (button_style, GTK_TYPE_BUTTON,
209 "focus-line-width", &focus_width,
210 "focus-padding", &focus_pad,
211 NULL);
212 facade_button_get_inner_border (button_style, &inner_border);
213
214 common_width = 2 * (border_width + focus_width + focus_pad);
215 request->width = (common_width
216 + 2 * button_style->xthickness
217 + inner_border.left + inner_border.right
218 + child_request->width);
219 request->height = (common_width
220 + 2 * button_style->ythickness
221 + inner_border.top + inner_border.bottom
222 + child_request->height);
223 }
224
225 void
226 facade_button_get_focus_inset (gint border_width,
227 GtkWidget *base,
228 GtkStyle *button_style,
229 GtkBorder *focus_inset)
230 {
231 facade_button_get_inner_border (button_style, focus_inset);
232 thicken_border (border_width + button_style->xthickness,
233 border_width + button_style->ythickness,
234 focus_inset);
235 }
236
237 static void
238 facade_button_get_label_inset (gint border_width,
239 GtkWidget *base,
240 GtkStyle *button_style,
241 GtkBorder *label_inset)
242 {
243 gint focus_width;
244 gint focus_pad;
245
246 facade_button_get_focus_inset (border_width, base, button_style,
247 label_inset);
248
249 gtk_style_get (button_style, GTK_TYPE_BUTTON,
250 "focus-line-width", &focus_width,
251 "focus-padding", &focus_pad,
252 NULL);
253 thicken_border (focus_width + focus_pad,
254 focus_width + focus_pad,
255 label_inset);
256 }
257
258 static void
259 get_layout_location (GtkWidget *base,
260 const GdkRectangle *label_area,
261 PangoLayout *layout,
262 gint xpad,
263 gint ypad,
264 gfloat xalign,
265 gfloat yalign,
266 gint *x,
267 gint *y)
268 {
269 PangoRectangle logical;
270 GtkRequisition req;
271
272 if (gtk_widget_get_direction (base) == GTK_TEXT_DIR_LTR)
273 xalign = xalign;
274 else
275 xalign = 1.0 - xalign;
276
277 pango_layout_get_pixel_extents (layout, NULL, &logical);
278
279 facade_label_get_size_request_from_layout (xpad, ypad, layout, &req);
280
281 *x = floor (label_area->x + xpad + xalign * (label_area->width - req.width));
282
283 if (gtk_widget_get_direction (base) == GTK_TEXT_DIR_LTR)
284 *x = MAX (*x, label_area->x + xpad);
285 else
286 *x = MIN (*x, label_area->x + label_area->width - xpad);
287 *x -= logical.x;
288
289 /* bgo#315462 - For single-line labels, *do* align the requisition with
290 * respect to the allocation, even if we are under-allocated. For multi-line
291 * labels, always show the top of the text when they are under-allocated.
292 * The rationale is this:
293 *
294 * - Single-line labels appear in GtkButtons, and it is very easy to get them
295 * to be smaller than their requisition. The button may clip the label,
296 * but the label will still be able to show most of itself and the focus
297 * rectangle. Also, it is fairly easy to read a single line of clipped
298 * text.
299 *
300 * - Multi-line labels should not be clipped to showing "something in the
301 * middle". You want to read the first line, at least, to get some
302 * context.
303 */
304 if (pango_layout_get_line_count (layout) == 1)
305 *y = floor (label_area->y + ypad
306 + (label_area->height - req.height) * yalign);
307 else
308 *y = floor (label_area->y + ypad
309 + MAX (((label_area->height - req.height) * yalign),
310 0));
311 }
312
313 void
314 facade_button_render (GtkWidget *base,
315 GdkDrawable *window,
316 GdkRectangle *expose_area,
317
318 GdkRectangle *button_area,
319 gint border_width,
320 GtkStyle *button_style,
321 GtkStateType state_type,
322
323 GtkStyle *label_style,
324 const gchar *label,
325 gint xpad,
326 gint ypad,
327 gfloat xalign,
328 gfloat yalign)
329 {
330 GdkRectangle label_area;
331 PangoLayout *layout;
332 GtkBorder inset;
333 gint x, y;
334
335 /* Paint the button. */
336 gtk_paint_box (button_style, window,
337 state_type,
338 GTK_SHADOW_OUT, expose_area, base, "button",
339 button_area->x + border_width,
340 button_area->y + border_width,
341 button_area->width - border_width * 2,
342 button_area->height - border_width * 2);
343
344 /* Figure out where the label should go. */
345 facade_button_get_label_inset (border_width, base, button_style, &inset);
346 inset_rectangle (button_area, &inset, &label_area);
347
348 /* Paint the label. */
349 layout = facade_label_get_layout (base, label);
350 get_layout_location (base, &label_area, layout, xpad, ypad, xalign, yalign,
351 &x, &y);
352 gtk_paint_layout (label_style, window, state_type, FALSE, expose_area,
353 base, "label", x, y, layout);
354 g_object_unref (layout);
355 }
356
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef FACADE_WIDGET_FACADE_H
17 #define FACADE_WIDGET_FACADE_H 1
18
19 #include <gtk/gtk.h>
20
21 G_BEGIN_DECLS
22
23 GtkStyle *facade_get_style (GtkWidget *base, GType, ...);
24
25 void facade_hbox_get_base_size_request (gint border_width,
26 gint spacing,
27 gint n_children,
28 GtkRequisition *);
29 void facade_hbox_add_child_size_request (gint hbox_border_width,
30 const GtkRequisition *child_request,
31 gint child_padding,
32 GtkRequisition *);
33
34 void facade_arrow_get_size_request (gint xpad,
35 gint ypad,
36 GtkRequisition *);
37
38
39 void facade_alignment_get_size_request (gint border_width,
40 gint padding_left,
41 gint padding_right,
42 gint padding_top,
43 gint padding_bottom,
44 const GtkRequisition *child_request,
45 GtkRequisition *);
46
47 void facade_label_get_size_request (gint xpad,
48 gint ypad,
49 GtkWidget *base,
50 const char *text,
51 GtkRequisition *);
52 void facade_label_get_size_request_from_layout (gint xpad,
53 gint ypad,
54 PangoLayout *,
55 GtkRequisition *);
56 PangoLayout *facade_label_get_layout (GtkWidget *base,
57 const char *text);
58
59 void facade_button_get_size_request (gint border_width,
60 GtkWidget *base,
61 GtkStyle *button_style,
62 const GtkRequisition *child_request,
63 GtkRequisition *);
64 void facade_button_render (GtkWidget *base,
65 GdkDrawable *window,
66 GdkRectangle *expose_area,
67
68 GdkRectangle *button_area,
69 gint border_width,
70 GtkStyle *button_style,
71 GtkStateType state_type,
72
73 GtkStyle *label_style,
74 const gchar *label,
75 gint xpad,
76 gint ypad,
77 gfloat xalign,
78 gfloat yalign);
79 void facade_button_get_focus_inset (gint border_width,
80 GtkWidget *base,
81 GtkStyle *button_style,
82 GtkBorder *focus_inset);
83
84 G_END_DECLS
85
86 #endif /* FACADE_WIDGET_FACADE_H */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
3939 #include "psppire-acr.h"
4040 #include "helper.h"
4141
42 static void psppire_acr_init (PsppireAcr *);
43
44 GType
45 psppire_acr_get_type (void)
46 {
47 static GType acr_type = 0;
48
49 if (!acr_type)
50 {
51 static const GTypeInfo acr_info =
52 {
53 sizeof (PsppireAcrClass),
54 NULL, /* base_init */
55 NULL, /* base_finalize */
56 NULL, /* class_init */
57 NULL, /* class_finalize */
58 NULL, /* class_data */
59 sizeof (PsppireAcr),
60 0,
61 (GInstanceInitFunc) psppire_acr_init,
62 };
63
64 acr_type = g_type_register_static (GTK_TYPE_HBOX, "PsppireAcr",
65 &acr_info, 0);
66 }
67
68 return acr_type;
69 }
70
42 G_DEFINE_TYPE (PsppireAcr, psppire_acr, GTK_TYPE_HBOX);
43
44 static void
45 psppire_acr_dispose (GObject *obj)
46 {
47 PsppireAcr *acr = PSPPIRE_ACR (obj);
48 psppire_acr_set_model (acr, NULL);
49
50 G_OBJECT_CLASS (psppire_acr_parent_class)->dispose (obj);
51 }
52
53 static void
54 psppire_acr_class_init (PsppireAcrClass *class)
55 {
56 G_OBJECT_CLASS (class)->dispose = psppire_acr_dispose;
57 }
7158
7259 static gboolean row_is_selected (const PsppireAcr *acr);
7360
346333
347334
348335
349 /* Set the widget's treemodel */
336 /* Set the widget's treemodel to LISTSTORE. LISTSTORE ownership is not
337 transferred. */
350338 void
351339 psppire_acr_set_model (PsppireAcr *acr, GtkListStore *liststore)
352340 {
341 if (acr->list_store)
342 g_object_unref (acr->list_store);
343 if (liststore)
344 g_object_ref (liststore);
345
353346 acr->list_store = liststore;
354347
355348 gtk_tree_view_set_model (GTK_TREE_VIEW (acr->tv),
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "ui/gui/psppire-button-editable.h"
19
20 #include <gettext.h>
21 #define _(msgid) gettext (msgid)
22 #define N_(msgid) msgid
23
24 /* GtkCellEditable interface. */
25 static void gtk_cell_editable_interface_init (GtkCellEditableIface *iface);
26 static void button_editable_editing_done (GtkCellEditable *cell_editable);
27 static void button_editable_remove_widget (GtkCellEditable *cell_editable);
28 static void button_editable_start_editing (GtkCellEditable *cell_editable,
29 GdkEvent *event);
30
31 G_DEFINE_TYPE_EXTENDED (PsppireButtonEditable,
32 psppire_button_editable,
33 GTK_TYPE_BUTTON,
34 0,
35 G_IMPLEMENT_INTERFACE (
36 GTK_TYPE_CELL_EDITABLE,
37 gtk_cell_editable_interface_init));
38
39 enum
40 {
41 PROP_0,
42 PROP_PATH,
43 PROP_SLASH
44 };
45
46 static void
47 psppire_button_editable_set_property (GObject *object,
48 guint prop_id,
49 const GValue *value,
50 GParamSpec *pspec)
51 {
52 PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (object);
53
54 switch (prop_id)
55 {
56 case PROP_PATH:
57 g_free (obj->path);
58 obj->path = g_value_dup_string (value);
59 break;
60
61 case PROP_SLASH:
62 psppire_button_editable_set_slash (obj, g_value_get_boolean (value));
63 break;
64
65 default:
66 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
67 break;
68 }
69 }
70
71 static void
72 psppire_button_editable_get_property (GObject *object,
73 guint prop_id,
74 GValue *value,
75 GParamSpec *pspec)
76 {
77 PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (object);
78
79 switch (prop_id)
80 {
81 case PROP_PATH:
82 g_value_set_string (value, obj->path);
83 break;
84
85 case PROP_SLASH:
86 g_value_set_boolean (value, psppire_button_editable_get_slash (obj));
87 break;
88
89 default:
90 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91 break;
92 }
93 }
94
95 static void
96 psppire_button_editable_dispose (GObject *gobject)
97 {
98 PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (gobject);
99
100 g_free (obj->path);
101 obj->path = NULL;
102
103 G_OBJECT_CLASS (psppire_button_editable_parent_class)->dispose (gobject);
104 }
105
106 static gboolean
107 psppire_button_editable_button_release (GtkWidget *widget,
108 GdkEventButton *event)
109 {
110 GtkButton *button;
111
112 if (event->button == 1)
113 {
114 button = GTK_BUTTON (widget);
115 gtk_button_released (button);
116 }
117
118 return TRUE;
119 }
120
121 static gboolean
122 psppire_button_editable_expose_event (GtkWidget *widget,
123 GdkEventExpose *event)
124 {
125 GtkWidgetClass *widget_class;
126 GtkStyle *style = gtk_widget_get_style (widget);
127 GtkAllocation allocation;
128 gboolean retval;
129
130 widget_class = GTK_WIDGET_CLASS (psppire_button_editable_parent_class);
131 retval = widget_class->expose_event (widget, event);
132
133 gtk_widget_get_allocation (widget, &allocation);
134 if (PSPPIRE_BUTTON_EDITABLE (widget)->slash)
135 gdk_draw_line (gtk_widget_get_window (widget), style->black_gc,
136 allocation.x,
137 allocation.y + allocation.height,
138 allocation.x + allocation.width,
139 allocation.y);
140 return retval;
141 }
142
143 static void
144 psppire_button_editable_class_init (PsppireButtonEditableClass *class)
145 {
146 GObjectClass *gobject_class;
147 GtkWidgetClass *widget_class;
148
149 gobject_class = G_OBJECT_CLASS (class);
150 widget_class = GTK_WIDGET_CLASS (class);
151
152 gobject_class->set_property = psppire_button_editable_set_property;
153 gobject_class->get_property = psppire_button_editable_get_property;
154 gobject_class->dispose = psppire_button_editable_dispose;
155
156 widget_class->button_release_event = psppire_button_editable_button_release;
157 widget_class->expose_event = psppire_button_editable_expose_event;
158
159 g_object_class_install_property (gobject_class,
160 PROP_PATH,
161 g_param_spec_string ("path",
162 _("TreeView path"),
163 _("The path to the row in the GtkTreeView, as a string"),
164 "",
165 G_PARAM_READWRITE));
166
167 g_object_class_install_property (gobject_class,
168 PROP_SLASH,
169 g_param_spec_boolean ("slash",
170 _("Diagonal slash"),
171 _("Whether to draw a diagonal slash across the button."),
172 FALSE,
173 G_PARAM_READWRITE));
174
175 }
176
177 static void
178 psppire_button_editable_init (PsppireButtonEditable *obj)
179 {
180 obj->path = g_strdup ("");
181 obj->slash = FALSE;
182 }
183
184 PsppireButtonEditable *
185 psppire_button_editable_new (void)
186 {
187 return PSPPIRE_BUTTON_EDITABLE (g_object_new (PSPPIRE_TYPE_BUTTON_EDITABLE, NULL));
188 }
189
190 void
191 psppire_button_editable_set_slash (PsppireButtonEditable *button,
192 gboolean slash)
193 {
194 g_return_if_fail (button != NULL);
195 if ((button->slash != 0) != (slash != 0))
196 {
197 button->slash = slash;
198 gtk_widget_queue_draw (GTK_WIDGET (button));
199 }
200 }
201
202 gboolean
203 psppire_button_editable_get_slash (const PsppireButtonEditable *button)
204 {
205 g_return_val_if_fail (button != NULL, FALSE);
206 return button->slash;
207 }
208
209 /* GtkCellEditable interface. */
210
211 static void
212 gtk_cell_editable_interface_init (GtkCellEditableIface *iface)
213 {
214 g_return_if_fail (iface != NULL);
215
216 iface->editing_done = button_editable_editing_done;
217 iface->remove_widget = button_editable_remove_widget;
218 iface->start_editing = button_editable_start_editing;
219 }
220
221 static void
222 button_editable_editing_done (GtkCellEditable *cell_editable)
223 {
224
225
226 }
227
228 static void
229 button_editable_remove_widget (GtkCellEditable *cell_editable)
230 {
231
232
233 }
234
235 static void
236 button_editable_start_editing (GtkCellEditable *cell_editable,
237 GdkEvent *event)
238 {
239 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef PSPPIRE_BUTTON_EDITABLE_H
17 #define PSPPIRE_BUTTON_EDITABLE_H 1
18
19 #include <gtk/gtk.h>
20
21 G_BEGIN_DECLS
22
23 #define PSPPIRE_TYPE_BUTTON_EDITABLE (psppire_button_editable_get_type())
24 #define PSPPIRE_BUTTON_EDITABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditable))
25 #define PSPPIRE_BUTTON_EDITABLE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditableClass))
26 #define PSPPIRE_IS_BUTTON_EDITABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE))
27 #define PSPPIRE_IS_BUTTON_EDITABLE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_BUTTON_EDITABLE))
28 #define PSPPIRE_BUTTON_EDITABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditableClass))
29
30 typedef struct _PsppireButtonEditable PsppireButtonEditable;
31 typedef struct _PsppireButtonEditableClass PsppireButtonEditableClass;
32
33 struct _PsppireButtonEditable {
34 GtkButton parent;
35 gchar *path;
36 gboolean slash;
37 };
38
39 struct _PsppireButtonEditableClass {
40 GtkButtonClass parent_class;
41 };
42
43 GType psppire_button_editable_get_type (void) G_GNUC_CONST;
44 PsppireButtonEditable* psppire_button_editable_new (void);
45
46 void psppire_button_editable_set_slash (PsppireButtonEditable *,
47 gboolean slash);
48 gboolean psppire_button_editable_get_slash (const PsppireButtonEditable *);
49
50 G_END_DECLS
51
52 #endif /* PSPPIRE_BUTTON_EDITABLE_H */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2010, 2011 Free Software Foundation
1 Copyright (C) 2007, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
151151 PSPPIRE_BUTTON_GOTO_MASK = (1 << PSPPIRE_BUTTON_GOTO),
152152 PSPPIRE_BUTTON_CONTINUE_MASK = (1 << PSPPIRE_BUTTON_CONTINUE),
153153 PSPPIRE_BUTTON_CANCEL_MASK = (1 << PSPPIRE_BUTTON_CANCEL),
154 PSPPIRE_BUTTON_CLOSE_MASK = (1 << PSPPIRE_BUTTON_CLOSE),
154155 PSPPIRE_BUTTON_HELP_MASK = (1 << PSPPIRE_BUTTON_HELP),
155156 PSPPIRE_BUTTON_RESET_MASK = (1 << PSPPIRE_BUTTON_RESET),
156157 PSPPIRE_BUTTON_PASTE_MASK = (1 << PSPPIRE_BUTTON_PASTE)
349350 psppire_box_pack_start_defaults (GTK_BOX (bb), bb->button[PSPPIRE_BUTTON_CANCEL]);
350351 g_object_set (bb->button[PSPPIRE_BUTTON_CANCEL], "no-show-all", TRUE, NULL);
351352
353 bb->button[PSPPIRE_BUTTON_CLOSE] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
354 g_signal_connect (bb->button[PSPPIRE_BUTTON_CLOSE], "clicked",
355 G_CALLBACK (close_dialog), NULL);
356 psppire_box_pack_start_defaults (GTK_BOX (bb), bb->button[PSPPIRE_BUTTON_CLOSE]);
357 g_object_set (bb->button[PSPPIRE_BUTTON_CLOSE], "no-show-all", TRUE, NULL);
358
352359
353360 bb->button[PSPPIRE_BUTTON_RESET] = gtk_button_new_from_stock ("pspp-stock-reset");
354361 g_signal_connect (bb->button[PSPPIRE_BUTTON_RESET], "clicked",
485492 { PSPPIRE_BUTTON_GOTO_MASK, "PSPPIRE_BUTTON_GOTO_MASK", "Goto case/variable" },
486493 { PSPPIRE_BUTTON_CONTINUE_MASK,"PSPPIRE_BUTTON_CONTINUE_MASK", "Accept and close the subdialog" },
487494 { PSPPIRE_BUTTON_CANCEL_MASK, "PSPPIRE_BUTTON_CANCEL_MASK", "Close dialog and discard settings" },
495 { PSPPIRE_BUTTON_CLOSE_MASK, "PSPPIRE_BUTTON_CLOSE_MASK", "Close dialog" },
488496 { PSPPIRE_BUTTON_HELP_MASK, "PSPPIRE_BUTTON_HELP_MASK", "Invoke context sensitive help" },
489497 { PSPPIRE_BUTTON_RESET_MASK, "PSPPIRE_BUTTON_RESET_MASK", "Restore dialog to its default settings" },
490498 { PSPPIRE_BUTTON_PASTE_MASK, "PSPPIRE_BUTTON_PASTE_MASK", "Accept dialog and paste syntax" },
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2010, 2011 Free Software Foundation
1 Copyright (C) 2007, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
4040 PSPPIRE_BUTTON_GOTO,
4141 PSPPIRE_BUTTON_CONTINUE,
4242 PSPPIRE_BUTTON_CANCEL,
43 PSPPIRE_BUTTON_CLOSE,
4344 PSPPIRE_BUTTON_HELP,
4445 PSPPIRE_BUTTON_RESET,
4546 PSPPIRE_BUTTON_PASTE,
6970 int *nvis_children,
7071 int *nvis_secondaries,
7172 int *width,
73 int *height);
7274
73
74 #define PSPPIRE_TYPE_BUTTON_MASK \
75 (psppire_button_flags_get_type())
76 int *height);
75 #define PSPPIRE_TYPE_BUTTON_MASK psppire_button_flags_get_type()
7776
7877 G_END_DECLS
7978
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "ui/gui/psppire-cell-renderer-button.h"
19
20 #include <math.h>
21 #include <string.h>
22
23 #include "ui/gui/psppire-button-editable.h"
24 #include "ui/gui/pspp-widget-facade.h"
25
26 #include "gl/configmake.h"
27 #include "gl/relocatable.h"
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31
32 static void psppire_cell_renderer_button_destroy (GtkObject *);
33 static void psppire_cell_renderer_button_finalize (GObject *);
34
35 static void update_style_cache (PsppireCellRendererButton *button,
36 GtkWidget *widget);
37
38 static void psppire_cell_renderer_button_load_gtkrc (void);
39
40
41 G_DEFINE_TYPE_EXTENDED (PsppireCellRendererButton,
42 psppire_cell_renderer_button,
43 GTK_TYPE_CELL_RENDERER,
44 0,
45 psppire_cell_renderer_button_load_gtkrc ());
46
47 static void
48 psppire_cell_renderer_button_load_gtkrc (void)
49 {
50 const char *gtkrc_file;
51
52 gtkrc_file = relocate (PKGDATADIR "/psppire.gtkrc");
53 gtk_rc_add_default_file (gtkrc_file);
54 gtk_rc_parse (gtkrc_file);
55 }
56
57 enum
58 {
59 PROP_0,
60 PROP_EDITABLE,
61 PROP_LABEL,
62 PROP_SLASH
63 };
64
65 static void
66 psppire_cell_renderer_button_set_property (GObject *object,
67 guint prop_id,
68 const GValue *value,
69 GParamSpec *pspec)
70 {
71 PsppireCellRendererButton *obj = PSPPIRE_CELL_RENDERER_BUTTON (object);
72
73 switch (prop_id)
74 {
75 case PROP_EDITABLE:
76 obj->editable = g_value_get_boolean (value);
77 if (obj->editable)
78 GTK_CELL_RENDERER (obj)->mode = GTK_CELL_RENDERER_MODE_EDITABLE;
79 else
80 GTK_CELL_RENDERER (obj)->mode = GTK_CELL_RENDERER_MODE_INERT;
81 break;
82
83 case PROP_LABEL:
84 g_free (obj->label);
85 obj->label = g_value_dup_string (value);
86 break;
87
88 case PROP_SLASH:
89 psppire_cell_renderer_button_set_slash (obj,
90 g_value_get_boolean (value));
91 break;
92
93 default:
94 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
95 break;
96 }
97 }
98
99 static void
100 psppire_cell_renderer_button_get_property (GObject *object,
101 guint prop_id,
102 GValue *value,
103 GParamSpec *pspec)
104 {
105 PsppireCellRendererButton *obj = PSPPIRE_CELL_RENDERER_BUTTON (object);
106
107 switch (prop_id)
108 {
109 case PROP_EDITABLE:
110 g_value_set_boolean (value, obj->editable);
111 break;
112
113 case PROP_LABEL:
114 g_value_set_string (value, obj->label);
115 break;
116
117 case PROP_SLASH:
118 g_value_set_boolean (value,
119 psppire_cell_renderer_button_get_slash (obj));
120 break;
121
122 default:
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124 break;
125 }
126 }
127
128 static void
129 on_style_set (GtkWidget *base,
130 GtkStyle *previous_style,
131 PsppireCellRendererButton *button)
132 {
133 update_style_cache (button, NULL);
134 }
135
136 static void
137 on_destroy (GtkObject *base,
138 PsppireCellRendererButton *button)
139 {
140 update_style_cache (button, NULL);
141 }
142
143 static void
144 update_style_cache (PsppireCellRendererButton *button,
145 GtkWidget *widget)
146 {
147 if (button->base == widget)
148 return;
149
150 /* Clear old cache. */
151 if (button->button_style)
152 {
153 g_object_unref (button->button_style);
154 button->button_style = NULL;
155 }
156 if (button->label_style)
157 {
158 g_object_unref (button->label_style);
159 button->label_style = NULL;
160 }
161 if (button->base != NULL)
162 {
163 if (button->style_set_handler)
164 {
165 g_signal_handler_disconnect (button->base,
166 button->style_set_handler);
167 button->style_set_handler = 0;
168 }
169 if (button->destroy_handler)
170 {
171 g_signal_handler_disconnect (button->base, button->destroy_handler);
172 button->destroy_handler = 0;
173 }
174 g_object_unref (button->base);
175 button->base = NULL;
176 }
177
178 /* Populate cache. */
179 if (widget)
180 {
181 button->button_style = facade_get_style (widget, GTK_TYPE_BUTTON, 0);
182 button->label_style = facade_get_style (widget, GTK_TYPE_BUTTON,
183 GTK_TYPE_LABEL, 0);
184 button->base = widget;
185 button->style_set_handler = g_signal_connect (widget, "style-set",
186 G_CALLBACK (on_style_set),
187 button);
188 button->destroy_handler = g_signal_connect (widget, "destroy",
189 G_CALLBACK (on_destroy),
190 button);
191
192 g_object_ref (widget);
193 g_object_ref (button->button_style);
194 g_object_ref (button->label_style);
195 }
196 }
197
198 static void
199 psppire_cell_renderer_button_render (GtkCellRenderer *cell,
200 GdkDrawable *window,
201 GtkWidget *widget,
202 GdkRectangle *background_area,
203 GdkRectangle *cell_area,
204 GdkRectangle *expose_area,
205 GtkCellRendererState flags)
206 {
207 PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
208 GtkStateType state_type;
209
210 if (!button->editable || !cell->sensitive)
211 state_type = GTK_STATE_INSENSITIVE;
212 else if (flags & GTK_CELL_RENDERER_SELECTED)
213 {
214 if (gtk_widget_has_focus (widget))
215 state_type = GTK_STATE_SELECTED;
216 else
217 state_type = GTK_STATE_ACTIVE;
218 }
219 else if (flags & GTK_CELL_RENDERER_PRELIT)
220 state_type = GTK_STATE_PRELIGHT;
221 else
222 {
223 if (gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE)
224 state_type = GTK_STATE_INSENSITIVE;
225 else
226 state_type = GTK_STATE_NORMAL;
227 }
228
229 update_style_cache (button, widget);
230 facade_button_render (widget, window, expose_area,
231 cell_area, button->border_width, button->button_style,
232 state_type,
233 button->label_style, button->label, button->xpad,
234 button->ypad, cell->xalign, cell->yalign);
235
236 if (button->slash)
237 gdk_draw_line (window, button->button_style->black_gc,
238 cell_area->x,
239 cell_area->y + cell_area->height,
240 cell_area->x + cell_area->width,
241 cell_area->y);
242 }
243
244 static void
245 psppire_cell_renderer_button_get_size (GtkCellRenderer *cell,
246 GtkWidget *widget,
247 GdkRectangle *cell_area,
248 gint *x_offset,
249 gint *y_offset,
250 gint *width,
251 gint *height)
252 {
253 PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
254
255 update_style_cache (button, widget);
256 if (cell_area != NULL)
257 {
258 /* The caller is really asking for the placement of the focus rectangle.
259 The focus rectangle should surround the whole label area, so calculate
260 that area. */
261 GtkBorder inset;
262
263 facade_button_get_focus_inset (button->border_width, widget,
264 button->button_style, &inset);
265
266 if (x_offset)
267 *x_offset = inset.left;
268 if (y_offset)
269 *y_offset = inset.top;
270 if (width)
271 *width = MAX (1, cell_area->width - inset.left - inset.right);
272 if (height)
273 *height = MAX (1, cell_area->height - inset.top - inset.bottom);
274 }
275 else
276 {
277 /* The caller is asking for the preferred size of the cell. */
278 GtkRequisition label_req;
279 GtkRequisition request;
280
281 facade_label_get_size_request (button->xpad, button->ypad,
282 widget, button->label, &label_req);
283 facade_button_get_size_request (button->border_width, widget,
284 button->button_style, &label_req,
285 &request);
286
287 if (x_offset)
288 *x_offset = 0;
289 if (y_offset)
290 *y_offset = 0;
291 if (width)
292 *width = request.width;
293 if (height)
294 *height = request.height;
295 }
296 }
297
298 static void
299 psppire_cell_renderer_button_clicked (GtkButton *button,
300 gpointer data)
301 {
302 PsppireCellRendererButton *cell_button = data;
303 gchar *path;
304
305 g_object_get (button, "path", &path, NULL);
306 g_signal_emit_by_name (cell_button, "clicked", path);
307 g_free (path);
308 }
309
310 static gboolean
311 psppire_cell_renderer_button_focus_out_event (GtkWidget *widget,
312 GdkEvent *event,
313 gpointer data)
314 {
315 PsppireCellRendererButton *cell_button = data;
316
317 g_signal_handlers_disconnect_by_func (widget,
318 psppire_cell_renderer_button_focus_out_event,
319 data);
320 g_signal_handlers_disconnect_by_func (widget,
321 psppire_cell_renderer_button_clicked,
322 data);
323
324 gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (cell_button), FALSE);
325
326 return FALSE;
327 }
328
329 #define IDLE_ID_STRING "psppire-cell-renderer-button-idle-id"
330
331 static gboolean
332 psppire_cell_renderer_button_initial_click (gpointer data)
333 {
334 GtkButton *button = data;
335
336 gtk_button_clicked (button);
337 g_object_steal_data (G_OBJECT (button), IDLE_ID_STRING);
338 return FALSE;
339 }
340
341 static void
342 psppire_cell_renderer_button_on_destroy (GObject *object, gpointer user_data)
343 {
344 guint idle_id;
345
346 idle_id = GPOINTER_TO_INT (g_object_steal_data (object, IDLE_ID_STRING));
347 if (idle_id != 0)
348 g_source_remove (idle_id);
349 }
350
351 static void
352 psppire_cell_renderer_button_double_click (GtkButton *button,
353 PsppireCellRendererButton *cell_button)
354 {
355 gchar *path;
356
357 if (g_object_get_data (G_OBJECT (button), IDLE_ID_STRING))
358 psppire_cell_renderer_button_initial_click (button);
359
360 g_object_get (button, "path", &path, NULL);
361 g_signal_emit_by_name (cell_button, "double-clicked", path);
362 g_free (path);
363 }
364
365 static gboolean
366 psppire_cell_renderer_button_press_event (GtkButton *button,
367 GdkEventButton *event,
368 gpointer data)
369 {
370 PsppireCellRendererButton *cell_button = data;
371
372 if (cell_button->click_time != 0)
373 {
374 GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
375 GtkSettings *settings = gtk_settings_get_for_screen (screen);
376 gint double_click_distance;
377 gint double_click_time;
378
379 g_object_get (settings,
380 "gtk-double-click-time", &double_click_time,
381 "gtk-double-click-distance", &double_click_distance,
382 NULL);
383
384 if (event->type == GDK_BUTTON_PRESS
385 && event->button == 1
386 && event->time <= cell_button->click_time + double_click_time
387 && ABS (event->x_root - cell_button->click_x) <= double_click_distance
388 && ABS (event->y_root - cell_button->click_y) <= double_click_distance)
389 {
390 psppire_cell_renderer_button_double_click (button, cell_button);
391 return TRUE;
392 }
393
394 cell_button->click_time = 0;
395 }
396
397 if (event->type == GDK_2BUTTON_PRESS)
398 {
399 psppire_cell_renderer_button_double_click (button, cell_button);
400 return TRUE;
401 }
402
403 return FALSE;
404 }
405
406 static GtkCellEditable *
407 psppire_cell_renderer_button_start_editing (GtkCellRenderer *cell,
408 GdkEvent *event,
409 GtkWidget *widget,
410 const gchar *path,
411 GdkRectangle *background_area,
412 GdkRectangle *cell_area,
413 GtkCellRendererState flags)
414 {
415 PsppireCellRendererButton *cell_button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
416 gfloat xalign, yalign;
417
418 gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
419 cell_button->button = g_object_new (PSPPIRE_TYPE_BUTTON_EDITABLE,
420 "label", cell_button->label,
421 "xalign", xalign,
422 "yalign", yalign,
423 "path", path,
424 "slash", cell_button->slash,
425 NULL);
426
427 g_signal_connect (G_OBJECT (cell_button->button), "focus-out-event",
428 G_CALLBACK (psppire_cell_renderer_button_focus_out_event),
429 cell);
430 g_signal_connect (G_OBJECT (cell_button->button), "clicked",
431 G_CALLBACK (psppire_cell_renderer_button_clicked),
432 cell);
433 g_signal_connect (G_OBJECT (cell_button->button), "button-press-event",
434 G_CALLBACK (psppire_cell_renderer_button_press_event),
435 cell);
436
437 gtk_widget_show (cell_button->button);
438
439 if (event != NULL && event->any.type == GDK_BUTTON_RELEASE)
440 {
441 guint idle_id;
442
443 cell_button->click_time = event->button.time;
444 cell_button->click_x = event->button.x_root;
445 cell_button->click_y = event->button.y_root;
446 idle_id = g_idle_add (psppire_cell_renderer_button_initial_click,
447 cell_button->button);
448 g_object_set_data (G_OBJECT (cell_button->button), IDLE_ID_STRING,
449 GINT_TO_POINTER (idle_id));
450 g_signal_connect (G_OBJECT (cell_button->button), "destroy",
451 G_CALLBACK (psppire_cell_renderer_button_on_destroy),
452 NULL);
453 }
454 else
455 {
456 cell_button->click_time = 0;
457 cell_button->click_x = 0;
458 cell_button->click_y = 0;
459 }
460
461 return GTK_CELL_EDITABLE (cell_button->button);
462 }
463
464 static void
465 psppire_cell_renderer_button_class_init (PsppireCellRendererButtonClass *class)
466 {
467 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
468 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
469 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
470
471 gobject_class->set_property = psppire_cell_renderer_button_set_property;
472 gobject_class->get_property = psppire_cell_renderer_button_get_property;
473 gobject_class->finalize = psppire_cell_renderer_button_finalize;
474
475 gtk_object_class->destroy = psppire_cell_renderer_button_destroy;
476
477 cell_class->get_size = psppire_cell_renderer_button_get_size;
478 cell_class->render = psppire_cell_renderer_button_render;
479 cell_class->start_editing = psppire_cell_renderer_button_start_editing;
480
481 g_signal_new ("clicked",
482 G_TYPE_FROM_CLASS (gobject_class),
483 G_SIGNAL_RUN_LAST,
484 0,
485 NULL, NULL,
486 g_cclosure_marshal_VOID__STRING,
487 G_TYPE_NONE,
488 1, G_TYPE_STRING);
489
490 g_signal_new ("double-clicked",
491 G_TYPE_FROM_CLASS (gobject_class),
492 G_SIGNAL_RUN_LAST,
493 0,
494 NULL, NULL,
495 g_cclosure_marshal_VOID__STRING,
496 G_TYPE_NONE,
497 1, G_TYPE_STRING);
498
499 g_object_class_install_property (gobject_class,
500 PROP_EDITABLE,
501 g_param_spec_boolean ("editable",
502 "Editable",
503 "Whether the button may be clicked.",
504 FALSE,
505 G_PARAM_READWRITE));
506
507 g_object_class_install_property (gobject_class,
508 PROP_LABEL,
509 g_param_spec_string ("label",
510 "Label",
511 "Text to appear in button.",
512 "",
513 G_PARAM_READWRITE));
514
515 g_object_class_install_property (gobject_class,
516 PROP_SLASH,
517 g_param_spec_boolean ("slash",
518 _("Diagonal slash"),
519 _("Whether to draw a diagonal slash across the button."),
520 FALSE,
521 G_PARAM_READWRITE));
522
523 }
524
525 static void
526 psppire_cell_renderer_button_init (PsppireCellRendererButton *obj)
527 {
528 obj->editable = FALSE;
529 obj->label = g_strdup ("");
530 obj->border_width = 0;
531 obj->xpad = 0;
532 obj->ypad = 0;
533
534 obj->slash = FALSE;
535
536 obj->button = NULL;
537
538 obj->button_style = NULL;
539 obj->label_style = NULL;
540 obj->base = NULL;
541 obj->style_set_handler = 0;
542 obj->destroy_handler = 0;
543 }
544
545 static void
546 psppire_cell_renderer_button_finalize (GObject *obj)
547 {
548 PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (obj);
549
550 g_free (button->label);
551 }
552
553 static void
554 psppire_cell_renderer_button_destroy (GtkObject *obj)
555 {
556 PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (obj);
557
558 update_style_cache (button, NULL);
559
560 GTK_OBJECT_CLASS (psppire_cell_renderer_button_parent_class)->destroy (obj);
561 }
562
563 GtkCellRenderer *
564 psppire_cell_renderer_button_new (void)
565 {
566 return GTK_CELL_RENDERER (g_object_new (PSPPIRE_TYPE_CELL_RENDERER_BUTTON, NULL));
567 }
568
569 void
570 psppire_cell_renderer_button_set_slash (PsppireCellRendererButton *button,
571 gboolean slash)
572 {
573 g_return_if_fail (button != NULL);
574 button->slash = slash;
575 }
576
577 gboolean
578 psppire_cell_renderer_button_get_slash (const PsppireCellRendererButton *button)
579 {
580 g_return_val_if_fail (button != NULL, FALSE);
581 return button->slash;
582 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef PSPPIRE_CELL_RENDERER_BUTTON_H
17 #define PSPPIRE_CELL_RENDERER_BUTTON_H 1
18
19 #include <gtk/gtk.h>
20
21 G_BEGIN_DECLS
22
23 #define PSPPIRE_TYPE_CELL_RENDERER_BUTTON (psppire_cell_renderer_button_get_type())
24 #define PSPPIRE_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButton))
25 #define PSPPIRE_CELL_RENDERER_BUTTON_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButtonClass))
26 #define PSPPIRE_IS_CELL_RENDERER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON))
27 #define PSPPIRE_IS_CELL_RENDERER_BUTTON_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_CELL_RENDERER_BUTTON))
28 #define PSPPIRE_CELL_RENDERER_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButtonClass))
29
30 typedef struct _PsppireCellRendererButton PsppireCellRendererButton;
31 typedef struct _PsppireCellRendererButtonClass PsppireCellRendererButtonClass;
32
33 struct _PsppireCellRendererButton {
34 GtkCellRenderer parent;
35
36 gboolean editable;
37 gchar *label;
38 gint border_width;
39 gint xpad;
40 gint ypad;
41
42 gboolean slash;
43
44 GtkWidget *button;
45 guint32 click_time;
46 gdouble click_x;
47 gdouble click_y;
48
49 /* Style caching. */
50 GtkStyle *button_style;
51 GtkStyle *label_style;
52 GtkWidget *base;
53 gulong style_set_handler;
54 gulong destroy_handler;
55 };
56
57 struct _PsppireCellRendererButtonClass {
58 GtkCellRendererClass parent_class;
59 };
60
61 GType psppire_cell_renderer_button_get_type (void) G_GNUC_CONST;
62 GtkCellRenderer* psppire_cell_renderer_button_new (void);
63
64 void psppire_cell_renderer_button_set_slash (PsppireCellRendererButton *,
65 gboolean slash);
66 gboolean psppire_cell_renderer_button_get_slash (const PsppireCellRendererButton *);
67
68 G_END_DECLS
69
70 #endif /* PSPPIRE_CELL_RENDERER_BUTTON_H */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
336336
337337
338338 static void
339 delete_variable_callback (PsppireDict *dict, gint posn,
340 gint x UNUSED, gint y UNUSED, gpointer data)
339 delete_variable_callback (PsppireDict *dict,
340 const struct variable *var UNUSED,
341 gint dict_idx, gint case_idx UNUSED, gpointer data)
341342 {
342343 PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
343344
344345 PsppireAxis *var_vaxis;
345346 g_object_get (de->var_sheet, "vertical-axis", &var_vaxis, NULL);
346347
347 psppire_axis_delete (var_vaxis, posn, 1);
348
349 psppire_axis_delete (de->haxis, posn, 1);
348 psppire_axis_delete (var_vaxis, dict_idx, 1);
349
350 psppire_axis_delete (de->haxis, dict_idx, 1);
350351 }
351352
352353
14341435 psppire_data_editor_set_font (PsppireDataEditor *de, PangoFontDescription *font_desc)
14351436 {
14361437 set_font (GTK_WIDGET (de), font_desc);
1437 gtk_container_foreach (GTK_CONTAINER (de), set_font, font_desc);
14381438 }
14391439
14401440
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2006, 2008, 2009, 2010 Free Software Foundation
1 Copyright (C) 2006, 2008, 2009, 2010, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
238238 static void
239239 psppire_data_store_init (PsppireDataStore *data_store)
240240 {
241 data_store->dict = 0;
241 data_store->dict = NULL;
242242 data_store->datasheet = NULL;
243243 data_store->dispose_has_run = FALSE;
244244 }
300300 A callback which occurs after a variable has been deleted.
301301 */
302302 static void
303 delete_variable_callback (GObject *obj, gint dict_index,
304 gint case_index, gint width,
303 delete_variable_callback (GObject *obj, const struct variable *var UNUSED,
304 gint dict_index, gint case_index,
305305 gpointer data)
306306 {
307307 PsppireDataStore *store = PSPPIRE_DATA_STORE (data);
418418 {
419419 PsppireDataStore *retval;
420420
421 retval = g_object_new (GTK_TYPE_DATA_STORE, NULL);
421 retval = g_object_new (PSPPIRE_TYPE_DATA_STORE, NULL);
422422
423423 psppire_data_store_set_dictionary (retval, dict);
424424
2323
2424 G_BEGIN_DECLS
2525
26 #define GTK_TYPE_DATA_STORE (psppire_data_store_get_type ())
26 #define PSPPIRE_TYPE_DATA_STORE (psppire_data_store_get_type ())
2727
2828 #define PSPPIRE_DATA_STORE(obj) \
29 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
30 GTK_TYPE_DATA_STORE, PsppireDataStore))
29 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
30 PSPPIRE_TYPE_DATA_STORE, PsppireDataStore))
3131
3232 #define PSPPIRE_DATA_STORE_CLASS(klass) \
33 (G_TYPE_CHECK_CLASS_CAST ((klass), \
34 GTK_TYPE_DATA_STORE, \
35 PsppireDataStoreClass))
33 (G_TYPE_CHECK_CLASS_CAST ((klass), \
34 PSPPIRE_TYPE_DATA_STORE, \
35 PsppireDataStoreClass))
3636
3737
3838 #define PSPPIRE_IS_DATA_STORE(obj) \
39 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DATA_STORE))
39 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DATA_STORE))
4040
4141 #define PSPPIRE_IS_DATA_STORE_CLASS(klass) \
42 (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DATA_STORE))
42 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DATA_STORE))
4343
4444 #define PSPPIRE_DATA_STORE_GET_CLASS(obj) \
45 (G_TYPE_INSTANCE_GET_CLASS ((obj), \
46 GTK_TYPE_DATA_STORE, \
47 PsppireDataStoreClass))
45 (G_TYPE_INSTANCE_GET_CLASS ((obj), \
46 PSPPIRE_TYPE_DATA_STORE, \
47 PsppireDataStoreClass))
4848
4949 typedef struct _PsppireDataStore PsppireDataStore;
5050 typedef struct _PsppireDataStoreClass PsppireDataStoreClass;
3333 #include "ui/gui/count-dialog.h"
3434 #include "ui/gui/crosstabs-dialog.h"
3535 #include "ui/gui/entry-dialog.h"
36 #include "ui/gui/examine-dialog.h"
3736 #include "ui/gui/executor.h"
38 #include "ui/gui/factor-dialog.h"
3937 #include "ui/gui/find-dialog.h"
4038 #include "ui/gui/frequencies-dialog.h"
4139 #include "ui/gui/goto-case-dialog.h"
4947 #include "ui/gui/psppire-syntax-window.h"
5048 #include "ui/gui/psppire-window.h"
5149 #include "ui/gui/psppire.h"
52 #include "ui/gui/rank-dialog.h"
5350 #include "ui/gui/runs-dialog.h"
5451 #include "ui/gui/ks-one-sample-dialog.h"
5552 #include "ui/gui/recode-dialog.h"
56 #include "ui/gui/regression-dialog.h"
5753 #include "ui/gui/select-cases-dialog.h"
5854 #include "ui/gui/split-file-dialog.h"
59 #include "ui/gui/t-test-independent-samples-dialog.h"
6055 #include "ui/gui/t-test-one-sample.h"
6156 #include "ui/gui/t-test-paired-samples.h"
6257 #include "ui/gui/text-data-import-dialog.h"
10591054
10601055
10611056 connect_action (de, "data_transpose", G_CALLBACK (transpose_dialog));
1062
10631057 connect_action (de, "data_select-cases", G_CALLBACK (select_cases_dialog));
1064
10651058 connect_action (de, "data_aggregate", G_CALLBACK (aggregate_dialog));
1066
10671059 connect_action (de, "transform_compute", G_CALLBACK (compute_dialog));
1068
10691060 connect_action (de, "transform_autorecode", G_CALLBACK (autorecode_dialog));
1070
10711061 connect_action (de, "edit_find", G_CALLBACK (find_dialog));
1072
10731062 connect_action (de, "data_split-file", G_CALLBACK (split_file_dialog));
1074
10751063 connect_action (de, "data_weight-cases", G_CALLBACK (weight_cases_dialog));
1076
10771064 connect_action (de, "oneway-anova", G_CALLBACK (oneway_anova_dialog));
1078
1079 connect_action (de, "indep-t-test", G_CALLBACK (t_test_independent_samples_dialog));
1080
10811065 connect_action (de, "paired-t-test", G_CALLBACK (t_test_paired_samples_dialog));
1082
10831066 connect_action (de, "one-sample-t-test", G_CALLBACK (t_test_one_sample_dialog));
1084
10851067 connect_action (de, "utilities_comments", G_CALLBACK (comments_dialog));
1086
1087 connect_action (de, "transform_rank", G_CALLBACK (rank_dialog));
1088
10891068 connect_action (de, "transform_count", G_CALLBACK (count_dialog));
1090
10911069 connect_action (de, "transform_recode-same", G_CALLBACK (recode_same_dialog));
1092
10931070 connect_action (de, "transform_recode-different", G_CALLBACK (recode_different_dialog));
1094
10951071 connect_action (de, "analyze_frequencies", G_CALLBACK (frequencies_dialog));
1096
10971072 connect_action (de, "crosstabs", G_CALLBACK (crosstabs_dialog));
1098
1099 connect_action (de, "analyze_explore", G_CALLBACK (examine_dialog));
1100
1101 connect_action (de, "linear-regression", G_CALLBACK (regression_dialog));
1102
11031073 connect_action (de, "univariate", G_CALLBACK (univariate_dialog));
1104
1105 connect_action (de, "factor-analysis", G_CALLBACK (factor_dialog));
1106
11071074 connect_action (de, "chi-square", G_CALLBACK (chisquare_dialog));
11081075 connect_action (de, "binomial", G_CALLBACK (binomial_dialog));
11091076 connect_action (de, "runs", G_CALLBACK (runs_dialog));
11101077 connect_action (de, "ks-one-sample", G_CALLBACK (ks_one_sample_dialog));
11111078 connect_action (de, "k-related-samples", G_CALLBACK (k_related_dialog));
11121079 connect_action (de, "two-related-samples", G_CALLBACK (two_related_dialog));
1113
11141080
11151081 {
11161082 GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (de->builder, "uimanager1", GTK_TYPE_UI_MANAGER));
226226 psppire_dialog_action_set_refresh (pda, dialog_refresh);
227227
228228 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_descriptives_parent_class)->activate (pda);
229
230 g_object_unref (xml);
229231 }
230232
231233 static void
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <config.h>
18
19 #include "psppire-dialog-action-examine.h"
20
21 #include "psppire-var-view.h"
22 #include "dialog-common.h"
23 #include "psppire-selector.h"
24 #include "psppire-dict.h"
25 #include "psppire-dialog.h"
26 #include "builder-wrapper.h"
27
28 #include "gettext.h"
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
31
32 static void psppire_dialog_action_examine_class_init (PsppireDialogActionExamineClass *class);
33
34 G_DEFINE_TYPE (PsppireDialogActionExamine, psppire_dialog_action_examine, PSPPIRE_TYPE_DIALOG_ACTION);
35
36
37 #define STAT_DESCRIPTIVES 0x01
38 #define STAT_EXTREMES 0x02
39 #define STAT_PERCENTILES 0x04
40
41 static void
42 run_stats_dialog (PsppireDialogActionExamine *ed)
43 {
44 gint response;
45
46 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->descriptives_button),
47 ed->stats & STAT_DESCRIPTIVES);
48
49 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->extremes_button),
50 ed->stats & STAT_EXTREMES);
51
52 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->percentiles_button),
53 ed->stats & STAT_PERCENTILES);
54
55 response = psppire_dialog_run (PSPPIRE_DIALOG (ed->stats_dialog));
56
57 if ( response == PSPPIRE_RESPONSE_CONTINUE )
58 {
59 ed->stats = 0;
60 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->descriptives_button) ))
61 ed->stats |= STAT_DESCRIPTIVES;
62
63 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->extremes_button) ))
64 ed->stats |= STAT_EXTREMES;
65
66 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->percentiles_button) ))
67 ed->stats |= STAT_PERCENTILES;
68 }
69 }
70
71 static void
72 run_opts_dialog (PsppireDialogActionExamine *ed)
73 {
74 gint response;
75
76 switch (ed->opts)
77 {
78 case OPT_LISTWISE:
79 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->listwise), TRUE);
80 break;
81 case OPT_PAIRWISE:
82 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->pairwise), TRUE);
83 break;
84 case OPT_REPORT:
85 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ed->report), TRUE);
86 break;
87 default:
88 g_assert_not_reached ();
89 break;
90 };
91
92 response = psppire_dialog_run (PSPPIRE_DIALOG (ed->opts_dialog));
93
94 if ( response == PSPPIRE_RESPONSE_CONTINUE )
95 {
96 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->listwise)))
97 ed->opts = OPT_LISTWISE;
98 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->pairwise)))
99 ed->opts = OPT_PAIRWISE;
100 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ed->report)))
101 ed->opts = OPT_REPORT;
102 }
103 }
104
105
106
107
108 static char *
109 generate_syntax (PsppireDialogAction *act)
110 {
111 PsppireDialogActionExamine *ed = PSPPIRE_DIALOG_ACTION_EXAMINE (act);
112
113 const char *label;
114 gchar *text = NULL;
115 GString *str = g_string_new ("EXAMINE ");
116
117 g_string_append (str, "\n\t/VARIABLES=");
118 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (ed->variables), 0, str);
119
120 if ( 0 < gtk_tree_model_iter_n_children
121 (gtk_tree_view_get_model (GTK_TREE_VIEW (ed->factors)), NULL))
122 {
123 g_string_append (str, "\n\tBY ");
124 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (ed->factors), 0, str);
125 }
126
127 label = gtk_entry_get_text (GTK_ENTRY (ed->id_var));
128 if ( 0 != strcmp (label, "") )
129 {
130 g_string_append (str, "\n\t/ID = ");
131 g_string_append (str, label);
132 }
133
134 if ( ed->stats & (STAT_DESCRIPTIVES | STAT_EXTREMES))
135 {
136 g_string_append (str, "\n\t/STATISTICS =");
137
138 if ( ed->stats & STAT_DESCRIPTIVES)
139 g_string_append (str, " DESCRIPTIVES");
140
141 if ( ed->stats & STAT_EXTREMES)
142 g_string_append (str, " EXTREME");
143 }
144
145 if ( ed->stats & STAT_PERCENTILES)
146 g_string_append (str, "\n\t/PERCENTILES");
147
148
149 g_string_append (str, "\n\t/MISSING=");
150 switch (ed->opts)
151 {
152 case OPT_REPORT:
153 g_string_append (str, "REPORT");
154 break;
155 case OPT_PAIRWISE:
156 g_string_append (str, "PAIRWISE");
157 break;
158 default:
159 g_string_append (str, "LISTWISE");
160 break;
161 };
162
163 g_string_append (str, ".");
164 text = str->str;
165
166 g_string_free (str, FALSE);
167
168 return text;
169 }
170
171 static gboolean
172 dialog_state_valid (PsppireDialogAction *da)
173 {
174 PsppireDialogActionExamine *pae = PSPPIRE_DIALOG_ACTION_EXAMINE (da);
175 GtkTreeIter notused;
176 GtkTreeModel *vars =
177 gtk_tree_view_get_model (GTK_TREE_VIEW (pae->variables));
178
179 return gtk_tree_model_get_iter_first (vars, &notused);
180 }
181
182 static void
183 dialog_refresh (PsppireDialogAction *da)
184 {
185 PsppireDialogActionExamine *dae = PSPPIRE_DIALOG_ACTION_EXAMINE (da);
186 GtkTreeModel *liststore = NULL;
187
188 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (dae->variables));
189 gtk_list_store_clear (GTK_LIST_STORE (liststore));
190
191 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (dae->factors));
192 gtk_list_store_clear (GTK_LIST_STORE (liststore));
193
194 gtk_entry_set_text (GTK_ENTRY (dae->id_var), "");
195 dae->stats = 0x00;
196 dae->opts = OPT_LISTWISE;
197 }
198
199 static void
200 psppire_dialog_action_examine_activate (GtkAction *a)
201 {
202 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
203 PsppireDialogActionExamine *act = PSPPIRE_DIALOG_ACTION_EXAMINE (a);
204
205 GtkBuilder *xml = builder_new ("examine.ui");
206
207 GtkWidget *stats_button = get_widget_assert (xml, "stats-button");
208 GtkWidget *opts_button = get_widget_assert (xml, "opts-button");
209
210 GtkWidget *dep_sel = get_widget_assert (xml, "psppire-selector1");
211
212 pda->dialog = get_widget_assert (xml, "examine-dialog");
213 pda->source = get_widget_assert (xml, "treeview1");
214 act->variables = get_widget_assert (xml, "treeview2");
215 act->factors = get_widget_assert (xml, "treeview3");
216 act->id_var = get_widget_assert (xml, "entry1");
217
218 act->stats_dialog = get_widget_assert (xml, "statistics-dialog");
219 act->descriptives_button = get_widget_assert (xml, "descriptives-button");
220 act->extremes_button = get_widget_assert (xml, "extremes-button");
221 act->percentiles_button = get_widget_assert (xml, "percentiles-button");
222
223 act->opts_dialog = get_widget_assert (xml, "options-dialog");
224 act->listwise = get_widget_assert (xml, "radiobutton1");
225 act->pairwise = get_widget_assert (xml, "radiobutton2");
226 act->report = get_widget_assert (xml, "radiobutton3");
227
228 g_object_set (pda->source,
229 "model", pda->dict,
230 NULL);
231
232 psppire_selector_set_allow (PSPPIRE_SELECTOR (dep_sel), numeric_only);
233
234 psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid);
235 psppire_dialog_action_set_refresh (pda, dialog_refresh);
236
237 g_signal_connect_swapped (stats_button, "clicked",
238 G_CALLBACK (run_stats_dialog), act);
239
240 g_signal_connect_swapped (opts_button, "clicked",
241 G_CALLBACK (run_opts_dialog), act);
242
243 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_examine_parent_class)->activate (pda);
244
245 g_object_unref (xml);
246 }
247
248 static void
249 psppire_dialog_action_examine_class_init (PsppireDialogActionExamineClass *class)
250 {
251 GTK_ACTION_CLASS (class)->activate = psppire_dialog_action_examine_activate;
252
253 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
254 }
255
256 static void
257 psppire_dialog_action_examine_init (PsppireDialogActionExamine *act)
258 {
259 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #ifndef __PSPPIRE_DIALOG_ACTION_EXAMINE_H__
18 #define __PSPPIRE_DIALOG_ACTION_EXAMINE_H__
19
20 #include <glib-object.h>
21 #include <glib.h>
22
23 #include "psppire-dialog-action.h"
24
25 G_BEGIN_DECLS
26
27
28 #define PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE (psppire_dialog_action_examine_get_type ())
29
30 #define PSPPIRE_DIALOG_ACTION_EXAMINE(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE, PsppireDialogActionExamine))
33
34 #define PSPPIRE_DIALOG_ACTION_EXAMINE_CLASS(klass) \
35 (G_TYPE_CHECK_CLASS_CAST ((klass), \
36 PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE, \
37 PsppireDialogActionExamineClass))
38
39
40 #define PSPPIRE_IS_DIALOG_ACTION_EXAMINE(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE))
42
43 #define PSPPIRE_IS_DIALOG_ACTION_EXAMINE_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE))
45
46
47 #define PSPPIRE_DIALOG_ACTION_EXAMINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
48 PSPPIRE_TYPE_DIALOG_ACTION_EXAMINE, \
49 PsppireDialogActionExamineClass))
50
51 typedef struct _PsppireDialogActionExamine PsppireDialogActionExamine;
52 typedef struct _PsppireDialogActionExamineClass PsppireDialogActionExamineClass;
53
54
55 enum PsppireDialogActionExamineOpts
56 {
57 OPT_LISTWISE,
58 OPT_PAIRWISE,
59 OPT_REPORT
60 };
61
62 struct _PsppireDialogActionExamine
63 {
64 PsppireDialogAction parent;
65
66 /*< private >*/
67 GtkWidget *variables;
68 GtkWidget *factors;
69 GtkWidget *id_var;
70
71 /* The stats dialog */
72 GtkWidget *stats_dialog;
73 GtkWidget *descriptives_button;
74 GtkWidget *extremes_button;
75 GtkWidget *percentiles_button;
76 guint stats;
77
78 /* The options dialog */
79 GtkWidget *opts_dialog;
80 GtkWidget *listwise;
81 GtkWidget *pairwise;
82 GtkWidget *report;
83 enum PsppireDialogActionExamineOpts opts;
84 };
85
86
87 struct _PsppireDialogActionExamineClass
88 {
89 PsppireDialogActionClass parent_class;
90 };
91
92
93 GType psppire_dialog_action_examine_get_type (void) ;
94
95 G_END_DECLS
96
97 #endif /* __PSPPIRE_DIALOG_ACTION_EXAMINE_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <config.h>
18
19 #include "psppire-dialog-action-factor.h"
20
21 #include "psppire-var-view.h"
22 #include "dialog-common.h"
23 #include "psppire-selector.h"
24 #include "psppire-dict.h"
25 #include "psppire-dialog.h"
26 #include "builder-wrapper.h"
27 #include "psppire-scanf.h"
28
29 #include "gettext.h"
30 #define _(msgid) gettext (msgid)
31 #define N_(msgid) msgid
32
33 static void psppire_dialog_action_factor_class_init (PsppireDialogActionFactorClass *class);
34
35 G_DEFINE_TYPE (PsppireDialogActionFactor, psppire_dialog_action_factor, PSPPIRE_TYPE_DIALOG_ACTION);
36
37 static const char *rot_method_syntax[] =
38 {
39 "NOROTATE",
40 "VARIMAX",
41 "QUARTIMAX",
42 "EQUAMAX"
43 };
44
45 static void
46 on_extract_toggle (GtkToggleButton *button, PsppireDialogActionFactor *f)
47 {
48 gboolean active = gtk_toggle_button_get_active (button);
49
50 gtk_widget_set_sensitive (GTK_WIDGET (f->n_factors), active);
51 gtk_widget_set_sensitive (GTK_WIDGET (f->mineigen), ! active);
52 }
53
54 static char *
55 generate_syntax (PsppireDialogAction *act)
56 {
57 PsppireDialogActionFactor *rd = PSPPIRE_DIALOG_ACTION_FACTOR (act);
58
59 gchar *text = NULL;
60 GString *string = g_string_new ("FACTOR ");
61
62 g_string_append (string, "\n\t/VARIABLES=");
63
64 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->variables), 0, string);
65
66
67 g_string_append (string, "\n\t/CRITERIA = ");
68 if ( rd->extraction.explicit_nfactors )
69 g_string_append_printf (string, "FACTORS (%d)", rd->extraction.n_factors);
70 else
71 g_string_append_printf (string, "MINEIGEN (%g)", rd->extraction.mineigen);
72
73 /*
74 The CRITERIA = ITERATE subcommand is overloaded.
75 It applies to the next /ROTATION and/or EXTRACTION command whatever comes first.
76 */
77 g_string_append_printf (string, " ITERATE (%d)", rd->extraction.n_iterations);
78
79
80 g_string_append (string, "\n\t/EXTRACTION =");
81 if ( rd->extraction.paf)
82 g_string_append (string, "PAF");
83 else
84 g_string_append (string, "PC");
85
86
87 g_string_append (string, "\n\t/METHOD = ");
88 if ( rd->extraction.covariance )
89 g_string_append (string, "COVARIANCE");
90 else
91 g_string_append (string, "CORRELATION");
92
93
94
95 if ( rd->extraction.scree )
96 {
97 g_string_append (string, "\n\t/PLOT = ");
98 g_string_append (string, "EIGEN");
99 }
100
101 g_string_append (string, "\n\t/PRINT = ");
102 g_string_append (string, "INITIAL ");
103
104 if ( rd->extraction.unrotated )
105 g_string_append (string, "EXTRACTION ");
106
107 if ( rd->rotation.rotated_solution )
108 g_string_append (string, "ROTATION");
109
110
111 /* The CRITERIA = ITERATE subcommand is overloaded.
112 It applies to the next /ROTATION and/or EXTRACTION command whatever comes first.
113 */
114 g_string_append_printf (string, "\n\t/CRITERIA = ITERATE (%d)", rd->rotation.iterations );
115
116 g_string_append (string, "\n\t/ROTATION = ");
117 g_string_append (string, rot_method_syntax[rd->rotation.method]);
118
119 g_string_append (string, ".");
120 text = string->str;
121
122 g_string_free (string, FALSE);
123
124 return text;
125 }
126
127 static void
128 load_rotation_parameters (PsppireDialogActionFactor *fd, const struct rotation_parameters *p)
129 {
130 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->display_rotated_solution),
131 p->rotated_solution);
132
133 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->rotate_iterations),
134 p->iterations);
135
136 switch (p->method)
137 {
138 case ROT_NONE:
139 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_none), TRUE);
140 break;
141 case ROT_VARIMAX:
142 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_varimax), TRUE);
143 break;
144 case ROT_QUARTIMAX:
145 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_quartimax), TRUE);
146 break;
147 case ROT_EQUIMAX:
148 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->rotation_equimax), TRUE);
149 break;
150 default:
151 g_assert_not_reached ();
152 break;
153 }
154 }
155
156 static void
157 load_extraction_parameters (PsppireDialogActionFactor *fd, const struct extraction_parameters *p)
158 {
159 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->mineigen), p->mineigen);
160 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->n_factors), p->n_factors);
161
162 gtk_spin_button_set_value (GTK_SPIN_BUTTON (fd->extract_iterations), p->n_iterations);
163
164
165 if (p->explicit_nfactors)
166 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->nfactors_toggle), TRUE);
167 else
168 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->mineigen_toggle), TRUE);
169
170 if (p->covariance)
171 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->covariance_toggle), TRUE);
172 else
173 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->correlation_toggle), TRUE);
174
175
176 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->scree_button), p->scree);
177 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fd->unrotated_button), p->unrotated);
178
179 if ( p->paf )
180 gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 1);
181 else
182 gtk_combo_box_set_active (GTK_COMBO_BOX (fd->extraction_combo), 0);
183
184 }
185
186 static gboolean
187 dialog_state_valid (PsppireDialogActionFactor *da)
188 {
189 GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (da->variables));
190
191 if (gtk_tree_model_iter_n_children (liststore, NULL) < 2)
192 return FALSE;
193
194 return TRUE;
195 }
196
197 static const struct extraction_parameters default_extraction_parameters =
198 {1.0, 0, 25, FALSE, TRUE, FALSE, TRUE, FALSE};
199
200 static const struct rotation_parameters default_rotation_parameters =
201 {TRUE, 25, ROT_VARIMAX};
202
203 static void
204 dialog_refresh (PsppireDialogAction *da)
205 {
206 PsppireDialogActionFactor *fd = PSPPIRE_DIALOG_ACTION_FACTOR (da);
207 GtkTreeModel *liststore =
208 gtk_tree_view_get_model (GTK_TREE_VIEW (fd->variables));
209 gtk_list_store_clear (GTK_LIST_STORE (liststore));
210
211 load_extraction_parameters (fd, &default_extraction_parameters);
212 load_rotation_parameters (fd, &default_rotation_parameters);
213 }
214
215
216
217 static void
218 set_rotation_parameters (PsppireDialogActionFactor *act, struct rotation_parameters *p)
219 {
220 p->iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->rotate_iterations));
221 p->rotated_solution = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->display_rotated_solution));
222
223
224 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_none)))
225 p->method = ROT_NONE;
226
227 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_varimax)))
228 p->method = ROT_VARIMAX;
229
230 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_quartimax)))
231 p->method = ROT_QUARTIMAX;
232
233 if ( gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->rotation_equimax)))
234 p->method = ROT_EQUIMAX;
235 }
236
237 static void
238 set_extraction_parameters (PsppireDialogActionFactor *act, struct extraction_parameters *p)
239 {
240 p->mineigen = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->mineigen));
241 p->n_factors = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->n_factors));
242 p->n_iterations = gtk_spin_button_get_value (GTK_SPIN_BUTTON (act->extract_iterations));
243
244 p->explicit_nfactors = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->nfactors_toggle));
245 p->covariance = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->covariance_toggle));
246
247 p->scree = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->scree_button));
248 p->unrotated = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->unrotated_button));
249
250 p->paf = (gtk_combo_box_get_active (GTK_COMBO_BOX (act->extraction_combo)) == 1);
251 }
252
253
254 static void
255 run_extractions_subdialog (PsppireDialogActionFactor *act)
256 {
257 struct extraction_parameters *ex = &act->extraction;
258
259 gint response = psppire_dialog_run (PSPPIRE_DIALOG (act->extraction_dialog));
260
261 if ( response == PSPPIRE_RESPONSE_CONTINUE )
262 {
263 /* Set the parameters from their respective widgets */
264 set_extraction_parameters (act, ex);
265 }
266 else
267 {
268 /* Cancelled. Reset the widgets to their old state */
269 load_extraction_parameters (act, ex);
270 }
271 }
272
273 static void
274 run_rotations_subdialog (PsppireDialogActionFactor *act)
275 {
276 struct rotation_parameters *rot = &act->rotation;
277
278 gint response = psppire_dialog_run (PSPPIRE_DIALOG (act->rotation_dialog));
279
280 if ( response == PSPPIRE_RESPONSE_CONTINUE )
281 {
282 /* Set the parameters from their respective widgets */
283 set_rotation_parameters (act, rot);
284 }
285 else
286 {
287 /* Cancelled. Reset the widgets to their old state */
288 load_rotation_parameters (act, rot);
289 }
290 }
291
292 static void
293 psppire_dialog_action_factor_activate (GtkAction *a)
294 {
295 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
296 PsppireDialogActionFactor *act = PSPPIRE_DIALOG_ACTION_FACTOR (a);
297 GtkWidget *extraction_button ;
298 GtkWidget *rotation_button ;
299
300 GtkBuilder *xml = builder_new ("factor.ui");
301
302 pda->dialog = get_widget_assert (xml, "factor-dialog");
303 pda->source = get_widget_assert (xml, "dict-view");
304
305 extraction_button = get_widget_assert (xml, "button-extractions");
306 rotation_button = get_widget_assert (xml, "button-rotations");
307
308 act->extraction_dialog = get_widget_assert (xml, "extractions-dialog");
309 act->rotation_dialog = get_widget_assert (xml, "rotations-dialog");
310
311 act->variables = get_widget_assert (xml, "psppire-var-view1");
312
313 {
314 GtkWidget *hbox = get_widget_assert (xml, "hbox6");
315 GtkWidget *eigenvalue_extraction ;
316
317 act->mineigen_toggle = get_widget_assert (xml, "mineigen-radiobutton");
318
319 eigenvalue_extraction = psppire_scanf_new (_("_Eigenvalues over %4.2f times the mean eigenvalue"), &act->mineigen);
320
321 g_object_set (eigenvalue_extraction,
322 "use-underline", TRUE,
323 "mnemonic-widget", act->mineigen_toggle,
324 NULL);
325
326 act->nfactors_toggle = get_widget_assert (xml, "nfactors-radiobutton");
327 act->n_factors = get_widget_assert (xml, "spinbutton-nfactors");
328 act->extract_iterations = get_widget_assert (xml, "spinbutton-extract-iterations");
329 act->covariance_toggle = get_widget_assert (xml, "covariance-radiobutton");
330 act->correlation_toggle = get_widget_assert (xml, "correlations-radiobutton");
331
332 act->scree_button = get_widget_assert (xml, "scree-button");
333 act->unrotated_button = get_widget_assert (xml, "unrotated-button");
334 act->extraction_combo = get_widget_assert (xml, "combobox1");
335
336 gtk_container_add (GTK_CONTAINER (hbox), eigenvalue_extraction);
337
338 g_signal_connect (act->nfactors_toggle, "toggled", G_CALLBACK (on_extract_toggle), act);
339
340 gtk_widget_show_all (eigenvalue_extraction);
341 }
342
343 {
344 act->rotate_iterations = get_widget_assert (xml, "spinbutton-rot-iterations");
345
346 act->display_rotated_solution = get_widget_assert (xml, "checkbutton-rotated-solution");
347
348 act->rotation_none = get_widget_assert (xml, "radiobutton-none");
349 act->rotation_varimax = get_widget_assert (xml, "radiobutton-varimax");
350 act->rotation_quartimax = get_widget_assert (xml, "radiobutton-quartimax");
351 act->rotation_equimax = get_widget_assert (xml, "radiobutton-equimax");
352 }
353
354 g_signal_connect_swapped (extraction_button, "clicked",
355 G_CALLBACK (run_extractions_subdialog), act);
356 g_signal_connect_swapped (rotation_button, "clicked", G_CALLBACK (run_rotations_subdialog), act);
357
358
359 psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid);
360 psppire_dialog_action_set_refresh (pda, dialog_refresh);
361
362 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_factor_parent_class)->activate (pda);
363
364 g_object_unref (xml);
365 }
366
367 static void
368 psppire_dialog_action_factor_class_init (PsppireDialogActionFactorClass *class)
369 {
370 GTK_ACTION_CLASS (class)->activate = psppire_dialog_action_factor_activate;
371
372 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
373 }
374
375 static void
376 psppire_dialog_action_factor_init (PsppireDialogActionFactor *act)
377 {
378 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #ifndef __PSPPIRE_DIALOG_ACTION_FACTOR_H__
18 #define __PSPPIRE_DIALOG_ACTION_FACTOR_H__
19
20 #include <glib-object.h>
21 #include <glib.h>
22
23 #include "psppire-dialog-action.h"
24
25 G_BEGIN_DECLS
26
27
28 #define PSPPIRE_TYPE_DIALOG_ACTION_FACTOR (psppire_dialog_action_factor_get_type ())
29
30 #define PSPPIRE_DIALOG_ACTION_FACTOR(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, PsppireDialogActionFactor))
33
34 #define PSPPIRE_DIALOG_ACTION_FACTOR_CLASS(klass) \
35 (G_TYPE_CHECK_CLASS_CAST ((klass), \
36 PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, \
37 PsppireDialogActionFactorClass))
38
39
40 #define PSPPIRE_IS_DIALOG_ACTION_FACTOR(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_FACTOR))
42
43 #define PSPPIRE_IS_DIALOG_ACTION_FACTOR_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_FACTOR))
45
46
47 #define PSPPIRE_DIALOG_ACTION_FACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
48 PSPPIRE_TYPE_DIALOG_ACTION_FACTOR, \
49 PsppireDialogActionFactorClass))
50
51 typedef struct _PsppireDialogActionFactor PsppireDialogActionFactor;
52 typedef struct _PsppireDialogActionFactorClass PsppireDialogActionFactorClass;
53
54
55 enum rotation_type {
56 ROT_NONE,
57 ROT_VARIMAX,
58 ROT_QUARTIMAX,
59 ROT_EQUIMAX
60 };
61
62 struct rotation_parameters
63 {
64 gboolean rotated_solution;
65 gint iterations;
66
67 enum rotation_type method;
68 };
69
70 struct extraction_parameters
71 {
72 gdouble mineigen;
73 gint n_factors;
74 gint n_iterations;
75
76 gboolean explicit_nfactors;
77 gboolean covariance;
78
79 gboolean scree;
80 gboolean unrotated;
81
82 gboolean paf;
83 };
84
85
86 struct _PsppireDialogActionFactor
87 {
88 PsppireDialogAction parent;
89
90 /*< private >*/
91 GtkWidget *variables ;
92
93 /* The Extraction subdialog */
94 GtkWidget *extraction_dialog;
95 GtkWidget *rotation_dialog;
96
97 GtkWidget *n_factors;
98 GtkWidget *mineigen;
99 GtkWidget *extract_iterations;
100
101 GtkWidget *nfactors_toggle;
102 GtkWidget *mineigen_toggle;
103
104 GtkWidget *covariance_toggle;
105 GtkWidget *correlation_toggle;
106
107 GtkWidget *scree_button;
108 GtkWidget *unrotated_button;
109
110 GtkWidget *extraction_combo;
111
112
113 /* Rotation Widgets */
114 GtkWidget *rotate_iterations;
115 GtkWidget *display_rotated_solution;
116 GtkWidget *rotation_none;
117 GtkWidget *rotation_varimax;
118 GtkWidget *rotation_quartimax;
119 GtkWidget *rotation_equimax;
120
121
122 struct extraction_parameters extraction;
123 struct rotation_parameters rotation;
124 };
125
126
127 struct _PsppireDialogActionFactorClass
128 {
129 PsppireDialogActionClass parent_class;
130 };
131
132
133 GType psppire_dialog_action_factor_get_type (void) ;
134
135 G_END_DECLS
136
137 #endif /* __PSPPIRE_DIALOG_ACTION_FACTOR_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <config.h>
18
19 #include "psppire-dialog-action-indep-samps.h"
20 #include "psppire-value-entry.h"
21
22 #include "dialog-common.h"
23 #include <ui/syntax-gen.h>
24 #include "psppire-var-view.h"
25
26 #include "t-test-options.h"
27
28 #include "psppire-dialog.h"
29 #include "builder-wrapper.h"
30
31 #include "psppire-dict.h"
32 #include "libpspp/str.h"
33
34 static void
35 psppire_dialog_action_indep_samps_class_init (PsppireDialogActionIndepSampsClass *class);
36
37 G_DEFINE_TYPE (PsppireDialogActionIndepSamps, psppire_dialog_action_indep_samps, PSPPIRE_TYPE_DIALOG_ACTION);
38
39 static gboolean
40 dialog_state_valid (gpointer data)
41 {
42 PsppireDialogActionIndepSamps *act = PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (data);
43
44 GtkTreeModel *vars = gtk_tree_view_get_model (GTK_TREE_VIEW (act->test_vars_tv));
45
46 GtkTreeIter notused;
47
48 if (NULL == act->grp_var)
49 return FALSE;
50
51 if ( 0 == gtk_tree_model_get_iter_first (vars, &notused))
52 return FALSE;
53
54 if ( act->group_defn == GROUPS_UNDEF)
55 return FALSE;
56
57 return TRUE;
58 }
59
60
61 static void
62 refresh (PsppireDialogAction *da)
63 {
64 PsppireDialogActionIndepSamps *act = PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (da);
65
66 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (act->test_vars_tv));
67
68 act->group_defn = GROUPS_UNDEF;
69
70 if (act->grp_var)
71 {
72 int width = var_get_width (act->grp_var);
73 value_destroy (&act->cut_point, width);
74 value_destroy (&act->grp_val[0], width);
75 value_destroy (&act->grp_val[1], width);
76 act->grp_var = NULL;
77 }
78
79 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[0]), NULL);
80 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[1]), NULL);
81 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_cut_point_entry), NULL);
82
83 gtk_entry_set_text (GTK_ENTRY (act->group_var_entry), "");
84
85 gtk_list_store_clear (GTK_LIST_STORE (model));
86
87 gtk_widget_set_sensitive (act->define_groups_button, FALSE);
88 }
89
90 /* Return TRUE if VE contains a text which is not valid for VAR or if it
91 contains the SYSMIS value */
92 static gboolean
93 value_entry_contains_invalid (PsppireValueEntry *ve, const struct variable *var)
94 {
95 gboolean result = FALSE;
96
97 if (var)
98 {
99 union value val;
100 const int width = var_get_width (var);
101 value_init (&val, width);
102
103 if ( psppire_value_entry_get_value (ve, &val, width))
104 {
105 if (var_is_value_missing (var, &val, MV_SYSTEM))
106 {
107 result = TRUE;
108 }
109 }
110 else
111 result = TRUE;
112
113 value_destroy (&val, width);
114 }
115
116 return result;
117 }
118
119 /* Returns TRUE iff the define groups subdialog has a
120 state which defines a valid group criterion */
121 static gboolean
122 define_groups_state_valid (gpointer data)
123 {
124 PsppireDialogActionIndepSamps *act = data;
125
126 if (gtk_toggle_button_get_active
127 (GTK_TOGGLE_BUTTON (act->dg_values_toggle_button)))
128 {
129 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[0]),
130 act->grp_var))
131 return FALSE;
132
133 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[1]),
134 act->grp_var))
135 return FALSE;
136 }
137 else
138 {
139 if (value_entry_contains_invalid (PSPPIRE_VALUE_ENTRY (act->dg_cut_point_entry),
140 act->grp_var))
141 return FALSE;
142 }
143
144 return TRUE;
145 }
146
147
148 static void
149 run_define_groups (PsppireDialogActionIndepSamps *act)
150 {
151 gint response;
152 PsppireDialogAction *da = PSPPIRE_DIALOG_ACTION (act);
153
154 if ( act->dg_table2->parent)
155 gtk_container_remove (GTK_CONTAINER (act->dg_table2->parent), act->dg_table2);
156
157 if ( act->dg_table1->parent)
158 gtk_container_remove (GTK_CONTAINER (act->dg_table1->parent), act->dg_table1);
159
160
161 if ( var_is_numeric (act->grp_var))
162 {
163 gtk_table_attach_defaults (GTK_TABLE (act->dg_table1), act->dg_table2,
164 1, 2, 1, 2);
165
166 gtk_container_add (GTK_CONTAINER (act->dg_box), act->dg_table1);
167 }
168 else
169 {
170 gtk_container_add (GTK_CONTAINER (act->dg_box), act->dg_table2);
171 act->group_defn = GROUPS_VALUES;
172 }
173
174
175 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (act->dg_dialog),
176 define_groups_state_valid, act);
177
178 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[0]), act->grp_var);
179 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[1]), act->grp_var);
180 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->dg_cut_point_entry), act->grp_var);
181
182 if ( act->group_defn != GROUPS_CUT_POINT )
183 {
184 gtk_toggle_button_set_active
185 (GTK_TOGGLE_BUTTON (act->dg_cut_point_toggle_button), TRUE);
186
187 gtk_toggle_button_set_active
188 (GTK_TOGGLE_BUTTON (act->dg_values_toggle_button), TRUE);
189 }
190 else
191 {
192 gtk_toggle_button_set_active
193 (GTK_TOGGLE_BUTTON (act->dg_values_toggle_button), TRUE);
194
195 gtk_toggle_button_set_active
196 (GTK_TOGGLE_BUTTON (act->dg_cut_point_toggle_button), TRUE);
197 }
198
199 g_signal_emit_by_name (act->dg_grp_entry[0], "changed");
200 g_signal_emit_by_name (act->dg_grp_entry[1], "changed");
201 g_signal_emit_by_name (act->dg_cut_point_entry, "changed");
202
203 response = psppire_dialog_run (PSPPIRE_DIALOG (act->def_grps_dialog));
204
205 if (response == PSPPIRE_RESPONSE_CONTINUE)
206 {
207 const int width = var_get_width (act->grp_var);
208
209 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (act->dg_values_toggle_button)))
210 {
211 act->group_defn = GROUPS_VALUES;
212
213 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[0]),
214 &act->grp_val[0], width);
215
216 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act->dg_grp_entry[1]),
217 &act->grp_val[1], width);
218 }
219 else
220 {
221 act->group_defn = GROUPS_CUT_POINT;
222
223 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (act->dg_cut_point_entry),
224 &act->cut_point, width);
225 }
226
227 psppire_dialog_notify_change (PSPPIRE_DIALOG (da->dialog));
228 }
229 }
230
231 /* Called whenever the group variable entry widget's contents change */
232 static void
233 on_grp_var_change (GtkEntry *entry, PsppireDialogActionIndepSamps *act)
234 {
235 PsppireDialogAction *da = PSPPIRE_DIALOG_ACTION (act);
236 const gchar *text = gtk_entry_get_text (entry);
237
238 const struct variable *v = psppire_dict_lookup_var (da->dict, text);
239
240 gtk_widget_set_sensitive (act->define_groups_button, v != NULL);
241
242 if (act->grp_var)
243 {
244 int width = var_get_width (act->grp_var);
245 value_destroy (&act->cut_point, width);
246 value_destroy (&act->grp_val[0], width);
247 value_destroy (&act->grp_val[1], width);
248 }
249
250 if (v)
251 {
252 const int width = var_get_width (v);
253 value_init (&act->cut_point, width);
254 value_init (&act->grp_val[0], width);
255 value_init (&act->grp_val[1], width);
256
257 if (width == 0)
258 {
259 act->cut_point.f = SYSMIS;
260 act->grp_val[0].f = SYSMIS;
261 act->grp_val[1].f = SYSMIS;
262 }
263 else
264 {
265 act->cut_point.short_string[0] = '\0';
266 act->grp_val[0].short_string[0] = '\0';
267 act->grp_val[1].short_string[0] = '\0';
268 }
269 }
270
271 act->grp_var = v;
272 }
273
274 static void
275 set_group_criterion_type (GtkToggleButton *button,
276 PsppireDialogActionIndepSamps *act)
277 {
278 gboolean by_values = gtk_toggle_button_get_active (button);
279
280 gtk_widget_set_sensitive (act->dg_label, by_values);
281 gtk_widget_set_sensitive (act->dg_table2, by_values);
282
283 gtk_widget_set_sensitive (act->dg_hbox1, !by_values);
284 }
285
286
287 static void
288 psppire_dialog_action_indep_samps_activate (GtkAction *a)
289 {
290 PsppireDialogActionIndepSamps *act = PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (a);
291 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
292
293 GtkBuilder *xml = builder_new ("indep-samples.ui");
294
295 pda->dialog = get_widget_assert (xml,"independent-samples-dialog");
296 pda->source = get_widget_assert (xml, "indep-samples-treeview1");
297 act->define_groups_button = get_widget_assert (xml, "define-groups-button");
298 act->options_button = get_widget_assert (xml, "indep-samples-options-button");
299
300 act->def_grps_dialog = get_widget_assert (xml, "define-groups-dialog");
301 act->group_var_entry = get_widget_assert (xml, "indep-samples-entry");
302 act->test_vars_tv = get_widget_assert (xml, "indep-samples-treeview2");
303
304 act->dg_dialog = get_widget_assert (xml, "define-groups-dialog");
305 act->dg_grp_entry[0] = get_widget_assert (xml, "group1-entry");
306 act->dg_grp_entry[1] = get_widget_assert (xml, "group2-entry");
307 act->dg_cut_point_entry = get_widget_assert (xml, "cut-point-entry");
308 act->dg_box = get_widget_assert (xml, "dialog-hbox2");
309
310 act->dg_table1 = get_widget_assert (xml, "table1");
311 act->dg_table2 = get_widget_assert (xml, "table2");
312 act->dg_label = get_widget_assert (xml, "label4");
313 act->dg_hbox1 = get_widget_assert (xml, "hbox1");
314 act->dg_values_toggle_button = get_widget_assert (xml, "radiobutton3");
315 act->dg_cut_point_toggle_button = get_widget_assert (xml, "radiobutton4");
316
317 act->opts = tt_options_dialog_create (GTK_WINDOW (pda->toplevel));
318
319 g_object_ref (act->dg_table1);
320 g_object_ref (act->dg_table2);
321
322 g_signal_connect (act->dg_values_toggle_button, "toggled",
323 G_CALLBACK (set_group_criterion_type), act);
324
325
326 g_object_unref (xml);
327
328 psppire_dialog_action_set_refresh (pda, refresh);
329
330 psppire_dialog_action_set_valid_predicate (pda,
331 dialog_state_valid);
332
333 g_signal_connect_swapped (act->define_groups_button, "clicked",
334 G_CALLBACK (run_define_groups), act);
335
336 g_signal_connect_swapped (act->options_button, "clicked",
337 G_CALLBACK (tt_options_dialog_run), act->opts);
338
339
340 g_signal_connect (act->group_var_entry, "changed",
341 G_CALLBACK (on_grp_var_change), act);
342
343 if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_indep_samps_parent_class)->activate)
344 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_indep_samps_parent_class)->activate (pda);
345 }
346
347
348
349 static char *
350 generate_syntax (PsppireDialogAction *a)
351 {
352 PsppireDialogActionIndepSamps *act = PSPPIRE_DIALOG_ACTION_INDEP_SAMPS (a);
353 gchar *text;
354
355 GString *str = g_string_new ("T-TEST /VARIABLES=");
356
357 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (act->test_vars_tv), 0, str);
358
359 g_string_append (str, "\n\t/GROUPS=");
360
361 g_string_append (str, var_get_name (act->grp_var));
362
363 if (act->group_defn != GROUPS_UNDEF)
364 {
365 g_string_append (str, "(");
366
367 {
368 const union value *val =
369 (act->group_defn == GROUPS_VALUES) ?
370 &act->grp_val[0] :
371 &act->cut_point;
372
373 struct string strx;
374 ds_init_empty (&strx);
375 syntax_gen_value (&strx, val, var_get_width (act->grp_var),
376 var_get_print_format (act->grp_var));
377
378 g_string_append (str, ds_cstr (&strx));
379 ds_destroy (&strx);
380 }
381
382 if (act->group_defn == GROUPS_VALUES)
383 {
384 g_string_append (str, ",");
385
386 {
387 struct string strx;
388 ds_init_empty (&strx);
389
390 syntax_gen_value (&strx, &act->grp_val[1], var_get_width (act->grp_var),
391 var_get_print_format (act->grp_var));
392
393 g_string_append (str, ds_cstr (&strx));
394 ds_destroy (&strx);
395 }
396 }
397
398 g_string_append (str, ")");
399 }
400
401 tt_options_dialog_append_syntax (act->opts, str);
402
403 g_string_append (str, ".\n");
404
405 text = str->str;
406
407 g_string_free (str, FALSE);
408
409 return text;
410 }
411
412 static void
413 psppire_dialog_action_indep_samps_class_init (PsppireDialogActionIndepSampsClass *class)
414 {
415 GtkActionClass *action_class = GTK_ACTION_CLASS (class);
416
417 action_class->activate = psppire_dialog_action_indep_samps_activate;
418
419 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
420 }
421
422
423 static void
424 psppire_dialog_action_indep_samps_init (PsppireDialogActionIndepSamps *act)
425 {
426 act->grp_var = NULL;
427 act->group_defn = GROUPS_UNDEF;
428 }
429
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <glib-object.h>
18 #include <glib.h>
19
20 #include "psppire-dialog-action.h"
21
22 #ifndef __PSPPIRE_DIALOG_ACTION_INDEP_SAMPS_H__
23 #define __PSPPIRE_DIALOG_ACTION_INDEP_SAMPS_H__
24
25 G_BEGIN_DECLS
26
27
28 #define PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS (psppire_dialog_action_indep_samps_get_type ())
29
30 #define PSPPIRE_DIALOG_ACTION_INDEP_SAMPS(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS, PsppireDialogActionIndepSamps))
33
34 #define PSPPIRE_DIALOG_ACTION_INDEP_SAMPS_CLASS(klass) \
35 (G_TYPE_CHECK_CLASS_CAST ((klass), \
36 PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS, \
37 PsppireDialogActionIndepSampsClass))
38
39
40 #define PSPPIRE_IS_DIALOG_ACTION_INDEP_SAMPS(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS))
42
43 #define PSPPIRE_IS_DIALOG_ACTION_INDEP_SAMPS_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS))
45
46
47 #define PSPPIRE_DIALOG_ACTION_INDEP_SAMPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
48 PSPPIRE_TYPE_DIALOG_ACTION_INDEP_SAMPS, \
49 PsppireDialogActionIndepSampsClass))
50
51 typedef struct _PsppireDialogActionIndepSamps PsppireDialogActionIndepSamps;
52 typedef struct _PsppireDialogActionIndepSampsClass PsppireDialogActionIndepSampsClass;
53
54
55 enum group_definition
56 {
57 GROUPS_UNDEF,
58 GROUPS_VALUES,
59 GROUPS_CUT_POINT
60 };
61
62 struct tt_options_dialog;
63
64 struct _PsppireDialogActionIndepSamps
65 {
66 PsppireDialogAction parent;
67
68 /*< private >*/
69 gboolean dispose_has_run ;
70
71 GtkWidget *test_vars_tv;
72 GtkWidget *def_grps_dialog;
73 GtkWidget *define_groups_button;
74 GtkWidget *options_button;
75
76 /* The variable which determines to which group a datum belongs */
77 const struct variable *grp_var;
78
79 /* The GtkEntry which holds the reference to the above variable */
80 GtkWidget *group_var_entry;
81
82 /* The define groups subdialog */
83 GtkWidget *dg_dialog;
84 GtkWidget *dg_label;
85 GtkWidget *dg_table1;
86 GtkWidget *dg_table2;
87 GtkWidget *dg_hbox1;
88 GtkWidget *dg_box;
89
90 GtkWidget *dg_values_toggle_button;
91 GtkWidget *dg_cut_point_toggle_button;
92
93 GtkWidget *dg_grp_entry[2];
94 GtkWidget *dg_cut_point_entry;
95
96 enum group_definition group_defn;
97
98 union value grp_val[2];
99 union value cut_point;
100
101 /* The options dialog */
102 struct tt_options_dialog *opts;
103 };
104
105
106 struct _PsppireDialogActionIndepSampsClass
107 {
108 PsppireDialogActionClass parent_class;
109 };
110
111
112 GType psppire_dialog_action_indep_samps_get_type (void) ;
113
114 G_END_DECLS
115
116 #endif /* __PSPPIRE_DIALOG_ACTION_INDEP_SAMPS_H__ */
119119 psppire_dialog_action_set_refresh (pda, dialog_refresh);
120120
121121 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_means_parent_class)->activate (pda);
122
123 g_object_unref (xml);
122124 }
123125
124126 static void
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <config.h>
18
19 #include "psppire-dialog-action-rank.h"
20
21 #include "psppire-var-view.h"
22 #include "dialog-common.h"
23 #include "psppire-selector.h"
24 #include "psppire-dict.h"
25 #include "psppire-dialog.h"
26 #include "builder-wrapper.h"
27
28 #include "gettext.h"
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
31
32 static void psppire_dialog_action_rank_class_init (PsppireDialogActionRankClass *class);
33
34 G_DEFINE_TYPE (PsppireDialogActionRank, psppire_dialog_action_rank, PSPPIRE_TYPE_DIALOG_ACTION);
35
36
37 static char *
38 generate_syntax (PsppireDialogAction *act)
39 {
40 PsppireDialogActionRank *rd = PSPPIRE_DIALOG_ACTION_RANK (act);
41
42 gchar *text = NULL;
43 GtkTreeModel *gs = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->group_vars));
44
45 GtkTreeIter notused;
46
47 GString *str = g_string_new ("RANK VARIABLES=");
48
49 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->rank_vars), 0, str);
50
51 g_string_append_printf (str, " (%c)",
52 gtk_toggle_button_get_active (rd->ascending_togglebutton)
53 ?'A':'D');
54
55 if ( gtk_tree_model_get_iter_first (gs, &notused) )
56 {
57 g_string_append (str, "\n\tBY ");
58
59 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->group_vars), 0, str);
60 }
61
62 g_string_append (str, "\n\t/PRINT = ");
63 if (gtk_toggle_button_get_active (rd->summary_togglebutton))
64 g_string_append (str, "YES");
65 else
66 g_string_append (str, "NO");
67
68
69 if (gtk_toggle_button_get_active (rd->func_button [RANK]))
70 g_string_append (str, "\n\t/RANK");
71 if (gtk_toggle_button_get_active (rd->func_button [NORMAL]))
72 g_string_append (str, "\n\t/NORMAL");
73 if (gtk_toggle_button_get_active (rd->func_button [PROPORTION]))
74 g_string_append (str, "\n\t/PROPORTION");
75 if (gtk_toggle_button_get_active (rd->func_button [PERCENT]))
76 g_string_append (str, "\n\t/PERCENT");
77 if (gtk_toggle_button_get_active (rd->func_button [RFRACTION]))
78 g_string_append (str, "\n\t/RFRACTION");
79 if (gtk_toggle_button_get_active (rd->func_button [N]))
80 g_string_append (str, "\n\t/N");
81 if (gtk_toggle_button_get_active (rd->func_button [SAVAGE]))
82 g_string_append (str, "\n\t/SAVAGE");
83 if (gtk_toggle_button_get_active (rd->func_button [NTILES]))
84 {
85 gint n = gtk_spin_button_get_value (GTK_SPIN_BUTTON (rd->ntiles_entry));
86 g_string_append_printf (str, "\n\t/NTILES(%d)", n);
87 }
88
89
90 if (gtk_toggle_button_get_active (rd->func_button [NORMAL])
91 ||
92 gtk_toggle_button_get_active (rd->func_button [PROPORTION]))
93 {
94 g_string_append (str, "\n\t/FRACTION=");
95
96 if ( gtk_toggle_button_get_active (rd->blom))
97 g_string_append (str, "BLOM");
98 else if ( gtk_toggle_button_get_active (rd->tukey))
99 g_string_append (str, "TUKEY");
100 else if ( gtk_toggle_button_get_active (rd->rankit))
101 g_string_append (str, "RANKIT");
102 else if ( gtk_toggle_button_get_active (rd->vw))
103 g_string_append (str, "VW");
104 }
105
106 g_string_append (str, "\n\t/TIES=");
107 if ( gtk_toggle_button_get_active (rd->mean))
108 g_string_append (str, "MEAN");
109 else if ( gtk_toggle_button_get_active (rd->low))
110 g_string_append (str, "LOW");
111 else if ( gtk_toggle_button_get_active (rd->high))
112 g_string_append (str, "HIGH");
113 else if ( gtk_toggle_button_get_active (rd->condense))
114 g_string_append (str, "CONDENSE");
115
116
117 g_string_append (str, ".");
118 text = str->str;
119
120 g_string_free (str, FALSE);
121
122 return text;
123 }
124
125 static gboolean
126 dialog_state_valid (PsppireDialogAction *da)
127 {
128 PsppireDialogActionRank *dar = PSPPIRE_DIALOG_ACTION_RANK (da);
129 GtkTreeIter notused;
130 GtkTreeModel *vars = gtk_tree_view_get_model (GTK_TREE_VIEW (dar->rank_vars));
131
132 return gtk_tree_model_get_iter_first (vars, &notused);
133 }
134
135 static void
136 dialog_refresh (PsppireDialogAction *act)
137 {
138 PsppireDialogActionRank *dar = PSPPIRE_DIALOG_ACTION_RANK (act);
139
140 GtkTreeModel *liststore;
141
142 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (dar->rank_vars));
143 gtk_list_store_clear (GTK_LIST_STORE (liststore));
144
145 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (dar->group_vars));
146 gtk_list_store_clear (GTK_LIST_STORE (liststore));
147
148 gtk_toggle_button_set_active (dar->ascending_togglebutton, TRUE);
149 gtk_toggle_button_set_active (dar->summary_togglebutton, FALSE);
150 }
151
152 static void
153 types_dialog_reset (PsppireDialogActionRank *rd)
154 {
155 gint i;
156
157 for (i = 0 ; i < n_RANK_FUNCS ; ++i )
158 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->func_button [i]),
159 FALSE);
160
161 gtk_widget_set_sensitive (rd->ntiles_entry, FALSE);
162
163 gtk_widget_set_sensitive (rd->formula_box, FALSE);
164 }
165
166 static void
167 run_types_dialog (GtkButton *b, PsppireDialogActionRank *dar)
168 {
169 PsppireDialogAction *act = PSPPIRE_DIALOG_ACTION (dar);
170
171 gint response;
172
173 gtk_window_set_transient_for (GTK_WINDOW (dar->types_dialog),
174 GTK_WINDOW (act->dialog));
175
176 types_dialog_reset (dar);
177
178 response = psppire_dialog_run (PSPPIRE_DIALOG (dar->types_dialog));
179 }
180
181 static void
182 run_ties_dialog (GtkButton *b, PsppireDialogActionRank *dar)
183 {
184 PsppireDialogAction *act = PSPPIRE_DIALOG_ACTION (dar);
185
186 gint response;
187
188 gtk_window_set_transient_for (GTK_WINDOW (dar->ties_dialog),
189 GTK_WINDOW (act->dialog));
190
191 response = psppire_dialog_run (PSPPIRE_DIALOG (dar->ties_dialog));
192 }
193
194 static void
195 on_ntiles_toggle (GtkToggleButton *toggle_button, PsppireDialogActionRank *dar)
196 {
197 gboolean active = gtk_toggle_button_get_active (toggle_button);
198 gtk_widget_set_sensitive (GTK_WIDGET (dar), active);
199 }
200
201 static void
202 set_sensitivity (PsppireDialogActionRank *dar)
203 {
204 gboolean sens = gtk_toggle_button_get_active
205 (GTK_TOGGLE_BUTTON (dar->func_button[PROPORTION]))
206 ||
207 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dar->func_button[NORMAL]));
208
209 gtk_widget_set_sensitive (dar->formula_box, sens);
210 }
211
212 static void
213 psppire_dialog_action_rank_activate (GtkAction *a)
214 {
215 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
216 PsppireDialogActionRank *act = PSPPIRE_DIALOG_ACTION_RANK (a);
217
218 GtkBuilder *xml = builder_new ("rank.ui");
219
220 GtkWidget *types_button = get_widget_assert (xml, "button1");
221 GtkWidget *ties_button = get_widget_assert (xml, "button2");
222
223 pda->dialog = get_widget_assert (xml, "rank-dialog");
224 pda->source = get_widget_assert (xml, "dict-treeview");
225 act->rank_vars = get_widget_assert (xml, "variables-treeview");
226 act->group_vars = get_widget_assert (xml, "group-vars-treeview");
227 act->ascending_togglebutton =
228 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "radiobutton1"));
229
230 act->summary_togglebutton =
231 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "summary-checkbutton"));
232
233 act->types_dialog = get_widget_assert (xml, "rank-types-dialog");
234
235
236 act->ntiles_entry = get_widget_assert (xml, "ntiles-entry");
237
238 act->func_button[RANK] =
239 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "rank-checkbutton"));
240
241 act->func_button[SAVAGE] =
242 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "savage-checkbutton"));
243
244 act->func_button[RFRACTION] =
245 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "rfrac-checkbutton"));
246
247 act->func_button[PERCENT] =
248 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "percent-checkbutton"));
249
250 act->func_button[N] =
251 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "sum-checkbutton"));
252
253 act->func_button[NTILES] =
254 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "ntiles-checkbutton"));
255
256 act->func_button[PROPORTION] =
257 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "prop-checkbutton"));
258
259 act->func_button[NORMAL] =
260 GTK_TOGGLE_BUTTON (get_widget_assert (xml, "normal-checkbutton"));
261
262 act->formula_box = get_widget_assert (xml, "formula-frame");
263
264 act->blom = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "blom-button"));
265 act->tukey = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "tukey-button"));
266 act->rankit = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "rankit-button"));
267 act->vw = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "vw-button"));
268
269 /* Ties dialog */
270 act->ties_dialog = PSPPIRE_DIALOG (get_widget_assert (xml, "ties-dialog"));
271
272 act->mean = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "mean-button"));
273 act->low = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "low-button"));
274 act->high = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "high-button"));
275 act->condense = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "condense-button"));
276
277 g_signal_connect_swapped (act->func_button[PROPORTION], "toggled",
278 G_CALLBACK (set_sensitivity),
279 act);
280
281 g_signal_connect_swapped (act->func_button[NORMAL], "toggled",
282 G_CALLBACK (set_sensitivity),
283 act);
284
285 g_signal_connect (types_button, "clicked",
286 G_CALLBACK (run_types_dialog), act);
287
288 g_signal_connect (ties_button, "clicked",
289 G_CALLBACK (run_ties_dialog), act);
290
291 g_signal_connect (act->func_button[NTILES], "toggled",
292 G_CALLBACK (on_ntiles_toggle),
293 act->ntiles_entry);
294
295 psppire_dialog_action_set_valid_predicate (pda, (void *) dialog_state_valid);
296 psppire_dialog_action_set_refresh (pda, dialog_refresh);
297
298 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_rank_parent_class)->activate (pda);
299
300 g_object_unref (xml);
301 }
302
303 static void
304 psppire_dialog_action_rank_class_init (PsppireDialogActionRankClass *class)
305 {
306 GTK_ACTION_CLASS (class)->activate = psppire_dialog_action_rank_activate;
307
308 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
309 }
310
311 static void
312 psppire_dialog_action_rank_init (PsppireDialogActionRank *act)
313 {
314 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #ifndef __PSPPIRE_DIALOG_ACTION_RANK_H__
18 #define __PSPPIRE_DIALOG_ACTION_RANK_H__
19
20 #include <glib-object.h>
21 #include <glib.h>
22
23 #include "psppire-dialog-action.h"
24
25 G_BEGIN_DECLS
26
27
28 #define PSPPIRE_TYPE_DIALOG_ACTION_RANK (psppire_dialog_action_rank_get_type ())
29
30 #define PSPPIRE_DIALOG_ACTION_RANK(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 PSPPIRE_TYPE_DIALOG_ACTION_RANK, PsppireDialogActionRank))
33
34 #define PSPPIRE_DIALOG_ACTION_RANK_CLASS(klass) \
35 (G_TYPE_CHECK_CLASS_CAST ((klass), \
36 PSPPIRE_TYPE_DIALOG_ACTION_RANK, \
37 PsppireDialogActionRankClass))
38
39
40 #define PSPPIRE_IS_DIALOG_ACTION_RANK(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_RANK))
42
43 #define PSPPIRE_IS_DIALOG_ACTION_RANK_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_RANK))
45
46
47 #define PSPPIRE_DIALOG_ACTION_RANK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
48 PSPPIRE_TYPE_DIALOG_ACTION_RANK, \
49 PsppireDialogActionRankClass))
50
51 typedef struct _PsppireDialogActionRank PsppireDialogActionRank;
52 typedef struct _PsppireDialogActionRankClass PsppireDialogActionRankClass;
53
54
55 enum RANK_FUNC
56 {
57 RANK,
58 NORMAL,
59 PERCENT,
60 RFRACTION,
61 PROPORTION,
62 N,
63 NTILES,
64 SAVAGE,
65 n_RANK_FUNCS
66 };
67
68 struct _PsppireDialogActionRank
69 {
70 PsppireDialogAction parent;
71
72 /*< private >*/
73 GtkWidget *rank_vars;
74 GtkWidget *group_vars;
75
76 GtkToggleButton *ascending_togglebutton;
77 GtkToggleButton *summary_togglebutton;
78
79
80 /* Types subdialog widgets */
81
82 GtkWidget *types_dialog;
83 GtkWidget *ntiles_entry;
84
85 GtkToggleButton *func_button[n_RANK_FUNCS];
86 GtkWidget *formula_box;
87
88 GtkToggleButton *blom;
89 GtkToggleButton *tukey;
90 GtkToggleButton *rankit;
91 GtkToggleButton *vw;
92
93 /* Ties subdialog widgets */
94
95 PsppireDialog *ties_dialog;
96 GtkToggleButton *mean;
97 GtkToggleButton *low;
98 GtkToggleButton *high;
99 GtkToggleButton *condense;
100 };
101
102
103 struct _PsppireDialogActionRankClass
104 {
105 PsppireDialogActionClass parent_class;
106 };
107
108
109 GType psppire_dialog_action_rank_get_type (void) ;
110
111 G_END_DECLS
112
113 #endif /* __PSPPIRE_DIALOG_ACTION_RANK_H__ */
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2008, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <config.h>
18
19 #include "psppire-dialog-action-regression.h"
20 #include "psppire-value-entry.h"
21
22 #include "dialog-common.h"
23 #include "helper.h"
24 #include <ui/syntax-gen.h>
25 #include "psppire-var-view.h"
26
27 #include "psppire-dialog.h"
28 #include "builder-wrapper.h"
29 #include "checkbox-treeview.h"
30 #include "psppire-dict.h"
31 #include "libpspp/str.h"
32
33 #include "gettext.h"
34 #define _(msgid) gettext (msgid)
35 #define N_(msgid) msgid
36
37
38 #define REGRESSION_STATS \
39 RG (COEFF, N_("Coeff")) \
40 RG (R, N_("R")) \
41 RG (ANOVA, N_("Anova")) \
42 RG (BCOV, N_("Bcov"))
43 enum
44 {
45 #define RG(NAME, LABEL) RG_##NAME,
46 REGRESSION_STATS
47 #undef RG
48 N_REGRESSION_STATS
49 };
50
51 enum
52 {
53 #define RG(NAME, LABEL) B_RG_##NAME = 1u << RG_##NAME,
54 REGRESSION_STATS
55 #undef RG
56 B_RG_STATS_ALL = (1u << N_REGRESSION_STATS) - 1,
57 B_RG_STATS_DEFAULT = B_RG_ANOVA | B_RG_COEFF | B_RG_R
58 };
59
60 static const struct checkbox_entry_item stats[] =
61 {
62 #define RG(NAME, LABEL) {#NAME, LABEL},
63 REGRESSION_STATS
64 #undef RG
65 };
66
67 static void
68 psppire_dialog_action_regression_class_init (PsppireDialogActionRegressionClass *class);
69
70 G_DEFINE_TYPE (PsppireDialogActionRegression, psppire_dialog_action_regression, PSPPIRE_TYPE_DIALOG_ACTION);
71
72 static gboolean
73 dialog_state_valid (gpointer data)
74 {
75 PsppireDialogActionRegression *rd = PSPPIRE_DIALOG_ACTION_REGRESSION (data);
76 GtkTreeModel *dep_vars = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->dep_vars));
77 GtkTreeModel *indep_vars = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->indep_vars));
78
79 GtkTreeIter notused;
80
81 return (gtk_tree_model_get_iter_first (dep_vars, &notused)
82 && gtk_tree_model_get_iter_first (indep_vars, &notused));
83 }
84
85 static void
86 refresh (PsppireDialogAction *rd_)
87 {
88 PsppireDialogActionRegression *rd = PSPPIRE_DIALOG_ACTION_REGRESSION (rd_);
89
90 GtkTreeModel *liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->dep_vars));
91 gtk_list_store_clear (GTK_LIST_STORE (liststore));
92
93 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->indep_vars));
94 gtk_list_store_clear (GTK_LIST_STORE (liststore));
95 }
96
97 static void
98 on_statistics_clicked (PsppireDialogActionRegression *rd)
99 {
100 int ret;
101 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->stat_view));
102
103 /* Take a backup copy of the existing model */
104 GtkListStore *backup_model = clone_list_store (GTK_LIST_STORE (model));
105
106 ret = psppire_dialog_run (PSPPIRE_DIALOG (rd->stat_dialog));
107
108 if ( ret != PSPPIRE_RESPONSE_CONTINUE )
109 {
110 /* If the user chose to abandon his changes, then replace the model, from the backup */
111 gtk_tree_view_set_model (GTK_TREE_VIEW (rd->stat_view) , GTK_TREE_MODEL (backup_model));
112 }
113 g_object_unref (backup_model);
114 }
115
116 static void
117 on_save_clicked (PsppireDialogActionRegression *rd)
118 {
119 int ret;
120 if (rd->pred)
121 {
122 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->pred_button), TRUE);
123 }
124 if (rd->resid)
125 {
126 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->resid_button), TRUE);
127 }
128
129 ret = psppire_dialog_run (PSPPIRE_DIALOG (rd->save_dialog));
130
131 if ( ret == PSPPIRE_RESPONSE_CONTINUE )
132 {
133 rd->pred = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->pred_button)) == TRUE)
134 ? TRUE : FALSE;
135 rd->resid = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->resid_button)) == TRUE)
136 ? TRUE : FALSE;
137 }
138 }
139
140
141 static void
142 psppire_dialog_action_regression_activate (GtkAction *a)
143 {
144 PsppireDialogActionRegression *act = PSPPIRE_DIALOG_ACTION_REGRESSION (a);
145 PsppireDialogAction *pda = PSPPIRE_DIALOG_ACTION (a);
146
147 GtkBuilder *xml = builder_new ("regression.ui");
148 GtkWidget *stat_button = get_widget_assert (xml, "stat-button");
149 GtkWidget *save_button = get_widget_assert (xml, "save-button");
150
151 pda->dialog = get_widget_assert (xml, "regression-dialog");
152 pda->source = get_widget_assert (xml, "dict-view");
153
154 act->dep_vars = get_widget_assert (xml, "dep-view");
155 act->indep_vars = get_widget_assert (xml, "indep-view");
156 act->stat_view = get_widget_assert (xml, "stat-view");
157 act->stat_dialog = get_widget_assert (xml, "statistics-dialog");
158 act->save_dialog = get_widget_assert (xml, "save-dialog");
159 act->pred_button = get_widget_assert (xml, "pred-button");
160 act->resid_button = get_widget_assert (xml, "resid-button");
161
162 g_object_unref (xml);
163
164 put_checkbox_items_in_treeview (GTK_TREE_VIEW (act->stat_view),
165 B_RG_STATS_DEFAULT,
166 N_REGRESSION_STATS,
167 stats);
168
169 psppire_dialog_action_set_refresh (pda, refresh);
170
171 psppire_dialog_action_set_valid_predicate (pda,
172 dialog_state_valid);
173
174 g_signal_connect_swapped (stat_button, "clicked",
175 G_CALLBACK (on_statistics_clicked), act);
176
177 g_signal_connect_swapped (save_button, "clicked",
178 G_CALLBACK (on_save_clicked), act);
179
180
181 if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_regression_parent_class)->activate)
182 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_regression_parent_class)->activate (pda);
183 }
184
185
186
187 static char *
188 generate_syntax (PsppireDialogAction *a)
189 {
190 PsppireDialogActionRegression *rd = PSPPIRE_DIALOG_ACTION_REGRESSION (a);
191 gchar *text = NULL;
192
193 gint i;
194 int n;
195 guint selected;
196 GtkTreeIter iter;
197 gboolean ok;
198
199 GString *string = g_string_new ("REGRESSION");
200
201 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->stat_view));
202
203 g_string_append (string, "\n\t/VARIABLES=");
204 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->indep_vars), 0, string);
205 g_string_append (string, "\n\t/DEPENDENT=\t");
206 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->dep_vars), 0, string);
207
208 selected = 0;
209 for (i = 0, ok = gtk_tree_model_get_iter_first (model, &iter); ok;
210 i++, ok = gtk_tree_model_iter_next (model, &iter))
211 {
212 gboolean toggled;
213 gtk_tree_model_get (model, &iter,
214 CHECKBOX_COLUMN_SELECTED, &toggled, -1);
215 if (toggled)
216 selected |= 1u << i;
217 else
218 selected &= ~(1u << i);
219 }
220
221 if (selected)
222 {
223 g_string_append (string, "\n\t/STATISTICS=");
224 n = 0;
225 for (i = 0; i < N_REGRESSION_STATS; i++)
226 if (selected & (1u << i))
227 {
228 if (n++)
229 g_string_append (string, " ");
230 g_string_append (string, stats[i].name);
231 }
232 }
233
234 if (rd->pred || rd->resid)
235 {
236 g_string_append (string, "\n\t/SAVE=");
237 if (rd->pred)
238 g_string_append (string, " PRED");
239 if (rd->resid)
240 g_string_append (string, " RESID");
241 }
242
243 g_string_append (string, ".\n");
244
245 text = string->str;
246
247 g_string_free (string, FALSE);
248
249 return text;
250 }
251
252 static void
253 psppire_dialog_action_regression_class_init (PsppireDialogActionRegressionClass *class)
254 {
255 GtkActionClass *action_class = GTK_ACTION_CLASS (class);
256
257 action_class->activate = psppire_dialog_action_regression_activate;
258
259 PSPPIRE_DIALOG_ACTION_CLASS (class)->generate_syntax = generate_syntax;
260 }
261
262
263 static void
264 psppire_dialog_action_regression_init (PsppireDialogActionRegression *act)
265 {
266 }
267
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #include <glib-object.h>
18 #include <glib.h>
19
20 #include "psppire-dialog-action.h"
21
22 #ifndef __PSPPIRE_DIALOG_ACTION_REGRESSION_H__
23 #define __PSPPIRE_DIALOG_ACTION_REGRESSION_H__
24
25 G_BEGIN_DECLS
26
27
28 #define PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION (psppire_dialog_action_regression_get_type ())
29
30 #define PSPPIRE_DIALOG_ACTION_REGRESSION(obj) \
31 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
32 PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION, PsppireDialogActionRegression))
33
34 #define PSPPIRE_DIALOG_ACTION_REGRESSION_CLASS(klass) \
35 (G_TYPE_CHECK_CLASS_CAST ((klass), \
36 PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION, \
37 PsppireDialogActionRegressionClass))
38
39
40 #define PSPPIRE_IS_DIALOG_ACTION_REGRESSION(obj) \
41 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION))
42
43 #define PSPPIRE_IS_DIALOG_ACTION_REGRESSION_CLASS(klass) \
44 (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION))
45
46
47 #define PSPPIRE_DIALOG_ACTION_REGRESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
48 PSPPIRE_TYPE_DIALOG_ACTION_REGRESSION, \
49 PsppireDialogActionRegressionClass))
50
51 typedef struct _PsppireDialogActionRegression PsppireDialogActionRegression;
52 typedef struct _PsppireDialogActionRegressionClass PsppireDialogActionRegressionClass;
53
54
55 struct _PsppireDialogActionRegression
56 {
57 PsppireDialogAction parent;
58
59 /*< private >*/
60 gboolean dispose_has_run ;
61
62 GtkWidget *dep_vars;
63 GtkWidget *indep_vars;
64
65 GtkWidget *resid_button;
66 GtkWidget *pred_button;
67
68 GtkWidget *stat_dialog;
69 GtkWidget *save_dialog;
70
71 GtkWidget *stat_view;
72
73
74 /* Save Options */
75 gboolean pred;
76 gboolean resid;
77 };
78
79
80 struct _PsppireDialogActionRegressionClass
81 {
82 PsppireDialogActionClass parent_class;
83 };
84
85
86 GType psppire_dialog_action_regression_get_type (void) ;
87
88 G_END_DECLS
89
90 #endif /* __PSPPIRE_DIALOG_ACTION_REGRESSION_H__ */
158158
159159 if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_reliability_parent_class)->activate)
160160 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_reliability_parent_class)->activate (pda);
161
162 g_object_unref (xml);
161163 }
162164
163165 static void
1717 #include <config.h>
1818
1919 #include "psppire-dialog-action-roc.h"
20 #include "psppire-value-entry.h"
2021
2122 #include "dialog-common.h"
2223 #include <ui/syntax-gen.h>
3637 static gboolean
3738 dialog_state_valid (gpointer data)
3839 {
40 int width;
41 gboolean result ;
42 union value val;
3943 PsppireDialogActionRoc *rd = data;
40 const gchar *text;
44 const gchar *var_name;
45 const struct variable *var;
4146
4247 GtkTreeModel *liststore =
4348 gtk_tree_view_get_model (GTK_TREE_VIEW (rd->test_variables));
4550 if (gtk_tree_model_iter_n_children (liststore, NULL) < 1)
4651 return FALSE;
4752
53 var_name = gtk_entry_get_text (GTK_ENTRY (rd->state_variable));
54
55 var = psppire_dict_lookup_var (PSPPIRE_DIALOG_ACTION (rd)->dict, var_name);
56
57 if ( var == NULL)
58 return FALSE;
59
60 width = var_get_width (var);
61 value_init (&val, width);
62
63 result = psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (rd->state_value), &val, width);
4864
49 text = gtk_entry_get_text (GTK_ENTRY (rd->state_variable));
50 if ( 0 == strcmp ("", text))
51 return FALSE;
52
53
54 text = gtk_entry_get_text (GTK_ENTRY (rd->state_value));
55 if ( 0 == strcmp ("", text))
56 return FALSE;
57
58
59 return TRUE;
65 if (var_is_value_missing (var, &val, MV_SYSTEM))
66 result = FALSE;
67
68 value_destroy (&val, width);
69
70 return result;
6071 }
6172
6273 static void
8495 gtk_list_store_clear (GTK_LIST_STORE (liststore));
8596
8697 gtk_entry_set_text (GTK_ENTRY (rd->state_variable), "");
87 gtk_entry_set_text (GTK_ENTRY (rd->state_value), "");
98 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (rd->state_value), NULL);
8899
89100 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->curve), TRUE);
90101 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->reference), FALSE);
93104 }
94105
95106 static void
107 on_state_var_changed (GtkAction *a)
108 {
109 PsppireDialogActionRoc *act = PSPPIRE_DIALOG_ACTION_ROC (a);
110
111 const gchar *var_name = gtk_entry_get_text (GTK_ENTRY(act->state_variable));
112
113 const struct variable *var =
114 psppire_dict_lookup_var (PSPPIRE_DIALOG_ACTION(act)->dict, var_name);
115
116 if ( var == NULL)
117 return;
118
119 psppire_value_entry_set_variable (PSPPIRE_VALUE_ENTRY (act->state_value), var);
120 }
121
122 static void
96123 psppire_dialog_action_roc_activate (GtkAction *a)
97124 {
98125 PsppireDialogActionRoc *act = PSPPIRE_DIALOG_ACTION_ROC (a);
100127
101128 GtkBuilder *xml = builder_new ("roc.ui");
102129 pda->dialog = get_widget_assert (xml, "roc-dialog");
103 pda->source = get_widget_assert (xml, "dict-view");
104130 pda->source = get_widget_assert (xml, "dict-view");
105131
106132 act->test_variables = get_widget_assert (xml, "psppire-var-view1");
112138 act->standard_error = get_widget_assert (xml, "standard-error");
113139 act->coordinates = get_widget_assert (xml, "co-ordinates");
114140
141 g_signal_connect_swapped (act->state_variable, "changed",
142 G_CALLBACK (on_state_var_changed), act);
143
115144 g_object_unref (xml);
116145
117146 g_signal_connect (act->curve, "toggled",
144173
145174 g_string_append (string, " (");
146175 {
147 const gchar *value = gtk_entry_get_text (GTK_ENTRY (rd->state_value));
148
149 const struct variable *var = psppire_dict_lookup_var (PSPPIRE_DIALOG_ACTION(rd)->dict, var_name);
176 const struct variable *var =
177 psppire_dict_lookup_var (PSPPIRE_DIALOG_ACTION(rd)->dict, var_name);
178
179 union value val;
180 value_init (&val, var_get_width (var));
181
182 psppire_value_entry_get_value (PSPPIRE_VALUE_ENTRY (rd->state_value),
183 &val, var_get_width (var));
150184
151185 g_return_val_if_fail (var, NULL);
152186
153 if ( var_is_alpha (var))
154 {
155 struct string str;
156 ds_init_empty (&str);
157 syntax_gen_string (&str, ss_cstr (value));
158 g_string_append (string, ds_cstr (&str));
159 ds_destroy (&str);
160 }
161 else
162 g_string_append (string, value);
187 {
188 struct string str;
189 ds_init_empty (&str);
190
191 syntax_gen_value (&str, &val, var_get_width (var),
192 var_get_print_format (var));
193
194 g_string_append (string, ds_cstr (&str));
195 ds_destroy (&str);
196 }
197 value_destroy (&val, var_get_width (var));
163198 }
199
164200 g_string_append (string, ")");
165201
166202
108108
109109 if (PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_sort_parent_class)->activate)
110110 PSPPIRE_DIALOG_ACTION_CLASS (psppire_dialog_action_sort_parent_class)->activate (pda);
111
112 g_object_unref (xml);
111113 }
112114
113115 static void
125125 break;
126126 }
127127 }
128
129 gtk_widget_destroy (act->dialog);
128130 }
129131
130132 static void
286286
287287
288288 object_class->finalize = psppire_dialog_finalize;
289
290 parent_class = g_type_class_peek_parent (class);
289291 }
290292
291293
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011 Free Software Foundation
1 Copyright (C) 2004, 2006, 2007, 2009, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
128128
129129
130130 signals [VARIABLE_CHANGED] =
131 g_signal_new ("variable_changed",
131 g_signal_new ("variable-changed",
132132 G_TYPE_FROM_CLASS (class),
133133 G_SIGNAL_RUN_FIRST,
134134 0,
141141
142142
143143 signals [VARIABLE_INSERTED] =
144 g_signal_new ("variable_inserted",
144 g_signal_new ("variable-inserted",
145145 G_TYPE_FROM_CLASS (class),
146146 G_SIGNAL_RUN_FIRST,
147147 0,
158158 G_SIGNAL_RUN_FIRST,
159159 0,
160160 NULL, NULL,
161 psppire_marshal_VOID__INT_INT_INT,
161 psppire_marshal_VOID__POINTER_INT_INT,
162162 G_TYPE_NONE,
163163 3,
164 G_TYPE_INT,
164 G_TYPE_POINTER,
165165 G_TYPE_INT,
166166 G_TYPE_INT);
167167
247247 }
248248
249249 static void
250 delcb (struct dictionary *d, int dict_idx, int case_idx, int width, void *pd)
250 delcb (struct dictionary *d, const struct variable *var,
251 int dict_idx, int case_idx, void *pd)
251252 {
252253 g_signal_emit (pd, signals [VARIABLE_DELETED], 0,
253 dict_idx, case_idx, width );
254 var, dict_idx, case_idx);
254255 }
255256
256257 static void
348349 }
349350
350351
351 /* Returns a valid name for a new variable in DICT.
352 The return value is statically allocated */
353 static gchar *
354 auto_generate_var_name (PsppireDict *dict)
355 {
356 gint d = 0;
357 static gchar name[10];
358
359 /* TRANSLATORS: This string must be a valid variable name. That means:
360 - The string must be at most 64 bytes (not characters) long.
361 - The string may not contain whitespace.
362 - The first character may not be '$'
363 - The first character may not be a digit
364 - The final charactor may not be '.' or '_'
365 */
366 while (g_snprintf (name, 10, _("VAR%05d"), d++),
367 psppire_dict_lookup_var (dict, name))
368 ;
352 /* Stores a valid name for a new variable in DICT into the SIZE bytes in NAME.
353 Returns true if successful, false if SIZE is insufficient. */
354 bool
355 psppire_dict_generate_name (const PsppireDict *dict, char *name, size_t size)
356 {
357 gint d;
358
359 for (d = 1; ; d++)
360 {
361 int len;
362
363 /* TRANSLATORS: This string must be a valid variable name. That means:
364 - The string must be at most 64 bytes (not characters) long.
365 - The string may not contain whitespace.
366 - The first character may not be '$'
367 - The first character may not be a digit
368 - The final charactor may not be '.' or '_'
369 */
370 len = snprintf (name, size, _("Var%04d"), d);
371 if (len + 1 >= size)
372 return false;
373
374 if (psppire_dict_lookup_var (dict, name) == NULL)
375 return true;
376 }
369377
370378 return name;
371379 }
372380
373 /* Insert a new variable at posn IDX, with the name NAME.
381 /* Insert a new variable at posn IDX, with the name NAME, and return the
382 new variable.
374383 If NAME is null, then a name will be automatically assigned.
375384 */
376 void
385 struct variable *
377386 psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name)
378387 {
379 struct variable *var ;
380 g_return_if_fail (idx >= 0);
381 g_return_if_fail (d);
382 g_return_if_fail (PSPPIRE_IS_DICT (d));
383
384 if ( ! name )
385 name = auto_generate_var_name (d);
388 struct variable *var;
389 char tmpname[64];
390
391 g_return_val_if_fail (idx >= 0, NULL);
392 g_return_val_if_fail (d, NULL);
393 g_return_val_if_fail (PSPPIRE_IS_DICT (d), NULL);
394
395 if (name == NULL)
396 {
397 if (!psppire_dict_generate_name (d, tmpname, sizeof tmpname))
398 g_return_val_if_reached (NULL);
399
400 name = tmpname;
401 }
386402
387403 d->disable_insert_signal = TRUE;
388404
393409 d->disable_insert_signal = FALSE;
394410
395411 g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
412
413 return var;
396414 }
397415
398416 /* Delete N variables beginning at FIRST */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2004, 2009 Free Software Foundation
1 Copyright (C) 2004, 2009, 2011 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
8989 void psppire_dict_delete_variables (PsppireDict *d, gint first, gint n);
9090
9191 /* Insert a new variable at posn IDX */
92 void psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name);
92 struct variable *psppire_dict_insert_variable (PsppireDict *d, gint idx,
93 const gchar *name);
9394
9495 void psppire_dict_resize_variable (PsppireDict *,
9596 const struct variable *,
9798
9899 gboolean psppire_dict_check_name (const PsppireDict *dict,
99100 const gchar *name, gboolean report);
101
102 bool psppire_dict_generate_name (const PsppireDict *, char *name, size_t size);
100103
101104 gint psppire_dict_get_next_value_idx (const PsppireDict *dict);
102105
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2009, 2010, 2011 Free Software Foundation
1 Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
6767 {
6868 PsppireDictView *dict_view = PSPPIRE_DICT_VIEW (object);
6969
70 g_object_unref (dict_view->menu);
70 gtk_widget_destroy (dict_view->menu);
7171 }
7272
7373 /* Properties */
120120 else
121121 {
122122 model = GTK_TREE_MODEL (dict_view->dict);
123 g_object_ref (model);
123124 }
124125
125126 gtk_tree_view_set_model (GTK_TREE_VIEW (dict_view), model);
127 g_object_unref (model);
126128 }
127129
128130 static void
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "psppire-empty-list-store.h"
19
20 static void psppire_empty_list_store_class_init (PsppireEmptyListStoreClass *);
21 static void psppire_empty_list_store_init (PsppireEmptyListStore *);
22
23 /* GtkTreeModel interface. */
24 static void gtk_tree_model_interface_init (GtkTreeModelIface *iface);
25 static GtkTreeModelFlags empty_list_store_get_flags (GtkTreeModel *tree_model);
26 static gint empty_list_store_get_n_columns (GtkTreeModel *tree_model);
27 static GType empty_list_store_get_column_type (GtkTreeModel *tree_model,
28 gint index_);
29 static gboolean empty_list_store_get_iter (GtkTreeModel *tree_model,
30 GtkTreeIter *iter,
31 GtkTreePath *path);
32 static GtkTreePath * empty_list_store_get_path (GtkTreeModel *tree_model,
33 GtkTreeIter *iter);
34 static void empty_list_store_get_value (GtkTreeModel *tree_model,
35 GtkTreeIter *iter,
36 gint column,
37 GValue *value);
38 static gboolean empty_list_store_iter_next (GtkTreeModel *tree_model,
39 GtkTreeIter *iter);
40 static gboolean empty_list_store_iter_children (GtkTreeModel *tree_model,
41 GtkTreeIter *iter,
42 GtkTreeIter *parent);
43 static gboolean empty_list_store_iter_has_child (GtkTreeModel *tree_model,
44 GtkTreeIter *iter);
45 static gint empty_list_store_iter_n_children (GtkTreeModel *tree_model,
46 GtkTreeIter *iter);
47 static gboolean empty_list_store_iter_nth_child (GtkTreeModel *tree_model,
48 GtkTreeIter *iter,
49 GtkTreeIter *parent,
50 gint n);
51 static gboolean empty_list_store_iter_parent (GtkTreeModel *tree_model,
52 GtkTreeIter *iter,
53 GtkTreeIter *child);
54
55 GType
56 psppire_empty_list_store_get_type (void)
57 {
58 static GType type = 0;
59 if (!type)
60 {
61 static const GTypeInfo psppire_empty_list_store_info =
62 {
63 sizeof(PsppireEmptyListStoreClass),
64 NULL, /* base init */
65 NULL, /* base finalize */
66 (GClassInitFunc) psppire_empty_list_store_class_init,
67 NULL, /* class finalize */
68 NULL, /* class data */
69 sizeof(PsppireEmptyListStore),
70 0, /* n_preallocs, ignored since 2.10 */
71 (GInstanceInitFunc) psppire_empty_list_store_init,
72 NULL
73 };
74 static const GInterfaceInfo gtk_tree_model_info =
75 {
76 (GInterfaceInitFunc) gtk_tree_model_interface_init,
77 (GInterfaceFinalizeFunc) NULL,
78 NULL
79 };
80 type = g_type_register_static (G_TYPE_OBJECT,
81 "PsppireEmptyListStore",
82 &psppire_empty_list_store_info, 0);
83 g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL,
84 &gtk_tree_model_info);
85 }
86 return type;
87 }
88
89 enum
90 {
91 PROP_0,
92 PROP_N_ROWS
93 };
94
95 static void
96 psppire_empty_list_store_set_property (GObject *object,
97 guint prop_id,
98 const GValue *value,
99 GParamSpec *pspec)
100 {
101 PsppireEmptyListStore *obj = PSPPIRE_EMPTY_LIST_STORE (object);
102
103 switch (prop_id)
104 {
105 case PROP_N_ROWS:
106 obj->n_rows = g_value_get_int (value);
107 break;
108
109 default:
110 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111 break;
112 }
113 }
114
115 static void
116 psppire_empty_list_store_get_property (GObject *object,
117 guint prop_id,
118 GValue *value,
119 GParamSpec *pspec)
120 {
121 PsppireEmptyListStore *obj = PSPPIRE_EMPTY_LIST_STORE (object);
122
123 switch (prop_id)
124 {
125 case PROP_N_ROWS:
126 g_value_set_int (value, obj->n_rows);
127 break;
128
129 default:
130 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
131 break;
132 }
133 }
134
135 static void
136 psppire_empty_list_store_class_init (PsppireEmptyListStoreClass *class)
137 {
138 GObjectClass *gobject_class;
139 gobject_class = G_OBJECT_CLASS (class);
140
141 gobject_class->set_property = psppire_empty_list_store_set_property;
142 gobject_class->get_property = psppire_empty_list_store_get_property;
143
144 g_object_class_install_property (gobject_class,
145 PROP_N_ROWS,
146 g_param_spec_int ("n-rows",
147 ("Number of rows"),
148 ("Number of rows in GtkTreeModel"),
149 0,
150 G_MAXINT,
151 0,
152 G_PARAM_READWRITE));
153 }
154
155 static void
156 psppire_empty_list_store_init (PsppireEmptyListStore *obj)
157 {
158 obj->n_rows = 0;
159 }
160
161 PsppireEmptyListStore *
162 psppire_empty_list_store_new (gint n_rows)
163 {
164 return PSPPIRE_EMPTY_LIST_STORE (g_object_new (PSPPIRE_TYPE_EMPTY_LIST_STORE,
165 "n-rows", n_rows,
166 NULL));
167 }
168
169 gint
170 psppire_empty_list_store_get_n_rows (const PsppireEmptyListStore *obj)
171 {
172 return obj->n_rows;
173 }
174
175 void
176 psppire_empty_list_store_set_n_rows (PsppireEmptyListStore *obj,
177 gint n_rows)
178 {
179 obj->n_rows = n_rows;
180 }
181
182 void
183 psppire_empty_list_store_row_inserted (PsppireEmptyListStore *obj,
184 gint row)
185 {
186 GtkTreeModel *tree_model = GTK_TREE_MODEL (obj);
187 GtkTreeIter iter;
188 GtkTreePath *path;
189
190 path = gtk_tree_path_new_from_indices (row, -1);
191 gtk_tree_model_get_iter (tree_model, &iter, path);
192 gtk_tree_model_row_inserted (tree_model, path, &iter);
193 gtk_tree_path_free (path);
194 }
195
196 void
197 psppire_empty_list_store_row_deleted (PsppireEmptyListStore *obj,
198 gint row)
199 {
200 GtkTreeModel *tree_model = GTK_TREE_MODEL (obj);
201 GtkTreePath *path;
202
203 path = gtk_tree_path_new_from_indices (row, -1);
204 gtk_tree_model_row_deleted (tree_model, path);
205 gtk_tree_path_free (path);
206 }
207
208 /* GtkTreeModel interface. */
209
210 /* Random number used in 'stamp' member of GtkTreeIter. */
211 #define TREE_MODEL_STAMP 0x10c44c13
212
213 static gboolean
214 empty_list_store_init_iter (GtkTreeModel *model, gint idx, GtkTreeIter *iter)
215 {
216 const PsppireEmptyListStore *store = PSPPIRE_EMPTY_LIST_STORE (model);
217
218 if (idx < 0 || idx >= store->n_rows)
219 {
220 iter->stamp = 0;
221 iter->user_data = GINT_TO_POINTER (-1);
222 return FALSE;
223 }
224 else
225 {
226 iter->stamp = TREE_MODEL_STAMP;
227 iter->user_data = GINT_TO_POINTER (idx);
228 return TRUE;
229 }
230 }
231
232 static void
233 gtk_tree_model_interface_init (GtkTreeModelIface *iface)
234 {
235 g_return_if_fail (iface != NULL);
236
237 iface->get_flags = empty_list_store_get_flags;
238 iface->get_n_columns = empty_list_store_get_n_columns;
239 iface->get_column_type = empty_list_store_get_column_type;
240 iface->get_iter = empty_list_store_get_iter;
241 iface->get_path = empty_list_store_get_path;
242 iface->get_value = empty_list_store_get_value;
243 iface->iter_next = empty_list_store_iter_next;
244 iface->iter_children = empty_list_store_iter_children;
245 iface->iter_has_child = empty_list_store_iter_has_child;
246 iface->iter_n_children = empty_list_store_iter_n_children;
247 iface->iter_nth_child = empty_list_store_iter_nth_child;
248 iface->iter_parent = empty_list_store_iter_parent;
249 }
250
251 static GtkTreeModelFlags
252 empty_list_store_get_flags (GtkTreeModel *tree_model G_GNUC_UNUSED)
253 {
254 return GTK_TREE_MODEL_LIST_ONLY;
255 }
256
257 static gint
258 empty_list_store_get_n_columns (GtkTreeModel *tree_model G_GNUC_UNUSED)
259 {
260 return 0;
261 }
262
263 static GType
264 empty_list_store_get_column_type (GtkTreeModel *tree_model,
265 gint index_)
266 {
267 g_return_val_if_reached (G_TYPE_NONE);
268 }
269
270 static gboolean
271 empty_list_store_get_iter (GtkTreeModel *tree_model,
272 GtkTreeIter *iter,
273 GtkTreePath *path)
274 {
275 gint *indices, depth;
276
277 g_return_val_if_fail (path, FALSE);
278
279 indices = gtk_tree_path_get_indices (path);
280 depth = gtk_tree_path_get_depth (path);
281
282 g_return_val_if_fail (depth == 1, FALSE);
283
284 return empty_list_store_init_iter (tree_model, indices[0], iter);
285 }
286
287 static GtkTreePath *
288 empty_list_store_get_path (GtkTreeModel *tree_model,
289 GtkTreeIter *iter)
290 {
291 GtkTreePath *path;
292
293 g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE);
294
295 path = gtk_tree_path_new ();
296 gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data));
297
298 return path;
299 }
300
301 static void
302 empty_list_store_get_value (GtkTreeModel *tree_model,
303 GtkTreeIter *iter,
304 gint column,
305 GValue *value)
306 {
307 g_return_if_reached ();
308 }
309
310 static gboolean
311 empty_list_store_iter_next (GtkTreeModel *tree_model,
312 GtkTreeIter *iter)
313 {
314 gint idx;
315
316 g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE);
317
318 idx = GPOINTER_TO_INT (iter->user_data);
319 return empty_list_store_init_iter (tree_model, idx + (idx >= 0), iter);
320 }
321
322 static gboolean
323 empty_list_store_iter_children (GtkTreeModel *tree_model,
324 GtkTreeIter *iter,
325 GtkTreeIter *parent)
326 {
327 return FALSE;
328 }
329
330 static gboolean
331 empty_list_store_iter_has_child (GtkTreeModel *tree_model,
332 GtkTreeIter *iter)
333 {
334 return FALSE;
335 }
336
337 static gint
338 empty_list_store_iter_n_children (GtkTreeModel *tree_model,
339 GtkTreeIter *iter)
340 {
341 return iter == NULL ? PSPPIRE_EMPTY_LIST_STORE (tree_model)->n_rows : 0;
342 }
343
344 static gboolean
345 empty_list_store_iter_nth_child (GtkTreeModel *tree_model,
346 GtkTreeIter *iter,
347 GtkTreeIter *parent,
348 gint n)
349 {
350 g_return_val_if_fail (parent == NULL, FALSE);
351
352 return empty_list_store_init_iter (tree_model, n, iter);
353 }
354
355 static gboolean
356 empty_list_store_iter_parent (GtkTreeModel *tree_model,
357 GtkTreeIter *iter,
358 GtkTreeIter *child)
359 {
360 return FALSE;
361 }
362
363 gint
364 empty_list_store_iter_to_row (const GtkTreeIter *iter)
365 {
366 g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, 0);
367 return GPOINTER_TO_INT (iter->user_data);
368 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef PSPPIRE_EMPTY_LIST_STORE_H
17 #define PSPPIRE_EMPTY_LIST_STORE_H 1
18
19 /* PsppireEmptyListStore is an GtkTreeModel implementation that has a
20 client-specified number of rows and zero columns. It is a useful model for
21 GtkTreeView or PsppSheetView when the client can easily synthesize cell data
22 using a callback set with gtk_tree_view_column_set_cell_data_func(). In
23 that situation, GtkListStore can be wasteful (because it uses a lot of
24 memory to store what does not need to be stored) and situation-specific
25 custom models require additional boilerplate. */
26
27 #include <glib-object.h>
28 #include <gtk/gtk.h>
29
30 G_BEGIN_DECLS
31
32 #define PSPPIRE_TYPE_EMPTY_LIST_STORE (psppire_empty_list_store_get_type())
33 #define PSPPIRE_EMPTY_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_EMPTY_LIST_STORE,PsppireEmptyListStore))
34 #define PSPPIRE_EMPTY_LIST_STORE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_EMPTY_LIST_STORE,PsppireEmptyListStoreClass))
35 #define PSPPIRE_IS_EMPTY_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_EMPTY_LIST_STORE))
36 #define PSPPIRE_IS_EMPTY_LIST_STORE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_EMPTY_LIST_STORE))
37 #define PSPPIRE_EMPTY_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_EMPTY_LIST_STORE,PsppireEmptyListStoreClass))
38
39 typedef struct _PsppireEmptyListStore PsppireEmptyListStore;
40 typedef struct _PsppireEmptyListStoreClass PsppireEmptyListStoreClass;
41
42 struct _PsppireEmptyListStore {
43 GObject parent;
44 gint n_rows;
45 };
46
47 struct _PsppireEmptyListStoreClass {
48 GObjectClass parent_class;
49 };
50
51 GType psppire_empty_list_store_get_type (void) G_GNUC_CONST;
52 PsppireEmptyListStore* psppire_empty_list_store_new (gint n_rows);
53
54 gint psppire_empty_list_store_get_n_rows (const PsppireEmptyListStore *);
55 void psppire_empty_list_store_set_n_rows (PsppireEmptyListStore *,
56 gint n_rows);
57
58 void psppire_empty_list_store_row_inserted (PsppireEmptyListStore *,
59 gint row);
60 void psppire_empty_list_store_row_deleted (PsppireEmptyListStore *,
61 gint row);
62
63 gint empty_list_store_iter_to_row (const GtkTreeIter *);
64
65 G_END_DECLS
66
67 #endif /* PSPPIRE_EMPTY_LIST_STORE_H */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2011 Free Software Foundation, Inc.
1 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
3939 COL_ENCODING
4040 };
4141
42 static void SENTINEL (0)
43 add_encodings (GtkTreeStore *store, const char *category, ...)
44 {
45 const char *encodings[16];
46 va_list args;
47 int n;
48
49 /* Count encoding arguments. */
50 va_start (args, category);
51 n = 0;
52 while ((encodings[n] = va_arg (args, const char *)) != NULL)
53 {
54 const char *encoding = encodings[n];
55 if (!strcmp (encoding, "Auto") || is_encoding_supported (encoding))
56 n++;
57 }
58 assert (n < sizeof encodings / sizeof *encodings);
59 va_end (args);
60
61 if (n == 0)
62 return;
63
64 va_start (args, category);
65 if (n == 1)
42 static void
43 add_encodings (GtkTreeStore *store, struct encoding_category *cat)
44 {
45 if (cat->n_encodings == 1)
6646 {
6747 char *description;
6848
69 if (strcmp (encodings[0], "Auto"))
70 description = xasprintf ("%s (%s)", category, encodings[0]);
49 if (strcmp (cat->encodings[0], "Auto"))
50 description = xasprintf ("%s (%s)", cat->category, cat->encodings[0]);
7151 else
72 description = xstrdup (category);
52 description = xstrdup (cat->category);
7353
7454 gtk_tree_store_insert_with_values (
7555 store, NULL, NULL, G_MAXINT,
7656 COL_DESCRIPTION, description,
77 COL_ENCODING, encodings[0],
57 COL_ENCODING, cat->encodings[0],
7858 -1);
7959
8060 free (description);
8666
8767 gtk_tree_store_insert_with_values (
8868 store, &head, NULL, G_MAXINT,
89 COL_DESCRIPTION, category,
69 COL_DESCRIPTION, cat->category,
9070 -1);
9171
92 for (i = 0; i < n; i++)
72 for (i = 0; i < cat->n_encodings; i++)
9373 gtk_tree_store_insert_with_values (
9474 store, NULL, &head, G_MAXINT,
95 COL_DESCRIPTION, encodings[i],
96 COL_ENCODING, encodings[i],
75 COL_DESCRIPTION, cat->encodings[i],
76 COL_ENCODING, cat->encodings[i],
9777 -1);
9878 }
99 va_end (args);
10079 }
10180
10281 static void
141120 gboolean allow_auto)
142121 {
143122 struct find_default_encoding_aux aux;
123 struct encoding_category *categories;
124 struct encoding_category locale_cat;
125 const char *locale_encoding;
144126 GtkCellRenderer *renderer;
145127 GtkWidget *hbox;
146128 GtkWidget *combo_box;
147129 GtkTreeStore *store;
130 size_t n_categories;
131 size_t i;
148132
149133 store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
150134
151135 if (allow_auto)
152 add_encodings (store, _("Automatically Detect"), "Auto", NULL_SENTINEL);
153 add_encodings (store, _("Locale Encoding"), locale_charset (),
154 NULL_SENTINEL);
155 add_encodings (store, "Unicode", "UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE",
156 "UTF-32", "UTF-32BE", "UTF-32LE", NULL_SENTINEL);
157 add_encodings (store, _("Arabic"), "IBM864", "ISO-8859-6", "Windows-1256",
158 NULL_SENTINEL);
159 add_encodings (store, _("Armenian"), "ARMSCII-8", NULL_SENTINEL);
160 add_encodings (store, _("Baltic"), "ISO-8859-13", "ISO-8859-4",
161 "Windows-1257", NULL_SENTINEL);
162 add_encodings (store, _("Celtic"), "ISO-8859-14", NULL_SENTINEL);
163 add_encodings (store, _("Central European"), "IBM852", "ISO-8859-2",
164 "Mac-CentralEurope", "Windows-1250", NULL_SENTINEL);
165 add_encodings (store, _("Chinese Simplified"), "GB18030", "GB2312", "GBK",
166 "HZ-GB-2312", "ISO-2022-CN", NULL_SENTINEL);
167 add_encodings (store, _("Chinese Traditional"), "Big5", "Big5-HKSCS",
168 "EUC-TW", NULL_SENTINEL);
169 add_encodings (store, _("Croatian"), "MacCroatian", NULL_SENTINEL);
170 add_encodings (store, _("Cyrillic"), "IBM855", "ISO-8859-5", "ISO-IR-111",
171 "KOI8-R", "MacCyrillic", NULL_SENTINEL);
172 add_encodings (store, _("Cyrillic/Russian"), "IBM866", NULL_SENTINEL);
173 add_encodings (store, _("Cyrillic/Ukrainian"), "KOI8-U", "MacUkrainian",
174 NULL_SENTINEL);
175 add_encodings (store, _("Georgian"), "GEOSTD8", NULL_SENTINEL);
176 add_encodings (store, _("Greek"), "ISO-8859-7", "MacGreek", NULL_SENTINEL);
177 add_encodings (store, _("Gujarati"), "MacGujarati", NULL_SENTINEL);
178 add_encodings (store, _("Gurmukhi"), "MacGurmukhi", NULL_SENTINEL);
179 add_encodings (store, _("Hebrew"), "IBM862", "ISO-8859-8-I", "Windows-1255",
180 NULL_SENTINEL);
181 add_encodings (store, _("Hebrew Visual"), "ISO-8859-8", NULL_SENTINEL);
182 add_encodings (store, _("Hindi"), "MacDevangari", NULL_SENTINEL);
183 add_encodings (store, _("Icelandic"), "MacIcelandic", NULL_SENTINEL);
184 add_encodings (store, _("Japanese"), "EUC-JP", "ISO-2022-JP", "Shift_JIS",
185 NULL_SENTINEL);
186 add_encodings (store, _("Korean"), "EUC-KR", "ISO-2022-KR", "JOHAB", "UHC",
187 NULL_SENTINEL);
188 add_encodings (store, _("Nordic"), "ISO-8859-10", NULL_SENTINEL);
189 add_encodings (store, _("Romanian"), "ISO-8859-16", "MacRomanian",
190 NULL_SENTINEL);
191 add_encodings (store, _("South European"), "ISO-8859-3", NULL_SENTINEL);
192 add_encodings (store, _("Thai"), "ISO-8859-11", "TIS-620", "Windows-874",
193 NULL_SENTINEL);
194 add_encodings (store, _("Turkish"), "IBM857", "ISO-8859-9", "Windows-1254",
195 NULL_SENTINEL);
196 add_encodings (store, _("Vietnamese"), "TVCN", "VISCII", "VPS",
197 "Windows-1258", NULL_SENTINEL);
198 add_encodings (store, _("Western European"), "ISO-8859-1", "ISO-8859-15",
199 "Windows-1252", "IBM850", "MacRoman", NULL_SENTINEL);
136 {
137 struct encoding_category auto_cat;
138 const char *encoding = "Auto";
139
140 auto_cat.category = _("Automatically Detect");
141 auto_cat.encodings = &encoding;
142 auto_cat.n_encodings = 1;
143 add_encodings (store, &auto_cat);
144 }
145
146 locale_encoding = locale_charset ();
147 locale_cat.category = _("Locale Encoding");
148 locale_cat.encodings = &locale_encoding;
149 locale_cat.n_encodings = 1;
150 add_encodings (store, &locale_cat);
151
152 categories = get_encoding_categories ();
153 n_categories = get_n_encoding_categories ();
154 for (i = 0; i < n_categories; i++)
155 add_encodings (store, &categories[i]);
200156
201157 combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
202158
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17 #include "ui/gui/psppire-format.h"
18
19 static gpointer
20 psppire_format_copy (gpointer boxed)
21 {
22 struct fmt_spec *format = boxed;
23 return g_memdup (format, sizeof *format);
24 }
25
26 static void
27 psppire_format_free (gpointer boxed)
28 {
29 struct fmt_spec *format = boxed;
30 g_free (format);
31 }
32
33 GType
34 psppire_format_get_type (void)
35 {
36 static GType type = 0;
37
38 if (type == 0)
39 type = g_boxed_type_register_static ("PsppireFormat",
40 psppire_format_copy,
41 psppire_format_free);
42
43 return type;
44 }
45
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17 #ifndef PSPPIRE_FORMAT_H
18 #define PSPPIRE_FORMAT_H 1
19
20 #include <glib-object.h>
21 #include "data/format.h"
22
23 #define PSPPIRE_TYPE_FORMAT (psppire_format_get_type ())
24
25 GType psppire_format_get_type (void) G_GNUC_CONST;
26
27 #endif /* src/ui/gui/psppire-format.h */
2525
2626 #include "libpspp/cast.h"
2727
28 #include "gl/minmax.h"
29
2830 static const struct lex_reader_class lex_gtk_text_buffer_reader_class ;
2931
3032
3133 struct lex_gtk_text_buffer_reader
3234 {
3335 struct lex_reader reader;
36
37 /* The GtkTextBuffer from which we are reading. */
3438 GtkTextBuffer *buffer;
3539 GtkTextIter start;
3640 GtkTextIter stop;
41
42 /* Text pulled from part of the GtkTextBuffer. */
43 gchar *part;
44 gsize part_len; /* Number of bytes in 'part'. */
45 gsize part_ofs; /* Current offset into 'part'. */
3746 };
3847
3948 static struct lex_gtk_text_buffer_reader *
5665 r->start = start;
5766 r->stop = stop;
5867
68 r->part = NULL;
69 r->part_len = 0;
70 r->part_ofs = 0;
71
5972 return &r->reader;
6073 }
6174
6578 enum prompt_style prompt_style UNUSED)
6679 {
6780 struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_);
68 int n_chars = n;
69 char *s;
81 gsize chunk;
7082
71 GtkTextIter iter = r->start ;
72
73 int offset = gtk_text_iter_get_offset (&iter);
74 int end_offset = gtk_text_iter_get_offset (&r->stop);
83 if (r->part_ofs == r->part_len)
84 {
85 /* Read up to N characters into r->part. N characters might be more than
86 N bytes, but that's OK: we'll just buffer up some of those bytes for
87 the next read. */
88 int n_chars = n;
7589
76 if ( end_offset - offset < n)
77 n_chars = end_offset - offset;
78
79 gtk_text_iter_set_offset (&iter, offset + n_chars);
90 GtkTextIter iter = r->start ;
8091
81 s = gtk_text_iter_get_text (&r->start, &iter);
92 int offset = gtk_text_iter_get_offset (&iter);
93 int end_offset = gtk_text_iter_get_offset (&r->stop);
8294
83 strncpy (buf, s, n_chars);
95 if ( end_offset - offset < n)
96 n_chars = end_offset - offset;
8497
85 r->start = iter;
98 gtk_text_iter_set_offset (&iter, offset + n_chars);
8699
87 return strlen (s);
100 g_free (r->part);
101 r->part = gtk_text_iter_get_text (&r->start, &iter);
102 r->part_len = strlen (r->part);
103 r->part_ofs = 0;
104
105 r->start = iter;
106 }
107
108 chunk = MIN (r->part_len - r->part_ofs, n);
109 memcpy (buf, r->part + r->part_ofs, chunk);
110 r->part_ofs += chunk;
111
112 return chunk;
88113 }
89114
90115
95120 struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_);
96121
97122 g_object_unref (r->buffer);
123 g_free (r->part);
98124 }
99125
100126
954954 GtkAction *copy_action;
955955 GtkAction *select_all_action;
956956 GtkTreeSelection *sel;
957 GtkTreeModel *model;
957958
958959 string_map_init (&window->render_opts);
959960
981982
982983 g_signal_connect (sel, "changed", G_CALLBACK (on_selection_change), copy_action);
983984
984 gtk_tree_view_set_model (window->overview,
985 GTK_TREE_MODEL (gtk_tree_store_new (
985 model = GTK_TREE_MODEL (gtk_tree_store_new (
986986 N_COLS,
987987 G_TYPE_STRING, /* COL_TITLE */
988988 G_TYPE_POINTER, /* COL_ADDR */
989 G_TYPE_LONG))); /* COL_Y */
989 G_TYPE_LONG)); /* COL_Y */
990 gtk_tree_view_set_model (window->overview, model);
991 g_object_unref (model);
990992
991993 window->in_command = false;
992994
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2009, 2010 Free Software Foundation
1 Copyright (C) 2007, 2009, 2010, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
8181
8282 static guint signals [n_SIGNALS];
8383
84 /* Callback for when an item disappears from the source list.
85 By implication, this means that the item has been inserted into the
86 destination.
87 */
88 static void
89 on_row_deleted (PsppireSelector *selector)
90 {
91 g_signal_emit (selector, signals [SELECTED], 0);
92 }
93
94 /* Callback for when a new item appears in the source list.
95 By implication, this means that an item has been deleted from the
96 destination.
97 */
98 static void
99 on_row_inserted (PsppireSelector *selector)
100 {
101 g_signal_emit (selector, signals [DE_SELECTED], 0);
102 }
103
84104
85105 GType
86106 psppire_selector_get_type (void)
151171
152172
153173 static void on_click (GtkButton *b);
174 static void on_realize (GtkWidget *selector);
175
154176
155177 static void update_subjects (PsppireSelector *selector);
156178
218240 {
219241 GObjectClass *object_class = G_OBJECT_CLASS (class);
220242 GtkButtonClass *button_class = GTK_BUTTON_CLASS (class);
243 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
221244 GParamSpec *orientation_spec =
222245 g_param_spec_enum ("orientation",
223246 "Orientation",
251274
252275
253276 button_class->clicked = on_click;
277 widget_class->realize = on_realize;
278
254279
255280 object_class->set_property = psppire_selector_set_property;
256281 object_class->get_property = psppire_selector_get_property;
351376
352377
353378 static void
354 on_realize (PsppireSelector *selector)
355 {
379 on_realize (GtkWidget *w)
380 {
381 PsppireSelector *selector = PSPPIRE_SELECTOR (w);
356382 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
357383 GtkTreeSelection* selection ;
358384
359385 GList *list = g_hash_table_lookup (class->source_hash, selector->source);
386
387 if (GTK_WIDGET_CLASS (parent_class)->realize)
388 GTK_WIDGET_CLASS (parent_class)->realize (w);
360389
361390 if ( NULL == list)
362391 return;
390419 selector->filter = NULL;
391420
392421 selector->arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE);
393 selector->filtered_source = NULL;
394422
395423
396424 gtk_container_add (GTK_CONTAINER (selector), selector->arrow);
406434
407435 selector->row_activate_id = 0;
408436 selector->source_select_id = 0;
409
410 g_signal_connect (selector, "realize",
411 G_CALLBACK (on_realize), NULL);
412
413437 }
414438
415439
544568 }
545569
546570
571 /* Callback which causes the filter to be refiltered.
572 Called when the DEST GtkEntry is activated (Enter is pressed), or when it
573 looses focus.
574 */
575 static gboolean
576 refilter (PsppireSelector *selector)
577 {
578 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source));
579 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
580 return FALSE;
581 }
582
547583 /* Removes something from the DEST widget */
548584 static void
549585 de_select_selection (PsppireSelector *selector)
561597
562598 selector->selecting = FALSE;
563599
564 gtk_tree_model_filter_refilter (selector->filtered_source);
600 refilter (selector);
565601
566602 g_signal_emit (selector, signals [DE_SELECTED], 0);
567603 }
578614 GList *selected_rows =
579615 gtk_tree_selection_get_selected_rows (selection, NULL);
580616
581 GtkTreeModel *childmodel = gtk_tree_model_filter_get_model
582 (selector->filtered_source);
617 GtkTreeModel *childmodel =
618 gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source))));
583619
584620 g_return_if_fail (selector->select_items);
621
622 if (selector->allow_selection &&
623 ! selector->allow_selection (selector->source, selector->dest))
624 return;
585625
586626 selector->selecting = TRUE;
587627
593633 GtkTreeIter iter;
594634 GtkTreePath *path = item->data;
595635
596 gtk_tree_model_get_iter (GTK_TREE_MODEL (selector->filtered_source),
636 gtk_tree_model_get_iter (GTK_TREE_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source))),
597637 &iter, path);
598638
599639 gtk_tree_model_filter_convert_iter_to_child_iter
600 (selector->filtered_source,
640 (GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source))),
601641 &child_iter,
602642 &iter);
603643
611651 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
612652 g_list_free (selected_rows);
613653
614 gtk_tree_model_filter_refilter (selector->filtered_source);
654 refilter (selector);
615655
616656 g_signal_emit (selector, signals [SELECTED], 0);
617657
641681
642682 if (GTK_BUTTON_CLASS (parent_class)->clicked)
643683 GTK_BUTTON_CLASS (parent_class)->clicked (b);
644
645684 }
646685
647686 static gboolean
708747
709748 /* set the source widget to SOURCE */
710749 static void
711 set_tree_view_source (PsppireSelector *selector,
712 GtkTreeView *source)
750 set_tree_view_source (PsppireSelector *selector)
713751 {
714752 GList *list = NULL;
715753
716754 PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE);
717755
718 GtkTreeModel *model = gtk_tree_view_get_model (source);
719
720 if ( ! (list = g_hash_table_lookup (class->source_hash, source)))
721 {
722 selector->filtered_source =
723 GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
724
725 gtk_tree_view_set_model (source,
726 GTK_TREE_MODEL (selector->filtered_source));
727
756 if ( ! (list = g_hash_table_lookup (class->source_hash, selector->source)))
757 {
728758 list = g_list_append (list, selector);
729 g_hash_table_insert (class->source_hash, source, list);
730
731
732 gtk_tree_model_filter_set_visible_func (selector->filtered_source,
733 is_source_item_visible,
734 selector,
735 NULL);
759 g_hash_table_insert (class->source_hash, selector->source, list);
736760 }
737761 else
738762 { /* Append this selector to the list and push the <source,list>
739763 pair onto the hash table */
740
741 selector->filtered_source = GTK_TREE_MODEL_FILTER (model);
742764
743765 if ( NULL == g_list_find (list, selector) )
744766 {
746768 list = g_list_prepend (list, selector);
747769 else
748770 list = g_list_append (list, selector);
749 g_hash_table_replace (class->source_hash, source, list);
771 g_hash_table_replace (class->source_hash, selector->source, list);
750772 }
751773 }
752774 }
775
776
777
778 /* This function is a callback which occurs when the
779 SOURCE's model has changed */
780 static void
781 update_model (
782 GtkTreeView *source,
783 GParamSpec *psp,
784 PsppireSelector *selector
785 )
786 {
787 GtkTreeModel *model = gtk_tree_view_get_model (source);
788
789 g_assert (source == GTK_TREE_VIEW (selector->source));
790
791 if (model && (model == g_object_get_data (G_OBJECT (source), "model-copy")))
792 return;
793
794 if (model != NULL)
795 {
796 GtkTreeModel *new_model = gtk_tree_model_filter_new (model, NULL);
797
798 g_object_set_data (G_OBJECT (source), "model-copy", new_model);
799
800 gtk_tree_view_set_model (source, new_model);
801
802 gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (new_model),
803 is_source_item_visible,
804 selector,
805 NULL);
806
807 g_signal_connect_swapped (new_model,
808 "row-deleted",
809 G_CALLBACK (on_row_deleted), selector);
810
811 g_signal_connect_swapped (new_model,
812 "row-inserted",
813 G_CALLBACK (on_row_inserted), selector);
814
815 g_object_unref (new_model);
816 }
817 }
818
753819
754820
755821 /*
765831
766832 if ( selector->selecting) return;
767833
768 gtk_tree_model_filter_refilter (selector->filtered_source);
834 refilter (selector);
769835 }
770836
771837
778844
779845 if ( selector->selecting ) return;
780846
781 gtk_tree_model_filter_refilter (selector->filtered_source);
847 refilter (selector);
782848 }
783849
784850
787853 {
788854 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->dest));
789855
790 g_signal_connect (model, "row-changed", G_CALLBACK (on_dest_data_change),
791 selector);
792
793 g_signal_connect (model, "row-deleted", G_CALLBACK (on_dest_data_delete),
794 selector);
856 if ( model )
857 {
858 g_signal_connect (model, "row-changed", G_CALLBACK (on_dest_data_change),
859 selector);
860
861 g_signal_connect (model, "row-deleted", G_CALLBACK (on_dest_data_delete),
862 selector);
863 }
795864 }
796865
797866 /* Set the destination widget to DEST */
813882 }
814883
815884
816 /* Callback which causes the filter to be refiltered.
817 Called when the DEST GtkEntry is activated (Enter is pressed), or when it
818 looses focus.
819 */
820 static gboolean
821 refilter (PsppireSelector *selector)
822 {
823 gtk_tree_model_filter_refilter (selector->filtered_source);
824 return FALSE;
825 }
826885
827886
828887 /* Callback for when the DEST GtkEntry is selected (clicked) */
838897 }
839898
840899
841 /* Callback for when an item disappears from the source list.
842 By implication, this means that the item has been inserted into the
843 destination.
844 */
845 static void
846 on_row_deleted (PsppireSelector *selector)
847 {
848 g_signal_emit (selector, signals [SELECTED], 0);
849 }
850
851 /* Callback for when a new item appears in the source list.
852 By implication, this means that an item has been deleted from the
853 destination.
854 */
855 static void
856 on_row_inserted (PsppireSelector *selector)
857 {
858 g_signal_emit (selector, signals [DE_SELECTED], 0);
859 }
860
861
862900
863901 /* Set DEST to be the destination GtkEntry widget */
864902 static void
878916 selector);
879917
880918
881 g_signal_connect_swapped (selector->filtered_source, "row-deleted",
882 G_CALLBACK (on_row_deleted), selector);
883
884 g_signal_connect_swapped (selector->filtered_source, "row-inserted",
885 G_CALLBACK (on_row_inserted), selector);
886919 }
887920
888921 static void
895928 }
896929 }
897930
931
898932 static void
899933 update_subjects (PsppireSelector *selector)
900934 {
901 GtkTreeModel *model = NULL;
902
903935 if ( NULL == selector->dest )
904936 return;
905937
908940 if ( NULL == selector->source )
909941 return;
910942
911 g_signal_connect_swapped (selector->source, "notify::model",
912 G_CALLBACK (update_subjects), selector);
913
914 model = gtk_tree_view_get_model (GTK_TREE_VIEW (selector->source));
915
916 if ( NULL == model)
917 return;
918
919
920943 if ( GTK_IS_TREE_VIEW (selector->source))
921 set_tree_view_source (selector, GTK_TREE_VIEW (selector->source) );
944 {
945 set_tree_view_source (selector);
946
947 g_signal_connect (selector->source, "notify::model",
948 G_CALLBACK (update_model), selector);
949
950 update_model (GTK_TREE_VIEW (selector->source), 0, selector);
951 }
922952 else
923953 g_error ("Unsupported source widget: %s", G_OBJECT_TYPE_NAME (selector->source));
924954
8686
8787 gint orientation;
8888
89 GtkTreeModelFilter *filtered_source;
90
9189 SelectItemsFunc *select_items;
9290 gpointer select_user_data;
9391
9694 AllowSelectionFunc *allow_selection;
9795
9896 gulong row_activate_id ;
99
10097 gulong source_select_id ;
10198
10299 gboolean primary_requested;
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17 #include "psppire-value-entry.h"
18 #include "data/data-in.h"
19 #include "data/value-labels.h"
20 #include "data/variable.h"
21 #include "libpspp/cast.h"
22 #include "libpspp/i18n.h"
23 #include "ui/gui/helper.h"
24 #include "ui/gui/psppire-format.h"
25
26 static void psppire_value_entry_finalize (GObject *);
27
28 G_DEFINE_TYPE (PsppireValueEntry,
29 psppire_value_entry,
30 GTK_TYPE_COMBO_BOX_ENTRY);
31
32 enum
33 {
34 COL_LABEL, /* Value label string. */
35 COL_VALUE, /* union value *. */
36 N_COLUMNS
37 };
38
39 enum
40 {
41 PROP_0,
42 PROP_SHOW_VALUE_LABEL,
43 PROP_VARIABLE,
44 PROP_VALUE_LABELS,
45 PROP_FORMAT,
46 PROP_ENCODING,
47 PROP_WIDTH
48 };
49
50 static void
51 psppire_value_entry_set_property (GObject *object,
52 guint prop_id,
53 const GValue *value,
54 GParamSpec *pspec)
55 {
56 PsppireValueEntry *obj = PSPPIRE_VALUE_ENTRY (object);
57
58 switch (prop_id)
59 {
60 case PROP_SHOW_VALUE_LABEL:
61 psppire_value_entry_set_show_value_label (obj,
62 g_value_get_boolean (value));
63 break;
64
65 case PROP_VARIABLE:
66 psppire_value_entry_set_variable (obj, g_value_get_pointer (value));
67 break;
68
69 case PROP_VALUE_LABELS:
70 psppire_value_entry_set_value_labels (obj, g_value_get_pointer (value));
71 break;
72
73 case PROP_FORMAT:
74 psppire_value_entry_set_format (obj, g_value_get_boxed (value));
75 break;
76
77 case PROP_ENCODING:
78 psppire_value_entry_set_encoding (obj, g_value_get_string (value));
79 break;
80
81 case PROP_WIDTH:
82 psppire_value_entry_set_width (obj, g_value_get_int (value));
83 break;
84
85 default:
86 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
87 break;
88 }
89 }
90
91 static void
92 psppire_value_entry_get_property (GObject *object,
93 guint prop_id,
94 GValue *value,
95 GParamSpec *pspec)
96 {
97 PsppireValueEntry *obj = PSPPIRE_VALUE_ENTRY (object);
98
99 switch (prop_id)
100 {
101 case PROP_SHOW_VALUE_LABEL:
102 g_value_set_boolean (value,
103 psppire_value_entry_get_show_value_label (obj));
104 break;
105
106 case PROP_VARIABLE:
107 g_return_if_reached ();
108
109 case PROP_VALUE_LABELS:
110 g_value_set_pointer (value, obj->val_labs);
111 break;
112
113 case PROP_FORMAT:
114 g_value_set_boxed (value, &obj->format);
115 break;
116
117 case PROP_ENCODING:
118 g_value_set_string (value, psppire_value_entry_get_encoding (obj));
119 break;
120
121 case PROP_WIDTH:
122 g_value_set_int (value, psppire_value_entry_get_width (obj));
123 break;
124
125 default:
126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
127 break;
128 }
129 }
130
131 static void
132 psppire_value_entry_class_init (PsppireValueEntryClass *class)
133 {
134 GObjectClass *gobject_class;
135 gobject_class = G_OBJECT_CLASS (class);
136
137 gobject_class->finalize = psppire_value_entry_finalize;
138 gobject_class->set_property = psppire_value_entry_set_property;
139 gobject_class->get_property = psppire_value_entry_get_property;
140
141 g_object_class_install_property (
142 gobject_class, PROP_SHOW_VALUE_LABEL,
143 g_param_spec_boolean ("show-value-label",
144 "Show Value Label",
145 "If true, a value that has a value label is shown "
146 "as the label. If false, all values are shown "
147 "literally.",
148 TRUE,
149 G_PARAM_WRITABLE | G_PARAM_READABLE));
150
151 g_object_class_install_property (
152 gobject_class, PROP_VARIABLE,
153 g_param_spec_pointer ("variable",
154 "Variable",
155 "Set to configure the PsppireValueEntry according "
156 "to the specified variable's value labels, format, "
157 "width, and encoding.",
158 G_PARAM_WRITABLE));
159
160 g_object_class_install_property (
161 gobject_class, PROP_VALUE_LABELS,
162 g_param_spec_pointer ("value-labels",
163 "Value Labels",
164 "The set of value labels from which the user may "
165 "choose and which is used to display the value (if "
166 "value labels are to be displayed)",
167 G_PARAM_READABLE | G_PARAM_WRITABLE));
168
169 g_object_class_install_property (
170 gobject_class, PROP_FORMAT,
171 g_param_spec_boxed ("format",
172 "Format",
173 "The format used to display values (that are not "
174 "displayed as value labels) and to interpret values "
175 "entered.",
176 PSPPIRE_TYPE_FORMAT,
177 G_PARAM_READABLE | G_PARAM_WRITABLE));
178
179 g_object_class_install_property (
180 gobject_class, PROP_ENCODING,
181 g_param_spec_string ("encoding",
182 "Encoding",
183 "The encoding (e.g. \"UTF-8\") for string values. "
184 "For numeric values this setting has no effect.",
185 "UTF-8",
186 G_PARAM_READABLE | G_PARAM_WRITABLE));
187
188 g_object_class_install_property (
189 gobject_class, PROP_WIDTH,
190 g_param_spec_int ("width",
191 "Width",
192 "Width of the value, either 0 for a numeric value or "
193 "a positive integer count of bytes for string values.",
194 0, MAX_STRING,
195 0,
196 G_PARAM_READABLE | G_PARAM_WRITABLE));
197 }
198
199 static void
200 psppire_value_entry_text_changed (GtkEntryBuffer *buffer,
201 GParamSpec *pspec,
202 PsppireValueEntry *obj)
203 {
204 obj->cur_value = NULL;
205 }
206
207 static void
208 psppire_value_entry_init (PsppireValueEntry *obj)
209 {
210 GtkEntry *entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (obj)));
211 GtkEntryBuffer *buffer = gtk_entry_get_buffer (entry);
212
213 obj->show_value_label = true;
214 obj->val_labs = NULL;
215 obj->format = F_8_0;
216 obj->encoding = NULL;
217 obj->cur_value = NULL;
218 gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (obj), COL_LABEL);
219
220 g_signal_connect (buffer, "notify::text",
221 G_CALLBACK (psppire_value_entry_text_changed), obj);
222 }
223
224 static void
225 psppire_value_entry_finalize (GObject *gobject)
226 {
227 PsppireValueEntry *obj = PSPPIRE_VALUE_ENTRY (gobject);
228
229 val_labs_destroy (obj->val_labs);
230 g_free (obj->encoding);
231
232 G_OBJECT_CLASS (psppire_value_entry_parent_class)->finalize (gobject);
233 }
234
235 GtkWidget *
236 psppire_value_entry_new (void)
237 {
238 return GTK_WIDGET (g_object_new (PSPPIRE_TYPE_VALUE_ENTRY, NULL));
239 }
240
241 static void
242 psppire_value_entry_refresh_model (PsppireValueEntry *obj)
243 {
244 GtkTreeModel *model;
245 GtkTreeModel *old_model;
246
247 if (val_labs_count (obj->val_labs) > 0)
248 {
249 const struct val_lab **vls = val_labs_sorted (obj->val_labs);
250 size_t n_vls = val_labs_count (obj->val_labs);
251
252 GtkListStore *list_store;
253 size_t i;
254
255 list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
256 model = GTK_TREE_MODEL (list_store);
257 for (i = 0; i < n_vls; i++)
258 {
259 const struct val_lab *vl = vls[i];
260 GtkTreeIter iter;
261
262 gtk_list_store_append (list_store, &iter);
263 gtk_list_store_set (list_store, &iter,
264 COL_LABEL, val_lab_get_label (vl),
265 COL_VALUE, val_lab_get_value (vl),
266 -1);
267 }
268 free (vls);
269 }
270 else
271 model = NULL;
272
273 old_model = gtk_combo_box_get_model (GTK_COMBO_BOX (obj));
274
275 if (old_model != model)
276 {
277 GtkEntry *entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (obj)));
278 gtk_entry_set_text (entry, "");
279 }
280
281 gtk_combo_box_set_model (GTK_COMBO_BOX (obj), model);
282 if (model != NULL)
283 g_object_unref (model);
284 }
285
286 void
287 psppire_value_entry_set_show_value_label (PsppireValueEntry *obj,
288 gboolean show_value_label)
289 {
290 if (obj->show_value_label != show_value_label)
291 {
292 obj->show_value_label = show_value_label;
293 g_object_notify (G_OBJECT (obj), "show-value-label");
294 }
295 }
296
297 gboolean
298 psppire_value_entry_get_show_value_label (const PsppireValueEntry *obj)
299 {
300 return obj->show_value_label;
301 }
302
303 void
304 psppire_value_entry_set_variable (PsppireValueEntry *obj,
305 const struct variable *var)
306 {
307 if (var != NULL)
308 {
309 psppire_value_entry_set_value_labels (obj, var_get_value_labels (var));
310 obj->format = *var_get_print_format (var);
311 psppire_value_entry_set_encoding (obj, var_get_encoding (var));
312 }
313 else
314 psppire_value_entry_set_value_labels (obj, NULL);
315 }
316
317 void
318 psppire_value_entry_set_value_labels (PsppireValueEntry *obj,
319 const struct val_labs *val_labs)
320 {
321 if (!val_labs_equal (obj->val_labs, val_labs))
322 {
323 obj->cur_value = NULL;
324
325 val_labs_destroy (obj->val_labs);
326 obj->val_labs = val_labs_clone (val_labs);
327
328 if (val_labs != NULL)
329 {
330 int width = val_labs_get_width (val_labs);
331 if (width != fmt_var_width (&obj->format))
332 obj->format = fmt_default_for_width (width);
333 }
334
335 psppire_value_entry_refresh_model (obj);
336
337 g_object_notify (G_OBJECT (obj), "value-labels");
338 }
339 }
340
341 const struct val_labs *
342 psppire_value_entry_get_value_labels (const PsppireValueEntry *obj)
343 {
344 return obj->val_labs;
345 }
346
347 void
348 psppire_value_entry_set_format (PsppireValueEntry *obj,
349 const struct fmt_spec *format)
350 {
351 if (!fmt_equal (format, &obj->format))
352 {
353 obj->cur_value = NULL;
354 obj->format = *format;
355
356 if (obj->val_labs
357 && val_labs_get_width (obj->val_labs) != fmt_var_width (format))
358 psppire_value_entry_set_value_labels (obj, NULL);
359
360 g_object_notify (G_OBJECT (obj), "format");
361 }
362 }
363
364 const struct fmt_spec *
365 psppire_value_entry_get_format (const PsppireValueEntry *obj)
366 {
367 return &obj->format;
368 }
369
370 void
371 psppire_value_entry_set_encoding (PsppireValueEntry *obj,
372 const gchar *encoding)
373 {
374 g_free (obj->encoding);
375 obj->encoding = encoding != NULL ? g_strdup (encoding) : NULL;
376
377 g_object_notify (G_OBJECT (obj), "encoding");
378 }
379
380 const gchar *
381 psppire_value_entry_get_encoding (const PsppireValueEntry *obj)
382 {
383 return obj->encoding ? obj->encoding : UTF8;
384 }
385
386 void
387 psppire_value_entry_set_width (PsppireValueEntry *obj, int width)
388 {
389 if (width != fmt_var_width (&obj->format))
390 {
391 struct fmt_spec format = fmt_default_for_width (width);
392 psppire_value_entry_set_format (obj, &format);
393 }
394 }
395
396 int
397 psppire_value_entry_get_width (const PsppireValueEntry *obj)
398 {
399 return fmt_var_width (&obj->format);
400 }
401
402 void
403 psppire_value_entry_set_value (PsppireValueEntry *obj,
404 const union value *value,
405 int width)
406 {
407 GtkEntry *entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (obj)));
408 gchar *string;
409
410 obj->cur_value = NULL;
411 if (obj->show_value_label)
412 {
413 struct val_lab *vl = val_labs_lookup (obj->val_labs, value);
414 if (vl != NULL)
415 {
416 gtk_entry_set_text (entry, val_lab_get_label (vl));
417 obj->cur_value = val_lab_get_value (vl);
418 return;
419 }
420 }
421
422 string = value_to_text__ (*value, &obj->format, obj->encoding);
423 gtk_entry_set_text (entry, string);
424 g_free (string);
425 }
426
427 gboolean
428 psppire_value_entry_get_value (PsppireValueEntry *obj,
429 union value *value,
430 int width)
431 {
432 GtkEntry *entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (obj)));
433 GtkTreeIter iter;
434
435 g_return_val_if_fail (fmt_var_width (&obj->format) == width, FALSE);
436
437 if (obj->cur_value)
438 {
439 value_copy (value, obj->cur_value, width);
440 return TRUE;
441 }
442 else if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (obj), &iter))
443 {
444 union value *v;
445
446 gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (obj)), &iter,
447 COL_VALUE, &v,
448 -1);
449 value_copy (value, v, width);
450 return TRUE;
451 }
452 else
453 {
454 const gchar *new_text;
455
456 new_text = gtk_entry_get_text (entry);
457 return data_in_msg (ss_cstr (new_text), UTF8,
458 obj->format.type,
459 value, width, obj->encoding);
460 }
461 }
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef PSPPIRE_VALUE_ENTRY_H
17 #define PSPPIRE_VALUE_ENTRY_H 1
18
19 #include <gtk/gtk.h>
20 #include "data/format.h"
21
22 /* PsppireValueEntry is a subclass of GtkComboBoxEntry that is specialized for
23 displaying and entering "union value"s. Its main advantage over a plain
24 GtkEntry is that, when value labels are supplied, it (optionally) displays
25 the value label instead of the value. It also allows the user to choose a
26 new value by label from the drop-down list.
27
28 The easiest way to use a PsppireValueEntry is to hand it a particular
29 variable whose values are to be displayed, using
30 psppire_value_entry_set_variable(). If you do that, you don't need any of
31 the other functions to set value labels, format, encoding, width, etc.,
32 because all of those are determined from the variable. The other functions
33 are useful if no variable is available. */
34
35 G_BEGIN_DECLS
36
37 union value;
38 struct fmt_spec;
39 struct val_labs;
40 struct variable;
41
42 #define PSPPIRE_TYPE_VALUE_ENTRY (psppire_value_entry_get_type())
43 #define PSPPIRE_VALUE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_VALUE_ENTRY,PsppireValueEntry))
44 #define PSPPIRE_VALUE_ENTRY_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_VALUE_ENTRY,PsppireValueEntryClass))
45 #define PSPPIRE_IS_VALUE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_VALUE_ENTRY))
46 #define PSPPIRE_IS_VALUE_ENTRY_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_VALUE_ENTRY))
47 #define PSPPIRE_VALUE_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_VALUE_ENTRY,PsppireValueEntryClass))
48
49 typedef struct _PsppireValueEntry PsppireValueEntry;
50 typedef struct _PsppireValueEntryClass PsppireValueEntryClass;
51
52 struct _PsppireValueEntry
53 {
54 GtkComboBoxEntry parent;
55
56 gboolean show_value_label;
57
58 struct val_labs *val_labs;
59 struct fmt_spec format;
60 gchar *encoding;
61
62 const union value *cur_value;
63 };
64
65 struct _PsppireValueEntryClass
66 {
67 GtkComboBoxEntryClass parent_class;
68 };
69
70 GType psppire_value_entry_get_type (void);
71 GtkWidget *psppire_value_entry_new (void);
72
73 void psppire_value_entry_set_show_value_label (PsppireValueEntry *,
74 gboolean show_value_label);
75 gboolean psppire_value_entry_get_show_value_label (const PsppireValueEntry *);
76
77 void psppire_value_entry_set_variable (PsppireValueEntry *,
78 const struct variable *);
79
80 void psppire_value_entry_set_value_labels (PsppireValueEntry *,
81 const struct val_labs *);
82 const struct val_labs *
83 psppire_value_entry_get_value_labels (const PsppireValueEntry *);
84
85 void psppire_value_entry_set_format (PsppireValueEntry *,
86 const struct fmt_spec *);
87 const struct fmt_spec *
88 psppire_value_entry_get_format (const PsppireValueEntry *);
89
90 void psppire_value_entry_set_encoding (PsppireValueEntry *, const gchar *);
91 const gchar *psppire_value_entry_get_encoding (const PsppireValueEntry *);
92
93 void psppire_value_entry_set_width (PsppireValueEntry *, int width);
94 int psppire_value_entry_get_width (const PsppireValueEntry *);
95
96 void psppire_value_entry_set_value (PsppireValueEntry *,
97 const union value *,
98 int width);
99 gboolean psppire_value_entry_get_value (PsppireValueEntry *,
100 union value *,
101 int width);
102
103 G_END_DECLS
104
105 #endif /* PSPPIRE_VALUE_ENTRY_H */
00 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation
1 Copyright (C) 2006, 2009, 2010, 2011, 2012 Free Software Foundation
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
5151
5252
5353 static void
54 var_delete_callback (GtkWidget *w, gint dict_idx, gint case_idx, gint val_cnt, gpointer data)
54 var_delete_callback (GtkWidget *w, const struct variable *var UNUSED,
55 gint dict_idx, gint case_idx UNUSED, gpointer data)
5556 {
5657 PsppireSheetModel *model = PSPPIRE_SHEET_MODEL (data);
5758
0 #
1 # Avoid making buttons inside the PSPPIRE data sheet and variable sheet
2 # extra-tall. This allows more rows to fit on the screen, making data
3 # easier to review.
4 #
5 style "thinbuttons" { ythickness = 0 }
6 widget_class "*<PsppSheetView>*GtkButton" style : rc "thinbuttons"
+0
-388
src/ui/gui/rank-dialog.c less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "rank-dialog.h"
19
20 #include <gtk/gtk.h>
21 #include <stdlib.h>
22
23 #include <ui/gui/psppire-data-window.h>
24 #include <ui/gui/dialog-common.h>
25 #include <ui/gui/dict-display.h>
26 #include <ui/gui/builder-wrapper.h>
27 #include <ui/gui/psppire-dialog.h>
28 #include <ui/gui/psppire-var-store.h>
29 #include <ui/gui/psppire-var-view.h>
30 #include "executor.h"
31 #include "helper.h"
32
33 #include "gettext.h"
34 #define _(msgid) gettext (msgid)
35 #define N_(msgid) msgid
36
37
38 enum RANK_FUNC
39 {
40 RANK,
41 NORMAL,
42 PERCENT,
43 RFRACTION,
44 PROPORTION,
45 N,
46 NTILES,
47 SAVAGE,
48 n_RANK_FUNCS
49 };
50
51
52
53
54 struct rank_dialog
55 {
56 PsppireDict *dict;
57 GtkWidget *rank_vars;
58 GtkWidget *group_vars;
59 GtkWidget *dialog;
60
61 GtkToggleButton *ascending_togglebutton;
62 GtkToggleButton *summary_togglebutton;
63
64
65 /* Types subdialog widgets */
66
67 GtkWidget *types_dialog;
68 GtkWidget *ntiles_entry;
69
70 GtkToggleButton *func_button[n_RANK_FUNCS];
71 GtkWidget *formula_box;
72
73 GtkToggleButton *blom;
74 GtkToggleButton *tukey;
75 GtkToggleButton *rankit;
76 GtkToggleButton *vw;
77
78 /* Ties subdialog widgets */
79
80 PsppireDialog *ties_dialog;
81 GtkToggleButton *mean;
82 GtkToggleButton *low;
83 GtkToggleButton *high;
84 GtkToggleButton *condense;
85 };
86
87 static void
88 refresh (PsppireDialog *dialog, struct rank_dialog *rd)
89 {
90 GtkTreeModel *liststore;
91
92 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->rank_vars));
93 gtk_list_store_clear (GTK_LIST_STORE (liststore));
94
95 liststore = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->group_vars));
96 gtk_list_store_clear (GTK_LIST_STORE (liststore));
97
98 gtk_toggle_button_set_active (rd->ascending_togglebutton, TRUE);
99 gtk_toggle_button_set_active (rd->summary_togglebutton, FALSE);
100 }
101
102 static char *
103 generate_syntax (const struct rank_dialog *rd)
104 {
105 gchar *text;
106
107 GtkTreeModel *gs = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->group_vars));
108
109 GtkTreeIter notused;
110
111 GString *str = g_string_new ("RANK VARIABLES=");
112
113 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->rank_vars), 0, str);
114
115 g_string_append_printf (str, " (%c)",
116 gtk_toggle_button_get_active (rd->ascending_togglebutton)
117 ?'A':'D');
118
119 if ( gtk_tree_model_get_iter_first (gs, &notused) )
120 {
121 g_string_append (str, "\n\tBY ");
122
123 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->group_vars), 0, str);
124 }
125
126 g_string_append (str, "\n\t/PRINT = ");
127 if (gtk_toggle_button_get_active (rd->summary_togglebutton))
128 g_string_append (str, "YES");
129 else
130 g_string_append (str, "NO");
131
132
133 if (gtk_toggle_button_get_active (rd->func_button [RANK]))
134 g_string_append (str, "\n\t/RANK");
135 if (gtk_toggle_button_get_active (rd->func_button [NORMAL]))
136 g_string_append (str, "\n\t/NORMAL");
137 if (gtk_toggle_button_get_active (rd->func_button [PROPORTION]))
138 g_string_append (str, "\n\t/PROPORTION");
139 if (gtk_toggle_button_get_active (rd->func_button [PERCENT]))
140 g_string_append (str, "\n\t/PERCENT");
141 if (gtk_toggle_button_get_active (rd->func_button [RFRACTION]))
142 g_string_append (str, "\n\t/RFRACTION");
143 if (gtk_toggle_button_get_active (rd->func_button [N]))
144 g_string_append (str, "\n\t/N");
145 if (gtk_toggle_button_get_active (rd->func_button [SAVAGE]))
146 g_string_append (str, "\n\t/SAVAGE");
147 if (gtk_toggle_button_get_active (rd->func_button [NTILES]))
148 {
149 gint n = gtk_spin_button_get_value (GTK_SPIN_BUTTON (rd->ntiles_entry));
150 g_string_append_printf (str, "\n\t/NTILES(%d)", n);
151 }
152
153
154 if (gtk_toggle_button_get_active (rd->func_button [NORMAL])
155 ||
156 gtk_toggle_button_get_active (rd->func_button [PROPORTION]))
157 {
158 g_string_append (str, "\n\t/FRACTION=");
159
160 if ( gtk_toggle_button_get_active (rd->blom))
161 g_string_append (str, "BLOM");
162 else if ( gtk_toggle_button_get_active (rd->tukey))
163 g_string_append (str, "TUKEY");
164 else if ( gtk_toggle_button_get_active (rd->rankit))
165 g_string_append (str, "RANKIT");
166 else if ( gtk_toggle_button_get_active (rd->vw))
167 g_string_append (str, "VW");
168 }
169
170 g_string_append (str, "\n\t/TIES=");
171 if ( gtk_toggle_button_get_active (rd->mean))
172 g_string_append (str, "MEAN");
173 else if ( gtk_toggle_button_get_active (rd->low))
174 g_string_append (str, "LOW");
175 else if ( gtk_toggle_button_get_active (rd->high))
176 g_string_append (str, "HIGH");
177 else if ( gtk_toggle_button_get_active (rd->condense))
178 g_string_append (str, "CONDENSE");
179
180
181 g_string_append (str, ".");
182
183 text = str->str;
184
185 g_string_free (str, FALSE);
186
187 return text;
188 }
189
190 /* Dialog is valid iff at least one variable has been selected */
191 static gboolean
192 dialog_state_valid (gpointer data)
193 {
194 struct rank_dialog *rd = data;
195
196 GtkTreeModel *vars = gtk_tree_view_get_model (GTK_TREE_VIEW (rd->rank_vars));
197
198 GtkTreeIter notused;
199
200 return gtk_tree_model_get_iter_first (vars, &notused);
201 }
202
203 static void on_ntiles_toggle (GtkToggleButton *, gpointer);
204 static void run_types_dialog (GtkButton *, gpointer);
205 static void run_ties_dialog (GtkButton *, gpointer );
206
207 static void
208 set_sensitivity (struct rank_dialog *rd)
209 {
210 gboolean sens = gtk_toggle_button_get_active
211 (GTK_TOGGLE_BUTTON (rd->func_button[PROPORTION]))
212 ||
213 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rd->func_button[NORMAL]));
214
215 gtk_widget_set_sensitive (rd->formula_box, sens);
216 }
217
218 /* Pops up the Rank dialog box */
219 void
220 rank_dialog (PsppireDataWindow *de)
221 {
222 gint response;
223
224 struct rank_dialog rd;
225
226 GtkBuilder * builder = builder_new ("rank.ui");
227
228 GtkWidget *vars = get_widget_assert (builder, "dict-treeview");
229
230 GtkWidget *types_button = get_widget_assert (builder, "button1");
231 GtkWidget *ties_button = get_widget_assert (builder, "button2");
232
233 PsppireVarStore *vs = NULL;
234
235 g_object_get (de->data_editor, "var-store", &vs, NULL);
236
237 g_object_get (vs, "dictionary", &rd.dict, NULL);
238 rd.rank_vars = get_widget_assert (builder, "variables-treeview");
239 rd.group_vars = get_widget_assert (builder, "group-vars-treeview");
240 rd.dialog = get_widget_assert (builder, "rank-dialog");
241 rd.ascending_togglebutton =
242 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "radiobutton1"));
243
244 rd.summary_togglebutton =
245 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "summary-checkbutton"));
246
247 rd.types_dialog = get_widget_assert (builder, "rank-types-dialog");
248
249
250 rd.ntiles_entry = get_widget_assert (builder, "ntiles-entry");
251
252 rd.func_button[RANK] =
253 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "rank-checkbutton"));
254
255 rd.func_button[SAVAGE] =
256 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "savage-checkbutton"));
257
258 rd.func_button[RFRACTION] =
259 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "rfrac-checkbutton"));
260
261 rd.func_button[PERCENT] =
262 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "percent-checkbutton"));
263
264 rd.func_button[N] =
265 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "sum-checkbutton"));
266
267 rd.func_button[NTILES] =
268 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "ntiles-checkbutton"));
269
270 rd.func_button[PROPORTION] =
271 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "prop-checkbutton"));
272
273 rd.func_button[NORMAL] =
274 GTK_TOGGLE_BUTTON (get_widget_assert (builder, "normal-checkbutton"));
275
276 rd.formula_box = get_widget_assert (builder, "formula-frame");
277
278 rd.blom = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "blom-button"));
279 rd.tukey = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "tukey-button"));
280 rd.rankit = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "rankit-button"));
281 rd.vw = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "vw-button"));
282
283 /* Ties dialog */
284 rd.ties_dialog = PSPPIRE_DIALOG (get_widget_assert (builder, "ties-dialog"));
285
286 rd.mean = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "mean-button"));
287 rd.low = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "low-button"));
288 rd.high = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "high-button"));
289 rd.condense = GTK_TOGGLE_BUTTON (get_widget_assert (builder, "condense-button"));
290
291 g_signal_connect_swapped (rd.func_button[PROPORTION], "toggled",
292 G_CALLBACK (set_sensitivity),
293 &rd);
294
295 g_signal_connect_swapped (rd.func_button[NORMAL], "toggled",
296 G_CALLBACK (set_sensitivity),
297 &rd);
298
299 g_signal_connect (rd.func_button[NTILES], "toggled",
300 G_CALLBACK (on_ntiles_toggle),
301 rd.ntiles_entry);
302
303 gtk_window_set_transient_for (GTK_WINDOW (rd.dialog), GTK_WINDOW (de));
304
305 g_object_set (vars, "model", rd.dict, NULL);
306
307 g_signal_connect (types_button, "clicked",
308 G_CALLBACK (run_types_dialog), &rd);
309
310 g_signal_connect (ties_button, "clicked",
311 G_CALLBACK (run_ties_dialog), &rd);
312
313 g_signal_connect (rd.dialog, "refresh", G_CALLBACK (refresh), &rd);
314
315 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (rd.dialog),
316 dialog_state_valid, &rd);
317
318 response = psppire_dialog_run (PSPPIRE_DIALOG (rd.dialog));
319
320
321 switch (response)
322 {
323 case GTK_RESPONSE_OK:
324 g_free (execute_syntax_string (de, generate_syntax (&rd)));
325 break;
326 case PSPPIRE_RESPONSE_PASTE:
327 g_free (paste_syntax_to_window (generate_syntax (&rd)));
328 break;
329 default:
330 break;
331 }
332
333 g_object_unref (builder);
334 }
335
336
337 static void
338 types_dialog_reset (struct rank_dialog *rd)
339 {
340 gint i;
341
342 for (i = 0 ; i < n_RANK_FUNCS ; ++i )
343 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rd->func_button [i]),
344 FALSE);
345
346 gtk_widget_set_sensitive (rd->ntiles_entry, FALSE);
347
348 gtk_widget_set_sensitive (rd->formula_box, FALSE);
349 }
350
351
352
353 static void
354 run_types_dialog (GtkButton *b, gpointer data)
355 {
356 struct rank_dialog *rd = data;
357 gint response;
358
359 gtk_window_set_transient_for (GTK_WINDOW (rd->types_dialog),
360 GTK_WINDOW (rd->dialog));
361
362 types_dialog_reset (rd);
363
364 response = psppire_dialog_run (PSPPIRE_DIALOG (rd->types_dialog));
365 }
366
367 static void
368 run_ties_dialog (GtkButton *b, gpointer data)
369 {
370 struct rank_dialog *rd = data;
371 gint response;
372
373 gtk_window_set_transient_for (GTK_WINDOW (rd->ties_dialog),
374 GTK_WINDOW (rd->dialog));
375
376
377 response = psppire_dialog_run (PSPPIRE_DIALOG (rd->ties_dialog));
378 }
379
380
381 static void
382 on_ntiles_toggle (GtkToggleButton *toggle_button, gpointer data)
383 {
384 GtkWidget *w = data;
385 gboolean active = gtk_toggle_button_get_active (toggle_button);
386 gtk_widget_set_sensitive (w, active);
387 }
+0
-25
src/ui/gui/rank-dialog.h less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef __RANK_DIALOG_H
17 #define __RANK_DIALOG_H
18
19
20 #include "psppire-data-window.h"
21
22 void rank_dialog (PsppireDataWindow *);
23
24 #endif
5454 <property name="visible">True</property>
5555 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
5656 <property name="xalign">0</property>
57 <property name="label" translatable="yes">By:</property>
57 <property name="label" translatable="yes">_By:</property>
58 <property name="use_underline">True</property>
59 <property name="mnemonic_widget">group-vars-treeview</property>
5860 </object>
5961 <packing>
6062 <property name="expand">False</property>
101103 <property name="visible">True</property>
102104 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
103105 <property name="xalign">0</property>
104 <property name="label" translatable="yes">Variable(s):</property>
106 <property name="label" translatable="yes">_Variable(s):</property>
107 <property name="use_underline">True</property>
108 <property name="mnemonic_widget">variables-treeview</property>
105109 </object>
106110 <packing>
107111 <property name="expand">False</property>
+0
-301
src/ui/gui/regression-dialog.c less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2008, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "checkbox-treeview.h"
19 #include "regression-dialog.h"
20 #include "executor.h"
21
22 #include <gtk/gtk.h>
23 #include <stdlib.h>
24
25 #include <ui/gui/psppire-data-window.h>
26 #include <ui/gui/dialog-common.h>
27 #include <ui/gui/dict-display.h>
28 #include <ui/gui/builder-wrapper.h>
29 #include <ui/gui/helper.h>
30 #include <ui/gui/psppire-dialog.h>
31 #include <ui/gui/psppire-var-store.h>
32 #include <ui/gui/psppire-var-view.h>
33
34
35 #include "gettext.h"
36 #define _(msgid) gettext (msgid)
37 #define N_(msgid) msgid
38
39
40 #define REGRESSION_STATS \
41 RG (COEFF, N_("Coeff")) \
42 RG (R, N_("R")) \
43 RG (ANOVA, N_("Anova")) \
44 RG (BCOV, N_("Bcov"))
45 enum
46 {
47 #define RG(NAME, LABEL) RG_##NAME,
48 REGRESSION_STATS
49 #undef RG
50 N_REGRESSION_STATS
51 };
52
53 enum
54 {
55 #define RG(NAME, LABEL) B_RG_##NAME = 1u << RG_##NAME,
56 REGRESSION_STATS
57 #undef RG
58 B_RG_STATS_ALL = (1u << N_REGRESSION_STATS) - 1,
59 B_RG_STATS_DEFAULT = B_RG_ANOVA | B_RG_COEFF | B_RG_R
60 };
61
62 static const struct checkbox_entry_item stats[] =
63 {
64 #define RG(NAME, LABEL) {#NAME, LABEL},
65 REGRESSION_STATS
66 #undef RG
67 };
68
69 struct save_options
70 {
71 gboolean pred;
72 gboolean resid;
73 };
74 struct regression_dialog
75 {
76 GtkTreeView *dep_vars;
77 GtkTreeView *indep_vars;
78 PsppireDict *dict;
79
80 GtkToggleButton *resid_button;
81 GtkToggleButton *pred_button;
82
83 GtkWidget *stat_dialog;
84 GtkWidget *save_dialog;
85
86 GtkWidget *stat_view;
87 GtkTreeModel *stat;
88 struct save_options current_opts;
89 };
90
91 static void
92 refresh (PsppireDialog *dialog, struct regression_dialog *rd)
93 {
94 GtkTreeModel *liststore = gtk_tree_view_get_model (rd->dep_vars);
95 gtk_list_store_clear (GTK_LIST_STORE (liststore));
96
97 liststore = gtk_tree_view_get_model (rd->indep_vars);
98 gtk_list_store_clear (GTK_LIST_STORE (liststore));
99 }
100
101 static void
102 on_statistics_clicked (struct regression_dialog *rd)
103 {
104 GtkListStore *liststore;
105 int ret;
106
107 liststore = clone_list_store (GTK_LIST_STORE (rd->stat));
108
109 ret = psppire_dialog_run (PSPPIRE_DIALOG (rd->stat_dialog));
110
111 if ( ret == PSPPIRE_RESPONSE_CONTINUE )
112 {
113 g_object_unref (liststore);
114 }
115 else
116 {
117 g_object_unref (rd->stat);
118 gtk_tree_view_set_model (GTK_TREE_VIEW (rd->stat_view) , GTK_TREE_MODEL (liststore));
119 rd->stat = GTK_TREE_MODEL (liststore);
120 }
121 }
122
123 static void
124 on_save_clicked (struct regression_dialog *rd)
125 {
126 int ret;
127 if (rd->current_opts.pred)
128 {
129 gtk_toggle_button_set_active (rd->pred_button, TRUE);
130 }
131 if (rd->current_opts.resid)
132 {
133 gtk_toggle_button_set_active (rd->resid_button, TRUE);
134 }
135
136 ret = psppire_dialog_run (PSPPIRE_DIALOG (rd->save_dialog));
137
138 if ( ret == PSPPIRE_RESPONSE_CONTINUE )
139 {
140 rd->current_opts.pred = (gtk_toggle_button_get_active (rd->pred_button) == TRUE)
141 ? TRUE : FALSE;
142 rd->current_opts.resid = (gtk_toggle_button_get_active (rd->resid_button) == TRUE)
143 ? TRUE : FALSE;
144 }
145 }
146
147 static char *
148 generate_syntax (const struct regression_dialog *rd)
149 {
150 gint i;
151 int n;
152 guint selected;
153 GtkTreeIter iter;
154 gboolean ok;
155
156 gchar *text;
157 GString *string = g_string_new ("REGRESSION");
158
159 g_string_append (string, "\n\t/VARIABLES=");
160 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->indep_vars), 0, string);
161 g_string_append (string, "\n\t/DEPENDENT=\t");
162 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (rd->dep_vars), 0, string);
163
164 selected = 0;
165 for (i = 0, ok = gtk_tree_model_get_iter_first (rd->stat, &iter); ok;
166 i++, ok = gtk_tree_model_iter_next (rd->stat, &iter))
167 {
168 gboolean toggled;
169 gtk_tree_model_get (rd->stat, &iter,
170 CHECKBOX_COLUMN_SELECTED, &toggled, -1);
171 if (toggled)
172 selected |= 1u << i;
173 else
174 selected &= ~(1u << i);
175 }
176
177 if (selected)
178 {
179 g_string_append (string, "\n\t/STATISTICS=");
180 n = 0;
181 for (i = 0; i < N_REGRESSION_STATS; i++)
182 if (selected & (1u << i))
183 {
184 if (n++)
185 g_string_append (string, " ");
186 g_string_append (string, stats[i].name);
187 }
188 }
189 if (rd->current_opts.pred || rd->current_opts.resid)
190 {
191 g_string_append (string, "\n\t/SAVE=");
192 if (rd->current_opts.pred)
193 g_string_append (string, " PRED");
194 if (rd->current_opts.resid)
195 g_string_append (string, " RESID");
196 }
197 g_string_append (string, ".\n");
198
199 text = string->str;
200
201 g_string_free (string, FALSE);
202
203 return text;
204 }
205
206 /* Dialog is valid iff at least one dependent and one independent variable have
207 been selected. */
208 static gboolean
209 dialog_state_valid (gpointer data)
210 {
211 struct regression_dialog *rd = data;
212
213 GtkTreeModel *dep_vars = gtk_tree_view_get_model (rd->dep_vars);
214 GtkTreeModel *indep_vars = gtk_tree_view_get_model (rd->indep_vars);
215
216 GtkTreeIter notused;
217
218 return (gtk_tree_model_get_iter_first (dep_vars, &notused)
219 && gtk_tree_model_get_iter_first (indep_vars, &notused));
220 }
221
222 /* Pops up the Regression dialog box */
223 void
224 regression_dialog (PsppireDataWindow *de)
225 {
226 gint response;
227 struct regression_dialog rd;
228
229 GtkBuilder *xml = builder_new ("regression.ui");
230 PsppireVarStore *vs;
231
232 GtkWidget *dialog = get_widget_assert (xml, "regression-dialog");
233 GtkWidget *source = get_widget_assert (xml, "dict-view");
234 GtkWidget *dest_dep = get_widget_assert (xml, "dep-view");
235 GtkWidget *dest_indep = get_widget_assert (xml, "indep-view");
236 GtkWidget *stat_button = get_widget_assert (xml, "stat-button");
237 GtkWidget *save_button = get_widget_assert (xml, "save-button");
238
239 GtkWidget *dep_selector = get_widget_assert (xml, "dep-selector");
240
241 rd.stat_view = get_widget_assert (xml, "stat-view");
242
243 g_object_get (de->data_editor, "var-store", &vs, NULL);
244
245
246 put_checkbox_items_in_treeview (GTK_TREE_VIEW(rd.stat_view),
247 B_RG_STATS_DEFAULT,
248 N_REGRESSION_STATS,
249 stats
250 );
251
252 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (de));
253
254 g_object_get (vs, "dictionary", &rd.dict, NULL);
255 g_object_set (source, "model", rd.dict, NULL);
256
257 rd.dep_vars = GTK_TREE_VIEW (dest_dep);
258 rd.indep_vars = GTK_TREE_VIEW (dest_indep);
259
260 psppire_selector_set_allow (PSPPIRE_SELECTOR (dep_selector), numeric_only);
261
262 rd.save_dialog = get_widget_assert (xml, "save-dialog");
263 rd.pred_button = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "pred-button"));
264 rd.resid_button = GTK_TOGGLE_BUTTON (get_widget_assert (xml, "resid-button"));
265 rd.stat_dialog = get_widget_assert (xml, "statistics-dialog");
266
267 rd.stat = gtk_tree_view_get_model (GTK_TREE_VIEW (rd.stat_view));
268 rd.current_opts.pred = FALSE;
269 rd.current_opts.resid = FALSE;
270
271 gtk_window_set_transient_for (GTK_WINDOW (rd.save_dialog), GTK_WINDOW (de));
272 gtk_window_set_transient_for (GTK_WINDOW (rd.stat_dialog), GTK_WINDOW (de));
273
274 g_signal_connect (dialog, "refresh", G_CALLBACK (refresh), &rd);
275
276 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (dialog),
277 dialog_state_valid, &rd);
278
279 g_signal_connect_swapped (stat_button, "clicked",
280 G_CALLBACK (on_statistics_clicked), &rd);
281 g_signal_connect_swapped (save_button, "clicked",
282 G_CALLBACK (on_save_clicked), &rd);
283
284 response = psppire_dialog_run (PSPPIRE_DIALOG (dialog));
285
286
287 switch (response)
288 {
289 case GTK_RESPONSE_OK:
290 g_free (execute_syntax_string (de, generate_syntax (&rd)));
291 break;
292 case PSPPIRE_RESPONSE_PASTE:
293 g_free (paste_syntax_to_window (generate_syntax (&rd)));
294 break;
295 default:
296 break;
297 }
298
299 g_object_unref (xml);
300 }
+0
-25
src/ui/gui/regression-dialog.h less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2008 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #ifndef __REGRESSION_DIALOG_H
17 #define __REGRESSION_DIALOG_H
18
19
20 #include "psppire-data-window.h"
21
22 void regression_dialog (PsppireDataWindow * data);
23
24 #endif
179179 </packing>
180180 </child>
181181 <child>
182 <object class="GtkEntry" id="entry2">
182 <object class="PsppireValueEntry" id="entry2">
183183 <property name="visible">True</property>
184184 <property name="can_focus">True</property>
185 <property name="invisible_char">&#x2022;</property>
186185 </object>
187186 <packing>
188187 <property name="position">1</property>
+0
-473
src/ui/gui/t-test-independent-samples-dialog.c less more
0 /* PSPPIRE - a graphical user interface for PSPP.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18 #include <config.h>
19 #include <gtk/gtk.h>
20 #include "t-test-independent-samples-dialog.h"
21 #include "psppire-dict.h"
22 #include "psppire-var-store.h"
23 #include "psppire-var-view.h"
24 #include "executor.h"
25 #include "psppire-data-window.h"
26 #include "psppire-dialog.h"
27 #include "dialog-common.h"
28 #include "dict-display.h"
29 #include "widget-io.h"
30 #include "t-test-options.h"
31 #include <ui/syntax-gen.h>
32
33 #include "builder-wrapper.h"
34 #include "helper.h"
35
36 #include <gl/xalloc.h>
37
38 #include <gettext.h>
39 #define _(msgid) gettext (msgid)
40 #define N_(msgid) msgid
41
42
43 enum group_definition
44 {
45 GROUPS_UNDEF,
46 GROUPS_VALUES,
47 GROUPS_CUT_POINT
48 };
49
50 struct tt_groups_dialog
51 {
52 GtkWidget *dialog;
53 GtkWidget *label;
54 GtkWidget *table1;
55 GtkWidget *table2;
56 GtkWidget *hbox1;
57
58 GtkWidget *values_toggle_button;
59 GtkWidget *cut_point_toggle_button;
60
61 GtkWidget *grp_entry[2];
62 GtkWidget *cut_point_entry;
63
64 enum group_definition group_defn;
65 gchar *val[2];
66 };
67
68 static void
69 set_group_criterion_type (GtkToggleButton *button,
70 struct tt_groups_dialog *groups)
71 {
72 gboolean by_values = gtk_toggle_button_get_active (button);
73
74 gtk_widget_set_sensitive (groups->label, by_values);
75 gtk_widget_set_sensitive (groups->table2, by_values);
76
77 gtk_widget_set_sensitive (groups->hbox1, !by_values);
78 }
79
80 static void
81 tt_groups_dialog_destroy (struct tt_groups_dialog *grps)
82 {
83 g_object_unref (grps->table1);
84 g_object_unref (grps->table2);
85
86 g_free (grps->val[0]);
87 g_free (grps->val[1]);
88
89 g_free (grps);
90 }
91
92 static struct tt_groups_dialog *
93 tt_groups_dialog_create (GtkBuilder *xml, GtkWindow *parent)
94 {
95 struct tt_groups_dialog *grps = xmalloc (sizeof (*grps));
96
97 grps->group_defn = GROUPS_UNDEF;
98
99 grps->dialog = get_widget_assert (xml, "define-groups-dialog");
100 grps->table1 = get_widget_assert (xml, "table1");
101 grps->table2 = get_widget_assert (xml, "table2");
102 grps->label = get_widget_assert (xml, "label4");
103 grps->hbox1 = get_widget_assert (xml, "hbox1");
104
105 grps->grp_entry[0] = get_widget_assert (xml, "group1-entry");
106 grps->grp_entry[1] = get_widget_assert (xml, "group2-entry");
107 grps->cut_point_entry = get_widget_assert (xml, "cut-point-entry");
108
109 grps->cut_point_toggle_button = get_widget_assert (xml, "radiobutton4");
110 grps->values_toggle_button = get_widget_assert (xml, "radiobutton3");
111
112 g_object_ref (grps->table1);
113 g_object_ref (grps->table2);
114
115 g_signal_connect (grps->values_toggle_button, "toggled",
116 G_CALLBACK (set_group_criterion_type), grps);
117
118 gtk_window_set_transient_for (GTK_WINDOW (grps->dialog), parent);
119
120 grps->val[0] = xstrdup ("");
121 grps->val[1] = xstrdup ("");
122
123 return grps;
124 }
125
126
127 struct tt_indep_samples_dialog
128 {
129 GtkBuilder *xml; /* The xml that generated the widgets */
130 GtkWidget *dialog;
131 PsppireDict *dict;
132 GtkWidget *define_groups_button;
133 GtkWidget *groups_entry;
134
135 struct tt_groups_dialog *grps;
136 struct tt_options_dialog *opts;
137 };
138
139
140 static void
141 set_define_groups_sensitivity (GtkEntry *entry,
142 struct tt_indep_samples_dialog *tt_d)
143 {
144 const gchar *text = gtk_entry_get_text (entry);
145
146 const struct variable *v = psppire_dict_lookup_var (tt_d->dict, text);
147
148 gtk_widget_set_sensitive (tt_d->define_groups_button, v != NULL);
149 }
150
151
152 static gchar *
153 generate_syntax (const struct tt_indep_samples_dialog *d)
154 {
155 struct variable *group_variable;
156 gchar *text;
157
158 GtkWidget *tv =
159 get_widget_assert (d->xml, "indep-samples-t-test-treeview2");
160
161 GString *str = g_string_new ("T-TEST /VARIABLES=");
162
163 psppire_var_view_append_names (PSPPIRE_VAR_VIEW (tv), 0, str);
164
165 g_string_append (str, "\n\t/GROUPS=");
166
167 group_variable =
168 psppire_dict_lookup_var (d->dict,
169 gtk_entry_get_text (GTK_ENTRY (d->groups_entry)));
170
171 g_string_append (str, var_get_name (group_variable));
172
173 if (d->grps->group_defn != GROUPS_UNDEF)
174 {
175 g_string_append (str, "(");
176
177 if ( var_is_alpha (group_variable))
178 {
179 struct string s = DS_EMPTY_INITIALIZER;
180 syntax_gen_string (&s, ss_cstr (d->grps->val[0]));
181 g_string_append (str, ds_cstr (&s));
182 ds_destroy (&s);
183 }
184 else
185 {
186 g_string_append (str, d->grps->val[0]);
187 }
188
189 if ( d->grps->group_defn == GROUPS_VALUES )
190 {
191 g_string_append (str, ",");
192
193 if ( var_is_alpha (group_variable))
194 {
195 struct string s = DS_EMPTY_INITIALIZER;
196 syntax_gen_string (&s, ss_cstr (d->grps->val[1]));
197 g_string_append (str, ds_cstr (&s));
198 ds_destroy (&s);
199 }
200 else
201 {
202 g_string_append (str, d->grps->val[1]);
203 }
204 }
205
206 g_string_append (str, ")");
207 }
208
209 tt_options_dialog_append_syntax (d->opts, str);
210
211 g_string_append (str, ".\n");
212
213 text = str->str;
214
215 g_string_free (str, FALSE);
216
217 return text;
218 }
219
220 static void
221 refresh (struct tt_indep_samples_dialog *ttd)
222 {
223 GtkWidget *tv =
224 get_widget_assert (ttd->xml, "indep-samples-t-test-treeview2");
225
226 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tv));
227
228 gtk_entry_set_text (GTK_ENTRY (ttd->groups_entry), "");
229
230 gtk_list_store_clear (GTK_LIST_STORE (model));
231
232 gtk_widget_set_sensitive (ttd->define_groups_button, FALSE);
233 }
234
235
236 /* Returns TRUE iff the define groups subdialog has a
237 state which defines a valid group criterion */
238 static gboolean
239 define_groups_state_valid (gpointer data)
240 {
241 struct tt_groups_dialog *d = data;
242
243 if ( gtk_toggle_button_get_active
244 (GTK_TOGGLE_BUTTON (d->values_toggle_button)))
245 {
246 if ( 0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (d->grp_entry[0]))))
247 return FALSE;
248
249 if ( 0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (d->grp_entry[1]))))
250 return FALSE;
251 }
252 else
253 {
254 if ( 0 == strcmp ("",
255 gtk_entry_get_text (GTK_ENTRY (d->cut_point_entry))))
256 return FALSE;
257 }
258
259 return TRUE;
260 }
261
262 static void
263 run_define_groups (struct tt_indep_samples_dialog *ttd)
264 {
265 struct tt_groups_dialog *grps = ttd->grps;
266
267 gint response;
268
269 GtkWidget *box = get_widget_assert (ttd->xml, "dialog-hbox2");
270
271 const gchar *text = gtk_entry_get_text (GTK_ENTRY (ttd->groups_entry));
272
273 const struct variable *v = psppire_dict_lookup_var (ttd->dict, text);
274
275 if ( grps->table2->parent)
276 gtk_container_remove (GTK_CONTAINER (grps->table2->parent), grps->table2);
277
278 if ( grps->table1->parent)
279 gtk_container_remove (GTK_CONTAINER (grps->table1->parent), grps->table1);
280
281
282 if ( var_is_numeric (v))
283 {
284 gtk_table_attach_defaults (GTK_TABLE (grps->table1), grps->table2,
285 1, 2, 1, 2);
286
287 gtk_container_add (GTK_CONTAINER (box), grps->table1);
288 }
289 else
290 {
291 gtk_container_add (GTK_CONTAINER (box), grps->table2);
292 grps->group_defn = GROUPS_VALUES;
293 }
294
295
296 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (grps->dialog),
297 define_groups_state_valid, grps);
298
299 if ( grps->group_defn != GROUPS_CUT_POINT )
300 {
301 gtk_toggle_button_set_active
302 (GTK_TOGGLE_BUTTON (grps->cut_point_toggle_button), TRUE);
303
304 gtk_toggle_button_set_active
305 (GTK_TOGGLE_BUTTON (grps->values_toggle_button), TRUE);
306
307 gtk_entry_set_text (GTK_ENTRY (grps->grp_entry[0]), grps->val[0]);
308 gtk_entry_set_text (GTK_ENTRY (grps->grp_entry[1]), grps->val[1]);
309
310 gtk_entry_set_text (GTK_ENTRY (grps->cut_point_entry), "");
311 }
312 else
313 {
314 gtk_toggle_button_set_active
315 (GTK_TOGGLE_BUTTON (grps->values_toggle_button), TRUE);
316
317 gtk_toggle_button_set_active
318 (GTK_TOGGLE_BUTTON (grps->cut_point_toggle_button), TRUE);
319
320 gtk_entry_set_text (GTK_ENTRY (grps->grp_entry[0]), "");
321 gtk_entry_set_text (GTK_ENTRY (grps->grp_entry[1]), "");
322
323 gtk_entry_set_text (GTK_ENTRY (grps->cut_point_entry), grps->val[0]);
324 }
325
326 g_signal_emit_by_name (grps->grp_entry[0], "changed");
327 g_signal_emit_by_name (grps->grp_entry[1], "changed");
328 g_signal_emit_by_name (grps->cut_point_entry, "changed");
329
330 response = psppire_dialog_run (PSPPIRE_DIALOG (grps->dialog));
331
332 if (response == PSPPIRE_RESPONSE_CONTINUE)
333 {
334 g_free (grps->val[0]);
335 g_free (grps->val[1]);
336
337 if (gtk_toggle_button_get_active
338 (GTK_TOGGLE_BUTTON (grps->values_toggle_button)))
339 {
340 grps->group_defn = GROUPS_VALUES;
341
342 grps->val[0] =
343 xstrdup (gtk_entry_get_text (GTK_ENTRY (grps->grp_entry[0])));
344
345 grps->val[1] =
346 xstrdup (gtk_entry_get_text (GTK_ENTRY (grps->grp_entry[1])));
347 }
348 else
349 {
350 grps->group_defn = GROUPS_CUT_POINT;
351
352 grps->val[1] = NULL;
353
354 grps->val[0] =
355 xstrdup (gtk_entry_get_text (GTK_ENTRY (grps->cut_point_entry)));
356 }
357
358 psppire_dialog_notify_change (PSPPIRE_DIALOG (ttd->dialog));
359 }
360 }
361
362
363
364 static gboolean
365 dialog_state_valid (gpointer data)
366 {
367 struct tt_indep_samples_dialog *tt_d = data;
368
369 GtkWidget *tv_vars =
370 get_widget_assert (tt_d->xml, "indep-samples-t-test-treeview2");
371
372 GtkTreeModel *vars = gtk_tree_view_get_model (GTK_TREE_VIEW (tv_vars));
373
374 GtkTreeIter notused;
375
376 if ( 0 == strcmp ("", gtk_entry_get_text (GTK_ENTRY (tt_d->groups_entry))))
377 return FALSE;
378
379 if ( 0 == gtk_tree_model_get_iter_first (vars, &notused))
380 return FALSE;
381
382 if ( tt_d->grps->group_defn == GROUPS_UNDEF)
383 return FALSE;
384
385 return TRUE;
386 }
387
388 /* Pops up the dialog box */
389 void
390 t_test_independent_samples_dialog (PsppireDataWindow *de)
391 {
392 struct tt_indep_samples_dialog tt_d;
393 gint response;
394
395 PsppireVarStore *vs = NULL;
396
397 GtkBuilder *xml = builder_new ("t-test.ui");
398
399 GtkWidget *dict_view =
400 get_widget_assert (xml, "indep-samples-t-test-treeview1");
401
402 GtkWidget *selector2 =
403 get_widget_assert (xml, "indep-samples-t-test-selector2");
404
405 GtkWidget *selector1 =
406 get_widget_assert (xml, "indep-samples-t-test-selector1");
407
408 GtkWidget *options_button =
409 get_widget_assert (xml, "indep-samples-t-test-options-button");
410
411 g_object_get (de->data_editor, "var-store", &vs, NULL);
412
413 tt_d.dialog = get_widget_assert (xml, "t-test-independent-samples-dialog");
414 tt_d.xml = xml;
415 g_object_get (vs, "dictionary", &tt_d.dict, NULL);
416
417 tt_d.define_groups_button = get_widget_assert (xml, "define-groups-button");
418 tt_d.groups_entry = get_widget_assert (xml, "indep-samples-t-test-entry");
419 tt_d.opts = tt_options_dialog_create (GTK_WINDOW (de));
420 tt_d.grps = tt_groups_dialog_create (xml, GTK_WINDOW (de));
421
422
423 gtk_window_set_transient_for (GTK_WINDOW (tt_d.dialog), GTK_WINDOW (de));
424
425 g_object_set (dict_view, "model", tt_d.dict, NULL);
426
427 psppire_selector_set_allow (PSPPIRE_SELECTOR (selector1),
428 numeric_only);
429
430
431 psppire_selector_set_filter_func (PSPPIRE_SELECTOR (selector2),
432 is_currently_in_entry);
433
434 g_signal_connect_swapped (tt_d.define_groups_button, "clicked",
435 G_CALLBACK (run_define_groups), &tt_d);
436
437
438 g_signal_connect_swapped (options_button, "clicked",
439 G_CALLBACK (tt_options_dialog_run), tt_d.opts);
440
441
442 g_signal_connect_swapped (tt_d.dialog, "refresh", G_CALLBACK (refresh),
443 &tt_d);
444
445 g_signal_connect (tt_d.groups_entry, "changed",
446 G_CALLBACK (set_define_groups_sensitivity), &tt_d);
447
448
449 psppire_dialog_set_valid_predicate (PSPPIRE_DIALOG (tt_d.dialog),
450 dialog_state_valid, &tt_d);
451
452 response = psppire_dialog_run (PSPPIRE_DIALOG (tt_d.dialog));
453
454 switch (response)
455 {
456 case GTK_RESPONSE_OK:
457 g_free (execute_syntax_string (de, generate_syntax (&tt_d)));
458 break;
459 case PSPPIRE_RESPONSE_PASTE:
460 g_free (paste_syntax_to_window (generate_syntax (&tt_d)));
461 break;
462 default:
463 break;
464 }
465
466 tt_options_dialog_destroy (tt_d.opts);
467 tt_groups_dialog_destroy (tt_d.grps);
468
469 g_object_unref (xml);
470 }
471
472
+0
-8
src/ui/gui/t-test-independent-samples-dialog.h less more
0 #ifndef T_TEST_INDEPENDENT_SAMPLES_DIALOG
1 #define T_TEST_INDEPENDENT_SAMPLES_DIALOG
2
3 #include "psppire-data-window.h"
4
5 void t_test_independent_samples_dialog (PsppireDataWindow *) ;
6
7 #endif
22 <requires lib="psppire" version="2054.17080"/>
33 <!-- interface-requires gtk+ 2.12 -->
44 <!-- interface-naming-policy project-wide -->
5 <object class="PsppireDialog" id="t-test-independent-samples-dialog">
6 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
7 <property name="title" translatable="yes">Independent-Samples T Test</property>
8 <property name="modal">True</property>
9 <child internal-child="hbox">
10 <object class="GtkHBox" id="dialog-hbox15">
11 <property name="visible">True</property>
12 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
13 <property name="spacing">2</property>
14 <child>
15 <object class="GtkHBox" id="hbox23">
16 <property name="visible">True</property>
17 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
18 <property name="spacing">5</property>
19 <child>
20 <object class="GtkScrolledWindow" id="scrolledwindow14">
21 <property name="visible">True</property>
22 <property name="can_focus">True</property>
23 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
24 <property name="hscrollbar_policy">never</property>
25 <property name="vscrollbar_policy">automatic</property>
26 <property name="shadow_type">etched-in</property>
27 <child>
28 <object class="PsppireDictView" id="indep-samples-t-test-treeview1">
29 <property name="visible">True</property>
30 <property name="can_focus">True</property>
31 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
32 <property name="headers_visible">False</property>
33 </object>
34 </child>
35 </object>
36 <packing>
37 <property name="position">0</property>
38 </packing>
39 </child>
40 <child>
41 <object class="GtkTable" id="table4">
42 <property name="visible">True</property>
43 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
44 <property name="n_rows">3</property>
45 <property name="n_columns">2</property>
46 <child>
47 <object class="GtkHButtonBox" id="hbuttonbox1">
48 <property name="visible">True</property>
49 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
50 <property name="layout_style">spread</property>
51 <child>
52 <object class="GtkButton" id="define-groups-button">
53 <property name="label" translatable="yes">Define Groups</property>
54 <property name="visible">True</property>
55 <property name="can_focus">True</property>
56 <property name="receives_default">True</property>
57 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
58 </object>
59 <packing>
60 <property name="expand">False</property>
61 <property name="fill">False</property>
62 <property name="position">0</property>
63 </packing>
64 </child>
65 <child>
66 <object class="GtkButton" id="indep-samples-t-test-options-button">
67 <property name="label" translatable="yes">Options...</property>
68 <property name="visible">True</property>
69 <property name="can_focus">True</property>
70 <property name="receives_default">True</property>
71 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
72 </object>
73 <packing>
74 <property name="expand">False</property>
75 <property name="fill">False</property>
76 <property name="position">1</property>
77 </packing>
78 </child>
79 </object>
80 <packing>
81 <property name="right_attach">2</property>
82 <property name="top_attach">2</property>
83 <property name="bottom_attach">3</property>
84 <property name="y_options">GTK_FILL</property>
85 <property name="y_padding">5</property>
86 </packing>
87 </child>
88 <child>
89 <object class="PsppireSelector" id="indep-samples-t-test-selector1">
90 <property name="visible">True</property>
91 <property name="can_focus">True</property>
92 <property name="receives_default">True</property>
93 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
94 <property name="border_width">5</property>
95 <property name="source_widget">indep-samples-t-test-treeview1</property>
96 <property name="dest_widget">indep-samples-t-test-treeview2</property>
97 </object>
98 <packing>
99 <property name="x_options"></property>
100 <property name="y_options">GTK_EXPAND</property>
101 </packing>
102 </child>
103 <child>
104 <object class="PsppireSelector" id="indep-samples-t-test-selector2">
105 <property name="visible">True</property>
106 <property name="can_focus">True</property>
107 <property name="receives_default">True</property>
108 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
109 <property name="border_width">5</property>
110 <property name="source_widget">indep-samples-t-test-treeview1</property>
111 <property name="dest_widget">indep-samples-t-test-entry</property>
112 </object>
113 <packing>
114 <property name="top_attach">1</property>
115 <property name="bottom_attach">2</property>
116 <property name="x_options"></property>
117 <property name="y_options"></property>
118 </packing>
119 </child>
120 <child>
121 <object class="GtkVBox" id="vbox29">
122 <property name="visible">True</property>
123 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
124 <property name="orientation">vertical</property>
125 <child>
126 <object class="GtkLabel" id="label35">
127 <property name="visible">True</property>
128 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
129 <property name="xalign">0</property>
130 <property name="label" translatable="yes">Test Variable(s):</property>
131 </object>
132 <packing>
133 <property name="expand">False</property>
134 <property name="fill">False</property>
135 <property name="position">0</property>
136 </packing>
137 </child>
138 <child>
139 <object class="GtkScrolledWindow" id="scrolledwindow15">
140 <property name="visible">True</property>
141 <property name="can_focus">True</property>
142 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
143 <property name="hscrollbar_policy">automatic</property>
144 <property name="vscrollbar_policy">automatic</property>
145 <property name="shadow_type">etched-in</property>
146 <child>
147 <object class="PsppireVarView" id="indep-samples-t-test-treeview2">
148 <property name="visible">True</property>
149 <property name="can_focus">True</property>
150 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
151 <property name="headers_visible">False</property>
152 </object>
153 </child>
154 </object>
155 <packing>
156 <property name="position">1</property>
157 </packing>
158 </child>
159 </object>
160 <packing>
161 <property name="left_attach">1</property>
162 <property name="right_attach">2</property>
163 </packing>
164 </child>
165 <child>
166 <object class="GtkVBox" id="vbox30">
167 <property name="visible">True</property>
168 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
169 <property name="orientation">vertical</property>
170 <child>
171 <object class="GtkLabel" id="label36">
172 <property name="visible">True</property>
173 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
174 <property name="label" translatable="yes">Define Groups</property>
175 </object>
176 <packing>
177 <property name="expand">False</property>
178 <property name="fill">False</property>
179 <property name="position">0</property>
180 </packing>
181 </child>
182 <child>
183 <object class="GtkEntry" id="indep-samples-t-test-entry">
184 <property name="visible">True</property>
185 <property name="can_focus">True</property>
186 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
187 </object>
188 <packing>
189 <property name="position">1</property>
190 </packing>
191 </child>
192 </object>
193 <packing>
194 <property name="left_attach">1</property>
195 <property name="right_attach">2</property>
196 <property name="top_attach">1</property>
197 <property name="bottom_attach">2</property>
198 <property name="y_options"></property>
199 </packing>
200 </child>
201 </object>
202 <packing>
203 <property name="position">1</property>
204 </packing>
205 </child>
206 </object>
207 <packing>
208 <property name="position">0</property>
209 </packing>
210 </child>
211 <child>
212 <object class="PsppireVButtonBox" id="psppire-vbuttonbox2">
213 <property name="visible">True</property>
214 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
215 <property name="border_width">5</property>
216 <property name="orientation">vertical</property>
217 </object>
218 <packing>
219 <property name="expand">False</property>
220 <property name="fill">False</property>
221 <property name="pack_type">end</property>
222 <property name="position">1</property>
223 </packing>
224 </child>
225 </object>
226 </child>
227 </object>
228 <object class="PsppireDialog" id="define-groups-dialog">
229 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
230 <property name="title" translatable="yes">Define Groups</property>
231 <property name="modal">True</property>
232 <child internal-child="hbox">
233 <object class="GtkHBox" id="dialog-hbox2">
234 <property name="visible">True</property>
235 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
236 <property name="spacing">2</property>
237 <child>
238 <object class="GtkTable" id="table1">
239 <property name="visible">True</property>
240 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
241 <property name="n_rows">3</property>
242 <property name="n_columns">2</property>
243 <property name="column_spacing">5</property>
244 <property name="row_spacing">5</property>
245 <child>
246 <object class="GtkRadioButton" id="radiobutton3">
247 <property name="visible">True</property>
248 <property name="can_focus">True</property>
249 <property name="receives_default">False</property>
250 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
251 <property name="active">True</property>
252 <property name="draw_indicator">True</property>
253 </object>
254 <packing>
255 <property name="x_options"></property>
256 </packing>
257 </child>
258 <child>
259 <object class="GtkTable" id="table2">
260 <property name="visible">True</property>
261 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
262 <property name="n_rows">2</property>
263 <property name="n_columns">2</property>
264 <property name="column_spacing">5</property>
265 <property name="row_spacing">5</property>
266 <child>
267 <object class="GtkLabel" id="label2">
268 <property name="visible">True</property>
269 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
270 <property name="label" translatable="yes">Group_2 value:</property>
271 <property name="use_underline">True</property>
272 <property name="mnemonic_widget">group2-entry</property>
273 </object>
274 <packing>
275 <property name="top_attach">1</property>
276 <property name="bottom_attach">2</property>
277 <property name="x_options"></property>
278 </packing>
279 </child>
280 <child>
281 <object class="GtkLabel" id="label1">
282 <property name="visible">True</property>
283 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
284 <property name="label" translatable="yes">Group_1 value:</property>
285 <property name="use_underline">True</property>
286 <property name="mnemonic_widget">group1-entry</property>
287 </object>
288 <packing>
289 <property name="x_options"></property>
290 </packing>
291 </child>
292 <child>
293 <object class="GtkEntry" id="group2-entry">
294 <property name="visible">True</property>
295 <property name="can_focus">True</property>
296 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
297 </object>
298 <packing>
299 <property name="left_attach">1</property>
300 <property name="right_attach">2</property>
301 <property name="top_attach">1</property>
302 <property name="bottom_attach">2</property>
303 </packing>
304 </child>
305 <child>
306 <object class="GtkEntry" id="group1-entry">
307 <property name="visible">True</property>
308 <property name="can_focus">True</property>
309 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
310 </object>
311 <packing>
312 <property name="left_attach">1</property>
313 <property name="right_attach">2</property>
314 </packing>
315 </child>
316 </object>
317 <packing>
318 <property name="left_attach">1</property>
319 <property name="right_attach">2</property>
320 <property name="top_attach">1</property>
321 <property name="bottom_attach">2</property>
322 <property name="y_options">GTK_EXPAND</property>
323 </packing>
324 </child>
325 <child>
326 <object class="GtkHBox" id="hbox1">
327 <property name="visible">True</property>
328 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
329 <child>
330 <object class="GtkLabel" id="label5">
331 <property name="visible">True</property>
332 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
333 <property name="xalign">0</property>
334 <property name="label" translatable="yes">_Cut point:</property>
335 <property name="use_underline">True</property>
336 <property name="mnemonic_widget">radiobutton4</property>
337 </object>
338 <packing>
339 <property name="position">0</property>
340 </packing>
341 </child>
342 <child>
343 <object class="GtkEntry" id="cut-point-entry">
344 <property name="visible">True</property>
345 <property name="can_focus">True</property>
346 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
347 </object>
348 <packing>
349 <property name="position">1</property>
350 </packing>
351 </child>
352 </object>
353 <packing>
354 <property name="left_attach">1</property>
355 <property name="right_attach">2</property>
356 <property name="top_attach">2</property>
357 <property name="bottom_attach">3</property>
358 <property name="y_options"></property>
359 <property name="y_padding">5</property>
360 </packing>
361 </child>
362 <child>
363 <object class="GtkLabel" id="label4">
364 <property name="visible">True</property>
365 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
366 <property name="xalign">0</property>
367 <property name="label" translatable="yes">_Use specified values:</property>
368 <property name="use_underline">True</property>
369 <property name="mnemonic_widget">radiobutton3</property>
370 </object>
371 <packing>
372 <property name="left_attach">1</property>
373 <property name="right_attach">2</property>
374 <property name="y_options"></property>
375 </packing>
376 </child>
377 <child>
378 <object class="GtkRadioButton" id="radiobutton4">
379 <property name="visible">True</property>
380 <property name="can_focus">True</property>
381 <property name="receives_default">False</property>
382 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
383 <property name="active">True</property>
384 <property name="draw_indicator">True</property>
385 <property name="group">radiobutton3</property>
386 </object>
387 <packing>
388 <property name="top_attach">2</property>
389 <property name="bottom_attach">3</property>
390 <property name="x_options"></property>
391 <property name="y_options"></property>
392 </packing>
393 </child>
394 <child>
395 <placeholder/>
396 </child>
397 </object>
398 <packing>
399 <property name="padding">5</property>
400 <property name="position">0</property>
401 </packing>
402 </child>
403 <child>
404 <object class="PsppireVButtonBox" id="psppire-vbuttonbox1">
405 <property name="visible">True</property>
406 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
407 <property name="border_width">5</property>
408 <property name="orientation">vertical</property>
409 <property name="buttons">PSPPIRE_BUTTON_CONTINUE_MASK | PSPPIRE_BUTTON_CANCEL_MASK | PSPPIRE_BUTTON_HELP_MASK</property>
410 </object>
411 <packing>
412 <property name="expand">False</property>
413 <property name="fill">False</property>
414 <property name="pack_type">end</property>
415 <property name="position">1</property>
416 </packing>
417 </child>
418 </object>
419 </child>
420 </object>
4215 <object class="PsppireDialog" id="options-dialog">
4226 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
4237 <property name="title" translatable="yes">Options</property>
1818 #include "ui/gui/text-data-import-dialog.h"
1919
2020 #include <errno.h>
21 #include <fcntl.h>
2122 #include <gtk-contrib/psppire-sheet.h>
2223 #include <gtk/gtk.h>
2324 #include <limits.h>
3233 #include "language/lexer/lexer.h"
3334 #include "libpspp/assertion.h"
3435 #include "libpspp/i18n.h"
36 #include "libpspp/line-reader.h"
3537 #include "libpspp/message.h"
3638 #include "ui/gui/checkbox-treeview.h"
3739 #include "ui/gui/dialog-common.h"
4042 #include "ui/gui/builder-wrapper.h"
4143 #include "ui/gui/psppire-data-window.h"
4244 #include "ui/gui/psppire-dialog.h"
45 #include "ui/gui/psppire-encoding-selector.h"
46 #include "ui/gui/psppire-empty-list-store.h"
4347 #include "ui/gui/psppire-var-sheet.h"
4448 #include "ui/gui/psppire-var-store.h"
4549 #include "ui/gui/psppire-scanf.h"
4650 #include "ui/syntax-gen.h"
4751
4852 #include "gl/error.h"
53 #include "gl/intprops.h"
4954 #include "gl/xalloc.h"
5055
5156 #include "gettext.h"
5257 #define _(msgid) gettext (msgid)
5358 #define N_(msgid) msgid
54
55
56 /* TextImportModel, a GtkTreeModel used by the text data import
57 dialog. */
58 enum
59 {
60 TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER, /* 1-based line number in file */
61 TEXT_IMPORT_MODEL_COLUMN_LINE, /* The line from the file. */
62 };
63 typedef struct TextImportModel TextImportModel;
64 typedef struct TextImportModelClass TextImportModelClass;
65
66 TextImportModel *text_import_model_new (struct string *lines, size_t line_cnt,
67 size_t first_line);
68 gint text_import_model_iter_to_row (const GtkTreeIter *);
6959
7060 struct import_assistant;
7161
7363 struct file
7464 {
7565 char *file_name; /* File name. */
66 gchar *encoding; /* Encoding. */
7667 unsigned long int total_lines; /* Number of lines in file. */
7768 bool total_is_exact; /* Is total_lines exact (or an estimate)? */
7869
225216 gint column_idx);
226217 static GtkTreeView *create_data_tree_view (bool input, GtkContainer *parent,
227218 struct import_assistant *);
228 static char *escape_underscores (const char *in);
229219 static void push_watch_cursor (struct import_assistant *);
230220 static void pop_watch_cursor (struct import_assistant *);
231221
371361 " /TYPE=TXT\n"
372362 " /FILE=%sq\n",
373363 ia->file.file_name);
364 if (ia->file.encoding && strcmp (ia->file.encoding, "Auto"))
365 syntax_gen_pspp (&s, " /ENCODING=%sq\n", ia->file.encoding);
374366 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
375367 ia->intro.n_cases_button)))
376368 ds_put_format (&s, " /IMPORTCASES=FIRST %d\n",
426418
427419 /* Choosing a file and reading it. */
428420
429 static char *choose_file (GtkWindow *parent_window);
421 static char *choose_file (GtkWindow *parent_window, gchar **encodingp);
430422
431423 /* Obtains the file to import from the user and initializes IA's
432424 file substructure. PARENT_WINDOW must be the window to use
440432 struct file *file = &ia->file;
441433 enum { MAX_PREVIEW_LINES = 1000 }; /* Max number of lines to read. */
442434 enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
443 FILE *stream;
444
445 file->file_name = choose_file (parent_window);
435 struct line_reader *reader;
436
437 file->file_name = choose_file (parent_window, &file->encoding);
446438 if (file->file_name == NULL)
447439 return false;
448440
449 stream = fopen (file->file_name, "r");
450 if (stream == NULL)
441 reader = line_reader_for_file (file->encoding, file->file_name, O_RDONLY);
442 if (reader == NULL)
451443 {
452444 msg (ME, _("Could not open `%s': %s"),
453445 file->file_name, strerror (errno));
460452 struct string *line = &file->lines[file->line_cnt];
461453
462454 ds_init_empty (line);
463 if (!ds_read_line (line, stream, MAX_LINE_LEN))
455 if (!line_reader_read (reader, line, MAX_LINE_LEN + 1)
456 || ds_length (line) > MAX_LINE_LEN)
464457 {
465 if (feof (stream))
458 if (line_reader_eof (reader))
466459 break;
467 else if (ferror (stream))
460 else if (line_reader_error (reader))
468461 msg (ME, _("Error reading `%s': %s"),
469 file->file_name, strerror (errno));
462 file->file_name, strerror (line_reader_error (reader)));
470463 else
471464 msg (ME, _("Failed to read `%s', because it contains a line "
472465 "over %d bytes long and therefore appears not to be "
473466 "a text file."),
474467 file->file_name, MAX_LINE_LEN);
475 fclose (stream);
468 line_reader_close (reader);
476469 destroy_file (ia);
477470 return false;
478471 }
479 ds_chomp_byte (line, '\n');
480 ds_chomp_byte (line, '\r');
481472 }
482473
483474 if (file->line_cnt == 0)
484475 {
485476 msg (ME, _("`%s' is empty."), file->file_name);
486 fclose (stream);
477 line_reader_close (reader);
487478 destroy_file (ia);
488479 return false;
489480 }
494485 else
495486 {
496487 struct stat s;
497 off_t position = ftello (stream);
498 if (fstat (fileno (stream), &s) == 0 && position > 0)
488 off_t position = line_reader_tell (reader);
489 if (fstat (line_reader_fileno (reader), &s) == 0 && position > 0)
499490 file->total_lines = (double) file->line_cnt / position * s.st_size;
500491 else
501492 file->total_lines = 0;
502493 }
494
495 line_reader_close (reader);
503496
504497 return true;
505498 }
515508 ds_destroy (&f->lines[i]);
516509 free (f->lines);
517510 g_free (f->file_name);
518 }
519
520 /* Obtains the file to read from the user and returns the name of
521 the file as a string that must be freed with g_free if
522 successful, otherwise a null pointer. PARENT_WINDOW must be
523 the window to use as the file chooser window's parent. */
511 g_free (f->encoding);
512 }
513
514 /* Obtains the file to read from the user. If successful, returns the name of
515 the file and stores the user's chosen encoding for the file into *ENCODINGP.
516 The caller must free each of these strings with g_free().
517
518 On failure, stores a null pointer and stores NULL in *ENCODINGP.
519
520 PARENT_WINDOW must be the window to use as the file chooser window's
521 parent. */
524522 static char *
525 choose_file (GtkWindow *parent_window)
523 choose_file (GtkWindow *parent_window, gchar **encodingp)
526524 {
527525 char *file_name;
526 GtkFileFilter *filter = NULL;
528527
529528 GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Import Delimited Text Data"),
530529 parent_window,
535534
536535 g_object_set (dialog, "local-only", FALSE, NULL);
537536
537 filter = gtk_file_filter_new ();
538 gtk_file_filter_set_name (filter, _("Text files"));
539 gtk_file_filter_add_mime_type (filter, "text/*");
540 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
541
542 filter = gtk_file_filter_new ();
543 gtk_file_filter_set_name (filter, _("Text (*.txt) Files"));
544 gtk_file_filter_add_pattern (filter, "*.txt");
545 gtk_file_filter_add_pattern (filter, "*.TXT");
546 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
547
548 filter = gtk_file_filter_new ();
549 gtk_file_filter_set_name (filter, _("Plain Text (ASCII) Files"));
550 gtk_file_filter_add_mime_type (filter, "text/plain");
551 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
552
553 filter = gtk_file_filter_new ();
554 gtk_file_filter_set_name (filter, _("Comma Separated Value Files"));
555 gtk_file_filter_add_mime_type (filter, "text/csv");
556 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
557
558 /* I've never encountered one of these, but it's listed here:
559 http://www.iana.org/assignments/media-types/text/tab-separated-values */
560 filter = gtk_file_filter_new ();
561 gtk_file_filter_set_name (filter, _("Tab Separated Value Files"));
562 gtk_file_filter_add_mime_type (filter, "text/tab-separated-values");
563 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
564
565 gtk_file_chooser_set_extra_widget (
566 GTK_FILE_CHOOSER (dialog), psppire_encoding_selector_new ("Auto", true));
567
568 filter = gtk_file_filter_new ();
569 gtk_file_filter_set_name (filter, _("All Files"));
570 gtk_file_filter_add_pattern (filter, "*");
571 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
572
538573 switch (gtk_dialog_run (GTK_DIALOG (dialog)))
539574 {
540575 case GTK_RESPONSE_ACCEPT:
541576 file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
577 *encodingp = psppire_encoding_selector_get_encoding (
578 gtk_file_chooser_get_extra_widget (GTK_FILE_CHOOSER (dialog)));
542579 break;
543580 default:
544581 file_name = NULL;
582 *encodingp = NULL;
545583 break;
546584 }
547585 gtk_widget_destroy (dialog);
863901 set_first_line (ia);
864902 }
865903
904 static void
905 render_line (GtkTreeViewColumn *tree_column,
906 GtkCellRenderer *cell,
907 GtkTreeModel *tree_model,
908 GtkTreeIter *iter,
909 gpointer data)
910 {
911 gint row = empty_list_store_iter_to_row (iter);
912 struct string *lines;
913
914 lines = g_object_get_data (G_OBJECT (tree_model), "lines");
915 g_return_if_fail (lines != NULL);
916
917 g_object_set (cell, "text", ds_cstr (&lines[row]), NULL);
918 }
919
920
866921 /* Creates and returns a tree view that contains each of the
867922 lines in IA's file as a row. */
868923 static GtkTreeView *
877932
878933 make_tree_view (ia, 0, &tree_view);
879934
880 column = gtk_tree_view_column_new_with_attributes
881 (
882 title, ia->asst.fixed_renderer,
883 "text", TEXT_IMPORT_MODEL_COLUMN_LINE,
884 (void *) NULL
885 );
935 column = gtk_tree_view_column_new_with_attributes (
936 title, ia->asst.fixed_renderer, (void *) NULL);
937 gtk_tree_view_column_set_cell_data_func (column, ia->asst.fixed_renderer,
938 render_line, NULL, NULL);
886939 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
887940
888941 max_line_length = 0;
10411094 }
10421095
10431096 gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (list));
1097 g_object_unref (list);
10441098
10451099 gtk_combo_box_entry_set_text_column (cb, 0);
10461100 }
15021556
15031557 column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_column),
15041558 "column-number"));
1505 row = text_import_model_iter_to_row (iter) + ia->first_line.skip_lines;
1559 row = empty_list_store_iter_to_row (iter) + ia->first_line.skip_lines;
15061560 field = ia->separators.columns[column].contents[row];
15071561 if (field.string != NULL)
15081562 {
17701824 {
17711825 char *error;
17721826
1773 error = data_in (field, C_ENCODING, in->type, &val, var_get_width (var),
1827 error = data_in (field, "UTF-8", in->type, &val, var_get_width (var),
17741828 dict_get_encoding (ia->formats.dict));
17751829 if (error != NULL)
17761830 {
18161870 bool ok;
18171871
18181872 ok = parse_field (ia,
1819 (text_import_model_iter_to_row (iter)
1873 (empty_list_store_iter_to_row (iter)
18201874 + ia->first_line.skip_lines),
18211875 GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_column),
18221876 "column-number")),
19001954 if (!ok)
19011955 return FALSE;
19021956
1903 *row = text_import_model_iter_to_row (&iter) + ia->first_line.skip_lines;
1957 *row = empty_list_store_iter_to_row (&iter) + ia->first_line.skip_lines;
19041958 return TRUE;
19051959 }
19061960
19121966 GtkTreeModel *model;
19131967
19141968 *tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
1915 model = GTK_TREE_MODEL (text_import_model_new (
1916 ia->file.lines + first_line,
1917 ia->file.line_cnt - first_line, first_line));
1969 model = GTK_TREE_MODEL (psppire_empty_list_store_new (
1970 ia->file.line_cnt - first_line));
1971 g_object_set_data (G_OBJECT (model), "lines", ia->file.lines + first_line);
1972 g_object_set_data (G_OBJECT (model), "first-line",
1973 GINT_TO_POINTER (first_line));
19181974 gtk_tree_view_set_model (*tree_view, model);
1975 g_object_unref (model);
19191976
19201977 add_line_number_column (ia, *tree_view);
1978 }
1979
1980 static void
1981 render_line_number (GtkTreeViewColumn *tree_column,
1982 GtkCellRenderer *cell,
1983 GtkTreeModel *tree_model,
1984 GtkTreeIter *iter,
1985 gpointer data)
1986 {
1987 gint row = empty_list_store_iter_to_row (iter);
1988 char s[INT_BUFSIZE_BOUND (int)];
1989 int first_line;
1990
1991 first_line = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_model),
1992 "first-line"));
1993 sprintf (s, "%d", first_line + row);
1994 g_object_set (cell, "text", s, NULL);
19211995 }
19221996
19231997 static void
19272001 GtkTreeViewColumn *column;
19282002
19292003 column = gtk_tree_view_column_new_with_attributes (
1930 _("Line"), ia->asst.prop_renderer,
1931 "text", TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER,
1932 (void *) NULL);
2004 _("Line"), ia->asst.prop_renderer, (void *) NULL);
19332005 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
19342006 gtk_tree_view_column_set_fixed_width (
19352007 column, get_monospace_width (treeview, ia->asst.prop_renderer, 5));
2008 gtk_tree_view_column_set_resizable (column, TRUE);
2009 gtk_tree_view_column_set_cell_data_func (column, ia->asst.prop_renderer,
2010 render_line_number, NULL, NULL);
19362011 gtk_tree_view_append_column (treeview, column);
19372012 }
19382013
20312106 return tree_view;
20322107 }
20332108
2034 static char *
2035 escape_underscores (const char *in)
2036 {
2037 char *out = xmalloc (2 * strlen (in) + 1);
2038 char *p;
2039
2040 p = out;
2041 for (; *in != '\0'; in++)
2042 {
2043 if (*in == '_')
2044 *p++ = '_';
2045 *p++ = *in;
2046 }
2047 *p = '\0';
2048
2049 return out;
2050 }
2051
2052 /* TextImportModel, a GtkTreeModel implementation used by some
2053 pages of the assistant. */
2054
2055 #define G_TYPE_TEXT_IMPORT_MODEL (text_import_model_get_type ())
2056 #define TEXT_IMPORT_MODEL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_TEXT_IMPORT_MODEL, TextImportModel))
2057 #define TEXT_IMPORT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_TEXT_IMPORT_MODEL, TextImportModelClass))
2058 #define IS_TEXT_IMPORT_MODEL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_TEXT_IMPORT_MODEL))
2059 #define IS_TEXT_IMPORT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_TEXT_IMPORT_MODEL))
2060 #define TEXT_IMPORT_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_TEXT_IMPORT_MODEL, TextImportModelClass))
2061
2062 /* Random number used in 'stamp' member of GtkTreeIter. */
2063 #define TREE_MODEL_STAMP 0x7efd67d3
2064
2065 struct TextImportModel
2066 {
2067 GObject parent;
2068 struct string *lines;
2069 size_t line_cnt;
2070 size_t first_line;
2071 };
2072
2073 struct TextImportModelClass
2074 {
2075 GObjectClass parent_class;
2076 };
2077
2078 GType text_import_model_get_type (void);
2079 static void text_import_model_tree_model_init (gpointer iface, gpointer data);
2080
2081 GType
2082 text_import_model_get_type (void)
2083 {
2084 static GType object_type = 0;
2085
2086 if (!object_type)
2087 {
2088 static const GTypeInfo object_info = {
2089 sizeof (TextImportModelClass),
2090 (GBaseInitFunc) NULL,
2091 (GBaseFinalizeFunc) NULL,
2092 NULL, /* class_init */
2093 NULL, /* class_finalize */
2094 NULL, /* class_data */
2095 sizeof (TextImportModel),
2096 0, /* n_preallocs */
2097 NULL, /* instance_init */
2098 };
2099
2100 static const GInterfaceInfo tree_model_info = {
2101 text_import_model_tree_model_init,
2102 NULL,
2103 NULL
2104 };
2105
2106 object_type = g_type_register_static (G_TYPE_OBJECT,
2107 "TextImportModel",
2108 &object_info, 0);
2109
2110 g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
2111 &tree_model_info);
2112
2113
2114 }
2115
2116 return object_type;
2117 }
2118
2119
2120 /* Creates and returns a new TextImportModel that contains the
2121 LINE_CNT lines in LINES. The lines before FIRST_LINE in LINES
2122 are not part of the model, but they are included in the line
2123 numbers in the TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER column.
2124
2125 The caller retains responsibility for freeing LINES and must
2126 ensure that its lifetime and that of the strings that it
2127 contains exceeds that of the TextImportModel. */
2128 TextImportModel *
2129 text_import_model_new (struct string *lines, size_t line_cnt,
2130 size_t first_line)
2131 {
2132 TextImportModel *new_text_import_model
2133 = g_object_new (G_TYPE_TEXT_IMPORT_MODEL, NULL);
2134 new_text_import_model->lines = lines;
2135 new_text_import_model->line_cnt = line_cnt;
2136 new_text_import_model->first_line = first_line;
2137 return new_text_import_model;
2138 }
2139
2140
2141 static gboolean
2142 tree_model_iter_has_child (GtkTreeModel *tree_model,
2143 GtkTreeIter *iter)
2144 {
2145 return FALSE;
2146 }
2147
2148 static gboolean
2149 tree_model_iter_parent (GtkTreeModel *tree_model,
2150 GtkTreeIter *iter,
2151 GtkTreeIter *child)
2152 {
2153 return TRUE;
2154 }
2155
2156 static GtkTreeModelFlags
2157 tree_model_get_flags (GtkTreeModel *model)
2158 {
2159 g_return_val_if_fail (IS_TEXT_IMPORT_MODEL (model), (GtkTreeModelFlags) 0);
2160
2161 return GTK_TREE_MODEL_LIST_ONLY | GTK_TREE_MODEL_ITERS_PERSIST;
2162 }
2163
2164
2165 static gint
2166 tree_model_n_columns (GtkTreeModel *model)
2167 {
2168 return 2;
2169 }
2170
2171 static GType
2172 tree_model_column_type (GtkTreeModel *model, gint index)
2173 {
2174 return (index == TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER ? G_TYPE_INT
2175 : index == TEXT_IMPORT_MODEL_COLUMN_LINE ? G_TYPE_STRING
2176 : -1);
2177 }
2178
2179 static gboolean
2180 init_iter (TextImportModel *list, gint idx, GtkTreeIter *iter)
2181 {
2182 if (idx < 0 || idx >= list->line_cnt)
2183 {
2184 iter->stamp = 0;
2185 iter->user_data = GINT_TO_POINTER (-1);
2186 return FALSE;
2187 }
2188 else
2189 {
2190 iter->stamp = TREE_MODEL_STAMP;
2191 iter->user_data = GINT_TO_POINTER (idx);
2192 return TRUE;
2193 }
2194 }
2195
2196 static gboolean
2197 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
2198 {
2199 gint *indices, depth;
2200
2201 TextImportModel *list = TEXT_IMPORT_MODEL (model);
2202
2203 g_return_val_if_fail (path, FALSE);
2204
2205 indices = gtk_tree_path_get_indices (path);
2206 depth = gtk_tree_path_get_depth (path);
2207
2208 g_return_val_if_fail (depth == 1, FALSE);
2209
2210 return init_iter (list, indices[0], iter);
2211 }
2212
2213
2214 static gboolean
2215 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
2216 {
2217 TextImportModel *list = TEXT_IMPORT_MODEL (model);
2218 gint idx;
2219
2220 assert (iter->stamp == TREE_MODEL_STAMP);
2221
2222 idx = GPOINTER_TO_INT (iter->user_data);
2223 return init_iter (list, idx == -1 ? -1 : idx + 1, iter);
2224 }
2225
2226 static GtkTreePath *
2227 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
2228 {
2229 GtkTreePath *path;
2230
2231 g_return_val_if_fail (iter->stamp == TREE_MODEL_STAMP, FALSE);
2232
2233 path = gtk_tree_path_new ();
2234 gtk_tree_path_append_index (path, GPOINTER_TO_INT (iter->user_data));
2235
2236 return path;
2237 }
2238
2239 static void
2240 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
2241 gint column, GValue *value)
2242 {
2243 TextImportModel *list = TEXT_IMPORT_MODEL (model);
2244 gint idx;
2245
2246 g_return_if_fail (iter->stamp == TREE_MODEL_STAMP);
2247
2248 idx = GPOINTER_TO_INT (iter->user_data);
2249 assert (idx >= 0 && idx < list->line_cnt);
2250
2251 if (column == 0)
2252 {
2253 g_value_init (value, G_TYPE_INT);
2254 g_value_set_int (value, idx + list->first_line + 1);
2255 }
2256 else
2257 {
2258 g_value_init (value, G_TYPE_STRING);
2259 g_value_set_static_string (value, ds_cstr (&list->lines[idx]));
2260 }
2261 }
2262
2263 static gboolean
2264 tree_model_iter_children (GtkTreeModel *tree_model,
2265 GtkTreeIter *iter,
2266 GtkTreeIter *parent)
2267 {
2268 return FALSE;
2269 }
2270
2271 static gint
2272 tree_model_n_children (GtkTreeModel *model, GtkTreeIter *iter)
2273 {
2274 TextImportModel *list = TEXT_IMPORT_MODEL (model);
2275
2276 return iter == NULL ? list->line_cnt : 0;
2277 }
2278
2279 static gboolean
2280 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
2281 GtkTreeIter *parent, gint n)
2282 {
2283 TextImportModel *list = TEXT_IMPORT_MODEL (model);
2284 g_return_val_if_fail (IS_TEXT_IMPORT_MODEL (model), FALSE);
2285
2286 if (parent)
2287 return FALSE;
2288 return init_iter (list, n, iter);
2289 }
2290
2291 static void
2292 text_import_model_tree_model_init (gpointer iface_, gpointer data UNUSED)
2293 {
2294 GtkTreeModelIface *iface = (GtkTreeModelIface *) iface_;
2295
2296 iface->get_flags = tree_model_get_flags;
2297 iface->get_n_columns = tree_model_n_columns;
2298 iface->get_column_type = tree_model_column_type;
2299 iface->get_iter = tree_model_get_iter;
2300 iface->iter_next = tree_model_iter_next;
2301 iface->get_path = tree_model_get_path;
2302 iface->get_value = tree_model_get_value;
2303
2304 iface->iter_children = tree_model_iter_children;
2305 iface->iter_has_child = tree_model_iter_has_child;
2306 iface->iter_n_children = tree_model_n_children;
2307 iface->iter_nth_child = tree_model_nth_child;
2308 iface->iter_parent = tree_model_iter_parent;
2309 }
2310
2311 gint
2312 text_import_model_iter_to_row (const GtkTreeIter *iter)
2313 {
2314 assert (iter->stamp == TREE_MODEL_STAMP);
2315 return GPOINTER_TO_INT (iter->user_data);
2316 }
2317
23182109 /* Increments the "watch cursor" level, setting the cursor for
23192110 the assistant window to a watch face to indicate to the user
23202111 that the ongoing operation may take some time. */
1414
1515 #include "psppire-dialog-action-correlation.h"
1616 #include "psppire-dialog-action-descriptives.h"
17 #include "psppire-dialog-action-examine.h"
18 #include "psppire-dialog-action-factor.h"
19 #include "psppire-dialog-action-indep-samps.h"
1720 #include "psppire-dialog-action-kmeans.h"
1821 #include "psppire-dialog-action-means.h"
1922 #include "psppire-means-layer.h"
23 #include "psppire-dialog-action-rank.h"
24 #include "psppire-dialog-action-regression.h"
2025 #include "psppire-dialog-action-reliability.h"
2126 #include "psppire-dialog-action-roc.h"
2227 #include "psppire-dialog-action-sort.h"
2328 #include "psppire-dialog-action-var-info.h"
29 #include "psppire-value-entry.h"
2430
2531
2632 /* Any custom widgets which are to be used in GtkBuilder ui files
3844 psppire_acr_get_type ();
3945 psppire_dict_view_get_type ();
4046 psppire_var_view_get_type ();
47 psppire_value_entry_get_type ();
4148
4249 psppire_dialog_action_correlation_get_type ();
4350 psppire_dialog_action_descriptives_get_type ();
51 psppire_dialog_action_examine_get_type ();
52 psppire_dialog_action_factor_get_type ();
4453 psppire_dialog_action_kmeans_get_type ();
4554 psppire_dialog_action_means_get_type ();
55 psppire_dialog_action_indep_samps_get_type ();
4656 psppire_means_layer_get_type ();
4757 psppire_dialog_action_var_info_get_type ();
58 psppire_dialog_action_rank_get_type ();
4859 psppire_dialog_action_reliability_get_type ();
60 psppire_dialog_action_regression_get_type ();
4961 psppire_dialog_action_roc_get_type ();
5062 psppire_dialog_action_sort_get_type ();
5163 }
1313 tests/libpspp/hmap-test \
1414 tests/libpspp/hmapx-test \
1515 tests/libpspp/i18n-test \
16 tests/libpspp/line-reader-test \
1617 tests/libpspp/ll-test \
1718 tests/libpspp/llx-test \
1819 tests/libpspp/range-map-test \
1920 tests/libpspp/range-set-test \
21 tests/libpspp/range-tower-test \
2022 tests/libpspp/sparse-array-test \
2123 tests/libpspp/sparse-xarray-test \
2224 tests/libpspp/str-test \
4143 tests_data_sack_LDADD = src/libpspp-core.la
4244 tests_data_sack_CFLAGS = $(AM_CFLAGS)
4345
46 tests_libpspp_line_reader_test_SOURCES = tests/libpspp/line-reader-test.c
47 tests_libpspp_line_reader_test_LDADD = src/libpspp/liblibpspp.la gl/libgl.la
48
4449 tests_libpspp_ll_test_SOURCES = \
4550 src/libpspp/ll.c \
4651 tests/libpspp/ll-test.c
97102 tests/libpspp/range-set-test.c
98103 tests_libpspp_range_set_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
99104 tests_libpspp_range_set_test_LDADD = src/libpspp/liblibpspp.la gl/libgl.la
105
106 tests_libpspp_range_tower_test_SOURCES = \
107 tests/libpspp/range-tower-test.c
108 tests_libpspp_range_tower_test_CPPFLAGS = $(AM_CPPFLAGS) -DASSERT_LEVEL=10
109 tests_libpspp_range_tower_test_LDADD = src/libpspp/liblibpspp.la gl/libgl.la
100110
101111 tests_libpspp_str_test_SOURCES = \
102112 tests/libpspp/str-test.c
298308 tests/language/utilities/insert.at \
299309 tests/language/utilities/permissions.at \
300310 tests/language/utilities/set.at \
311 tests/language/utilities/show.at \
301312 tests/language/utilities/title.at \
302313 tests/language/xforms/compute.at \
303314 tests/language/xforms/count.at \
312323 tests/libpspp/hmap.at \
313324 tests/libpspp/hmapx.at \
314325 tests/libpspp/i18n.at \
326 tests/libpspp/line-reader.at \
315327 tests/libpspp/ll.at \
316328 tests/libpspp/llx.at \
317329 tests/libpspp/range-map.at \
318330 tests/libpspp/range-set.at \
331 tests/libpspp/range-tower.at \
319332 tests/libpspp/sparse-array.at \
320333 tests/libpspp/sparse-xarray-test.at \
321334 tests/libpspp/str.at \
391404 tests/valgrind/llx-test \
392405 tests/valgrind/range-map-test \
393406 tests/valgrind/range-set-test \
407 tests/valgrind/range-tower-test \
394408 tests/valgrind/sparse-array-test \
395409 tests/valgrind/sparse-xarray-test \
396410 tests/valgrind/str-test \
4747 AT_CHECK([pspp do-if.sps], [0], [ignore])
4848 AT_CHECK([cat do-if.out], [0], [expout])
4949 AT_CLEANUP
50
51 AT_SETUP([unpaired END IF crash])
52 AT_DATA([do-if.sps], [dnl
53 DATA LIST LIST NOTABLE/a b c.
54 END IF.
55 ])
56 AT_CHECK([pspp -O format=csv do-if.sps], [1], [dnl
57 do-if.sps:2: error: END IF: This command cannot appear outside DO IF...END IF.
58 ])
59 AT_CLEANUP
567567 100
568568 ])
569569 AT_CLEANUP
570
571 AT_SETUP([GET DATA /TYPE=TXT with ENCODING subcommand])
572 AT_CHECK([i18n-test supports_encodings UTF-8 ISO-8859-1])
573 AT_DATA([get-data.sps], [dnl
574 set locale='utf-8'
575 get data /type=txt /file='data.txt' /encoding='iso-8859-1'
576 /delimiters="," /variables=s a8.
577 list.
578 ])
579 printf '\351' > data.txt # é in ISO-8859-1.
580 AT_CHECK([pspp -o pspp.csv get-data.sps])
581 AT_CHECK([cat pspp.csv], [0], [dnl
582 Table: Data List
583 s
584 é @&t@
585 ])
586 AT_CLEANUP
2424 ,Display Width: 14,,
2525 ])
2626 AT_CLEANUP
27
28
29 AT_BANNER([VARIABLE LABELS])
30
31 AT_SETUP([variable labels])
32
33 dnl The following test is to make sure the TVARS command works and that
34 dnl variables are displayed accordingly.
35 AT_DATA([var-labels.sps], [dnl
36 DATA LIST LIST NOTABLE /x * y *.
37 BEGIN DATA.
38 1 100
39 2 200
40 3 300
41 4 400
42 END DATA.
43
44 * While no labels have been set, the TVARS is irrelevant.
45 SET TVARS=NAMES.
46 DESCRIPTIVES ALL.
47
48 SET TVARS=LABELS.
49 DESCRIPTIVES ALL.
50
51 SET TVARS=BOTH.
52 DESCRIPTIVES ALL.
53
54 VARIABLE LABEL x 'foo' y 'bar'.
55
56 * Now, the TVARS setting should have effect
57
58 SET TVARS=NAMES.
59 DESCRIPTIVES ALL.
60
61 SET TVARS=LABELS.
62 DESCRIPTIVES ALL.
63
64 SET TVARS=BOTH.
65 DESCRIPTIVES ALL.
66 ])
67
68 AT_CHECK([pspp -O format=csv var-labels.sps], [0],[dnl
69 Table: Valid cases = 4; cases with missing value(s) = 0.
70 Variable,N,Mean,Std Dev,Minimum,Maximum
71 x,4,2.50,1.29,1.00,4.00
72 y,4,250.00,129.10,100.00,400.00
73
74 Table: Valid cases = 4; cases with missing value(s) = 0.
75 Variable,N,Mean,Std Dev,Minimum,Maximum
76 x,4,2.50,1.29,1.00,4.00
77 y,4,250.00,129.10,100.00,400.00
78
79 Table: Valid cases = 4; cases with missing value(s) = 0.
80 Variable,N,Mean,Std Dev,Minimum,Maximum
81 x,4,2.50,1.29,1.00,4.00
82 y,4,250.00,129.10,100.00,400.00
83
84 Table: Valid cases = 4; cases with missing value(s) = 0.
85 Variable,N,Mean,Std Dev,Minimum,Maximum
86 x,4,2.50,1.29,1.00,4.00
87 y,4,250.00,129.10,100.00,400.00
88
89 Table: Valid cases = 4; cases with missing value(s) = 0.
90 Variable,N,Mean,Std Dev,Minimum,Maximum
91 foo,4,2.50,1.29,1.00,4.00
92 bar,4,250.00,129.10,100.00,400.00
93
94 Table: Valid cases = 4; cases with missing value(s) = 0.
95 Variable,N,Mean,Std Dev,Minimum,Maximum
96 foo (x),4,2.50,1.29,1.00,4.00
97 bar (y),4,250.00,129.10,100.00,400.00
98 ])
99
100 AT_CLEANUP
115115 mv stdout expout
116116 AT_CHECK([pspp -O format=csv correlations2.sps], [0], [expout])
117117 AT_CLEANUP
118
119
120 AT_SETUP([CORRELATIONS -- non-square])
121 AT_DATA([corr-ns.sps], [dnl
122 set format = F11.3.
123 data list notable list /foo * bar * wiz *.
124 begin data.
125 1 1 6
126 2 2 5
127 3 3 4
128 4 4 3
129 5 5 2
130 6 6 1
131 end data.
132
133 correlations
134 variables = foo with bar wiz
135 .
136 ])
137
138 AT_CHECK([pspp -O format=csv corr-ns.sps], [0], [dnl
139 Table: Correlations
140 ,,bar,wiz
141 foo,Pearson Correlation,1.000,-1.000
142 ,Sig. (2-tailed),,.000
143 ,N,6,6
144 ])
145
146 AT_CLEANUP
518518 EXAMINE
519519 quality
520520 /STATISTICS descriptives
521 /PLOT = histogram
521522 .
522523 ])
523 AT_CHECK([pspp -o pspp.csv examine.sps])
524 AT_CHECK([pspp -o pspp.csv examine.sps], [0], [ignore])
524525 dnl Ignore output -- this is just a no-crash check.
525526 AT_CLEANUP
526527
586587 AT_CHECK([pspp -o pspp.csv examine.sps])
587588 dnl Ignore output -- this is just a no-crash check.
588589 AT_CLEANUP
590
591
592 dnl Test that the ID command works with non-numberic variables
593 AT_SETUP([EXAMINE -- non-numeric ID])
594
595 AT_DATA([examine-id.sps], [dnl
596 data list notable list /x * y (a12).
597 begin data.
598 1 one
599 2 two
600 3 three
601 4 four
602 5 five
603 6 six
604 7 seven
605 8 eight
606 9 nine
607 10 ten
608 11 eleven
609 12 twelve
610 30 thirty
611 300 threehundred
612 end data.
613
614 examine x
615 /statistics = extreme
616 /id = y
617 /plot = boxplot
618 .
619 ])
620
621 AT_CHECK([pspp -O format=csv examine-id.sps], [0],
622 [Table: Case Processing Summary
623 ,Cases,,,,,
624 ,Valid,,Missing,,Total,
625 ,N,Percent,N,Percent,N,Percent
626 x,14,100%,0,0%,14,100%
627
628 Table: Extreme Values
629 ,,,y,Value
630 x,Highest,1,threehundred,300.00
631 ,,2,thirty ,30.00
632 ,,3,twelve ,12.00
633 ,,4,eleven ,11.00
634 ,,5,ten ,10.00
635 ,Lowest,1,one ,1.00
636 ,,2,two ,2.00
637 ,,3,three ,3.00
638 ,,4,four ,4.00
639 ,,5,five ,5.00
640 ])
641
642 AT_CLEANUP
643
644 dnl Test for a crash which happened on cleanup from a bad input syntax
645 AT_SETUP([EXAMINE -- Bad Input])
646
647 AT_DATA([examine-bad.sps], [dnl
648 data list list /h * g *.
649 begin data.
650 1 1
651 2 1
652 3 1
653 4 1
654 5 2
655 6 2
656 7 2
657 8 2
658 9 2
659 end data.
660
661 EXAMINE
662 /VARIABLES= h
663 BY g
664 /STATISTICS = DESCRIPTIVES EXTREME
665 /PLOT = lkajsdas
666 .
667 ])
668
669 AT_CHECK([pspp -o pspp.csv examine-bad.sps], [1], [ignore])
670
671 AT_CLEANUP
672
673
674 dnl Check the MISSING=REPORT option
675 AT_SETUP([EXAMINE -- MISSING=REPORT])
676
677
678 AT_DATA([examine-report.sps], [dnl
679 set format = F22.0.
680 data list list /x * g *.
681 begin data.
682 1 1
683 2 1
684 3 1
685 4 1
686 5 1
687 6 1
688 7 1
689 8 1
690 9 1
691 10 2
692 20 2
693 30 2
694 40 2
695 50 2
696 60 2
697 70 2
698 80 2
699 90 2
700 101 9
701 201 9
702 301 9
703 401 9
704 501 99
705 601 99
706 701 99
707 801 99
708 901 99
709 1001 .
710 2002 .
711 3003 .
712 4004 .
713 end data.
714
715 MISSING VALUES g (9, 99, 999).
716
717 EXAMINE
718 /VARIABLES = x
719 BY g
720 /STATISTICS = EXTREME
721 /NOTOTAL
722 /MISSING = REPORT.
723 ])
724
725
726 AT_CHECK([pspp -O format=csv examine-report.sps], [0], [dnl
727 Table: Reading free-form data from INLINE.
728 Variable,Format
729 x,F8.0
730 g,F8.0
731
732 Table: Case Processing Summary
733 ,,Cases,,,,,
734 ,,Valid,,Missing,,Total,
735 ,g,N,Percent,N,Percent,N,Percent
736 x,. (missing),4,100%,0,0%,4,100%
737 ,1,9,100%,0,0%,9,100%
738 ,2,9,100%,0,0%,9,100%
739 ,9 (missing),4,100%,0,0%,4,100%
740 ,99 (missing),5,100%,0,0%,5,100%
741
742 Table: Extreme Values
743 ,g,,,Case Number,Value
744 x,. (missing),Highest,1,31,4004
745 ,,,2,30,3003
746 ,,,3,29,2002
747 ,,,4,28,1001
748 ,,,5,0,0
749 ,,Lowest,1,28,1001
750 ,,,2,29,2002
751 ,,,3,30,3003
752 ,,,4,31,4004
753 ,,,5,31,4004
754 ,1,Highest,1,9,9
755 ,,,2,8,8
756 ,,,3,7,7
757 ,,,4,6,6
758 ,,,5,5,5
759 ,,Lowest,1,1,1
760 ,,,2,2,2
761 ,,,3,3,3
762 ,,,4,4,4
763 ,,,5,5,5
764 ,2,Highest,1,18,90
765 ,,,2,17,80
766 ,,,3,16,70
767 ,,,4,15,60
768 ,,,5,14,50
769 ,,Lowest,1,10,10
770 ,,,2,11,20
771 ,,,3,12,30
772 ,,,4,13,40
773 ,,,5,14,50
774 ,9 (missing),Highest,1,22,401
775 ,,,2,21,301
776 ,,,3,20,201
777 ,,,4,19,101
778 ,,,5,0,0
779 ,,Lowest,1,19,101
780 ,,,2,20,201
781 ,,,3,21,301
782 ,,,4,22,401
783 ,,,5,22,401
784 ,99 (missing),Highest,1,27,901
785 ,,,2,26,801
786 ,,,3,25,701
787 ,,,4,24,601
788 ,,,5,23,501
789 ,,Lowest,1,23,501
790 ,,,2,24,601
791 ,,,3,25,701
792 ,,,4,26,801
793 ,,,5,27,901
794 ])
795
796
797 AT_CLEANUP
17951795
17961796 AT_CHECK([pspp -O format=csv factor-empty.sps], [0], [ignore])
17971797 AT_CLEANUP
1798
1799
1800 dnl Fixes a crash reported at
1801 dnl http://lists.gnu.org/archive/html/bug-gnu-pspp/2012-04/msg00001.html
1802 AT_SETUP([FACTOR /ROTATION=NOROTATE])
1803 AT_DATA([factor-norotate.sps], [dnl
1804 DATA LIST FREE / TRAIT1 TO TRAIT5 (F8.2).
1805 BEGIN DATA
1806 1 5 5 1 1
1807 8 9 7 9 8
1808 9 8 9 9 8
1809 9 9 9 9 9
1810 1 9 1 1 9
1811 9 7 7 9 9
1812 9 7 9 9 7
1813 END DATA
1814
1815 FACTOR /VARIABLES=TRAIT1 TO TRAIT5
1816 /ROTATION=NOROTATE /* NOROTATE may have caused the problem. */
1817 /EXTRACTION=PC
1818 /PRINT=DEFAULT DET UNIVARIATE ROTATION SIG CORRELATION.
1819 ])
1820 AT_CHECK([pspp -O format=csv factor-norotate.sps], [0], [dnl
1821 Table: Descriptive Statistics
1822 ,Mean,Std. Deviation,Analysis N
1823 TRAIT1,6.57,3.54,7
1824 TRAIT2,7.71,1.39,7
1825 TRAIT3,6.71,2.71,7
1826 TRAIT4,6.71,3.61,7
1827 TRAIT5,7.29,2.66,7
1828
1829 Table: Correlation Matrix
1830 ,,TRAIT1,TRAIT2,TRAIT3,TRAIT4,TRAIT5
1831 Correlations,TRAIT1,1.00,.30,.88,1.00,.54
1832 ,TRAIT2,.30,1.00,-.02,.33,.84
1833 ,TRAIT3,.88,-.02,1.00,.87,.13
1834 ,TRAIT4,1.00,.33,.87,1.00,.54
1835 ,TRAIT5,.54,.84,.13,.54,1.00
1836 Sig. (1-tailed),TRAIT1,,.26,.00,.00,.10
1837 ,TRAIT2,.26,,.48,.24,.01
1838 ,TRAIT3,.00,.48,,.01,.39
1839 ,TRAIT4,.00,.24,.01,,.10
1840 ,TRAIT5,.10,.01,.39,.10,
1841 Determinant,.00,,,,,
1842
1843 Table: Communalities
1844 ,Initial,Extraction
1845 TRAIT1,1.00,1.00
1846 TRAIT2,1.00,1.00
1847 TRAIT3,1.00,.99
1848 TRAIT4,1.00,.99
1849 TRAIT5,1.00,.99
1850
1851 Table: Total Variance Explained
1852 ,Initial Eigenvalues,,,Extraction Sums of Squared Loadings,,
1853 Component,Total,% of Variance,Cumulative %,Total,% of Variance,Cumulative %
1854 1,3.26,65.26,65.26,3.26,65.26,65.26
1855 2,1.54,30.77,96.03,1.54,30.77,96.03
1856 3,.17,3.36,99.39,.17,3.36,99.39
1857 4,.03,.61,100.00,.03,.61,100.00
1858 5,.00,.00,100.00,,,
1859
1860 Table: Component Matrix
1861 ,Component,,,
1862 ,1,2,3,4
1863 TRAIT1,.97,.23,-.08,.00
1864 TRAIT2,.52,-.81,.28,.00
1865 TRAIT3,.78,.59,.17,.00
1866 TRAIT4,.97,.21,-.04,.00
1867 TRAIT5,.70,-.67,-.23,.00
1868 ])
1869 AT_CLEANUP
151151
152152 frequencies /x /histogram /STATISTICS=median.
153153 ])
154 AT_CHECK([pspp -O format=csv frequencies.sps], [0], [dnl
155 Table: x
156 Value Label,Value,Frequency,Percent,Valid Percent,Cum Percent
157 ,1.00,1,100.00,100.00,100.00
158 Total,,1,100.0,100.0,
159
160 Table: x
161 N,Valid,1
162 ,Missing,0
163 S.E. Kurt,,.00
164 ,50 (Median),1.00
165 ])
154 AT_CHECK([pspp -O format=csv frequencies.sps], [0], [ignore])
155 dnl Ignore output - No crash test.
166156 AT_CLEANUP
167157
168158 # Tests for a bug which caused FREQUENCIES following TEMPORARY to
0 AT_BANNER([SHOW])
1
2 AT_SETUP([SHOW N])
3
4 AT_DATA([show.sps], [dnl
5 DATA LIST LIST NOTABLE /x.
6 BEGIN DATA.
7 1
8 2
9 3
10 END DATA.
11
12 SHOW N.
13 ])
14
15 AT_CHECK([pspp -O format=csv show.sps], [0], [dnl
16 show.sps:8: note: SHOW: N is 3.
17 ])
18
19 AT_CLEANUP
20
21
22 AT_SETUP([SHOW N empty])
23
24 AT_DATA([shown-empty.sps], [dnl
25 SHOW N.
26 ])
27
28 AT_CHECK([pspp -O format=csv shown-empty.sps], [0], [dnl
29 shown-empty.sps:1: note: SHOW: N is Unknown.
30 ])
31
32 AT_CLEANUP
33
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2010 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
137137 /* Recalculates the count for NODE's subtree by adding up the
138138 counts for its LEFT and RIGHT child subtrees. */
139139 static void
140 reaugment_elements (struct abt_node *node_,
141 const struct abt_node *left,
142 const struct abt_node *right,
143 const void *aux)
140 reaugment_elements (struct abt_node *node_, const void *aux)
144141 {
145142 struct element *node = abt_node_to_element (node_);
146143
147144 check (aux == &aux_data);
148145
149146 node->count = 1;
150 if (left != NULL)
151 node->count += abt_node_to_element (left)->count;
152 if (right != NULL)
153 node->count += abt_node_to_element (right)->count;
147 if (node->node.down[0] != NULL)
148 node->count += abt_node_to_element (node->node.down[0])->count;
149 if (node->node.down[1] != NULL)
150 node->count += abt_node_to_element (node->node.down[1])->count;
154151 }
155152
156153 /* Compares A and B and returns a strcmp-type return value. */
373370 check (abt_node_to_element (p)->data == order[cnt - i - 1]);
374371 check (p == NULL);
375372 }
373 check (abt_is_empty (abt) == (cnt == 0));
376374
377375 free (order);
378376 }
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2010, 2011 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 #include <config.h>
17
18 #include "libpspp/line-reader.h"
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "libpspp/i18n.h"
28 #include "libpspp/str.h"
29
30 #include "gl/error.h"
31 #include "gl/progname.h"
32 #include "gl/xalloc.h"
33
34 static void
35 usage (void)
36 {
37 printf ("usage: %s COMMAND [ARG]...\n"
38 "The available commands are:\n"
39 " help\n"
40 " print this usage message\n"
41 " buffer-size\n"
42 " print the buffer size, in bytes, on stdout\n"
43 " read FILE ENCODING\n"
44 " read FILE encoded in ENCODING and print it in UTF-8\n",
45 program_name);
46 exit (0);
47 }
48
49 static void
50 cmd_read (int argc, char *argv[])
51 {
52 struct line_reader *r;
53 const char *filename;
54 struct string line;
55 char *encoding;
56
57 if (argc != 4)
58 error (1, 0, "bad syntax for `%s' command; use `%s help' for help",
59 argv[1], program_name);
60
61 filename = argv[2];
62
63 r = (!strcmp(filename, "-")
64 ? line_reader_for_fd (argv[3], STDIN_FILENO)
65 : line_reader_for_file (argv[3], filename, O_RDONLY));
66 if (r == NULL)
67 error (1, errno, "line_reader_open failed");
68
69 encoding = xstrdup (line_reader_get_encoding (r));
70 printf ("encoded in %s", encoding);
71 if (line_reader_is_auto (r))
72 printf (" (auto)");
73 printf ("\n");
74
75 ds_init_empty (&line);
76 while (line_reader_read (r, &line, SIZE_MAX))
77 {
78 const char *new_encoding;
79 char *utf8_line;
80
81 new_encoding = line_reader_get_encoding (r);
82 if (strcmp (encoding, new_encoding))
83 {
84 free (encoding);
85 encoding = xstrdup (new_encoding);
86
87 printf ("encoded in %s", encoding);
88 if (line_reader_is_auto (r))
89 printf (" (auto)");
90 printf ("\n");
91 }
92
93 utf8_line = recode_string ("UTF-8", encoding,
94 ds_data (&line), ds_length (&line));
95 printf ("\"%s\"\n", utf8_line);
96 free (utf8_line);
97
98 ds_clear (&line);
99 }
100
101 if (!strcmp(filename, "-"))
102 line_reader_free (r);
103 else
104 {
105 if (line_reader_close (r) != 0)
106 error (1, errno, "line_reader_close failed");
107 }
108 }
109
110 int
111 main (int argc, char *argv[])
112 {
113 set_program_name (argv[0]);
114 i18n_init ();
115
116 if (argc < 2)
117 error (1, 0, "missing command name; use `%s help' for help", program_name);
118 else if (!strcmp(argv[1], "help") || !strcmp(argv[1], "--help"))
119 usage ();
120 else if (!strcmp(argv[1], "buffer-size"))
121 printf ("%d\n", LINE_READER_BUFFER_SIZE);
122 else if (!strcmp(argv[1], "read"))
123 cmd_read (argc, argv);
124 else
125 error (1, 0, "unknown command `%s'; use `%s help' for help",
126 argv[1], program_name);
127
128 return 0;
129 }
0 AT_BANNER([line_reader])
1
2 AT_SETUP([read ASCII])
3 AT_KEYWORDS([line_reader])
4 AT_CHECK([i18n-test supports_encodings ASCII])
5 AT_CHECK([echo string | line-reader-test read - ASCII], [0], [dnl
6 encoded in ASCII
7 "string"
8 ])
9 AT_CLEANUP
10
11 AT_SETUP([read UTF-8])
12 AT_KEYWORDS([line_reader])
13 AT_CHECK([printf '\346\227\245\346\234\254\350\252\236\n' | line-reader-test read - UTF-8], [0], [dnl
14 encoded in UTF-8
15 "日本語"
16 ])
17 AT_CLEANUP
18
19 AT_SETUP([read EUC-JP])
20 AT_KEYWORDS([line_reader])
21 AT_CHECK([i18n-test supports_encodings EUC-JP])
22 AT_CHECK([printf '\244\241 \244\242 \244\243 \244\244 \244\245 \244\246 \244\247 \244\250 \244\251 \244\252\n' | line-reader-test read - EUC-JP], [0], [dnl
23 encoded in EUC-JP
24 "ぁ あ ぃ い ぅ う ぇ え ぉ お"
25 ])
26 AT_CLEANUP
27
28 AT_SETUP([read ASCII as Auto])
29 AT_KEYWORDS([line_reader])
30 AT_CHECK([echo string | line-reader-test read - Auto], [0], [dnl
31 encoded in ASCII (auto)
32 "string"
33 ])
34 AT_CLEANUP
35
36 AT_SETUP([read UTF-8 as Auto])
37 AT_KEYWORDS([line_reader])
38 AT_CHECK([printf 'entr\303\251e\n' | line-reader-test read - Auto], [0], [dnl
39 encoded in ASCII (auto)
40 encoded in UTF-8
41 "entrée"
42 ])
43 AT_CLEANUP
44
45 AT_SETUP([read ISO-8859-1 as Auto,ISO-8859-1])
46 AT_KEYWORDS([line_reader])
47 AT_CHECK([i18n-test supports_encodings ISO-8859-1])
48 buffer_size=`line-reader-test buffer-size`
49 ($PERL -e "print 'x' x ($buffer_size - 2)"
50 printf '\none line\ntwo lines\nentr\351e\nfour lines\n') > input
51 (printf 'encoded in ASCII (auto)\n\"'
52 $PERL -e "print 'x' x ($buffer_size - 2)"
53 printf '\"\n"one line"\n"two lines"\nencoded in ISO-8859-1\n"entr\303\251e"\n"four lines"\n') > expout
54 AT_CHECK([line-reader-test read input Auto,ISO-8859-1], [0], [expout])
55 AT_CLEANUP
56
57 AT_SETUP([read UTF-16BE as Auto,UTF-16BE])
58 AT_KEYWORDS([line_reader])
59 AT_CHECK([i18n-test supports_encodings UTF-16BE])
60 AT_CHECK([printf '\0e\0n\0t\0r\0\351\0e\0\n' | line-reader-test read - Auto,UTF-16BE],
61 [0], [encoded in UTF-16BE
62 "entrée"
63 ])
64 AT_CLEANUP
65
66 AT_SETUP([read EUC-JP as Auto,EUC-JP])
67 AT_KEYWORDS([line_reader])
68 AT_CHECK([i18n-test supports_encodings EUC-JP])
69 AT_CHECK([printf 'entr\217\253\261e\n' | line-reader-test read - Auto,EUC-JP],
70 [0], [encoded in EUC-JP
71 "entrée"
72 ])
73 AT_CLEANUP
00 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
22
33 This program is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
162162 const struct range_set_node *node;
163163
164164 printf ("result:");
165 for (node = range_set_first (rs); node != NULL;
166 node = range_set_next (rs, node))
165 RANGE_SET_FOR_EACH (node, rs)
167166 printf (" (%lu,%lu)",
168167 range_set_node_get_start (node), range_set_node_get_end (node));
169168 printf ("\n");
253252 unsigned long int width = 0;
254253 struct range_set *rs = range_set_create_pool (NULL);
255254 while (next_region (pattern, start + width, &start, &width))
256 range_set_insert (rs, start, width);
255 range_set_set1 (rs, start, width);
257256 check_pattern (rs, pattern);
258257 return rs;
259258 }
293292 unsigned int final_pat;
294293
295294 rs = make_pattern (init_pat);
296 range_set_insert (rs, i, j - i);
295 range_set_set1 (rs, i, j - i);
297296 final_pat = init_pat | bit_range (i, j - i);
298297 check_pattern (rs, final_pat);
299298 rs2 = range_set_clone (rs, NULL);
326325 unsigned int final_pat;
327326
328327 rs = make_pattern (init_pat);
329 range_set_delete (rs, i, j - i);
328 range_set_set0 (rs, i, j - i);
330329 final_pat = init_pat & ~bit_range (i, j - i);
331330 check_pattern (rs, final_pat);
332331 range_set_destroy (rs);
460459 Makes sure that this doesn't cause a double-free. */
461460 pool = pool_create ();
462461 rs = range_set_create_pool (pool);
463 range_set_insert (rs, 1, 10);
462 range_set_set1 (rs, 1, 10);
464463 range_set_destroy (rs);
465464 pool_destroy (pool);
466465
468467 Makes sure that this doesn't cause a leak. */
469468 pool = pool_create ();
470469 rs = range_set_create_pool (pool);
471 range_set_insert (rs, 1, 10);
470 range_set_set1 (rs, 1, 10);
472471 pool_destroy (pool);
473472 }
474473
0 /* PSPP - a program for statistical analysis.
1 Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
2
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16 /* This is a test program for the routines defined in
17 range-tower.c. This test program aims to be as comprehensive as
18 possible. With -DNDEBUG, "gcov -b" should report 100%
19 coverage of lines and branches in range-tower.c routines.
20 (Without -DNDEBUG, branches caused by failed assertions will
21 not be taken.) "valgrind --leak-check=yes
22 --show-reachable=yes" should give a clean report, both with
23 and without -DNDEBUG. */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include "libpspp/range-tower.h"
30
31 #include <assert.h>
32 #include <limits.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "libpspp/compiler.h"
38 #include "libpspp/pool.h"
39
40 #include "gl/minmax.h"
41 #include "gl/xalloc.h"
42
43 /* Exit with a failure code.
44 (Place a breakpoint on this function while debugging.) */
45 static void
46 check_die (void)
47 {
48 abort ();
49 }
50
51 /* If OK is not true, prints a message about failure on the
52 current source file and the given LINE and terminates. */
53 static void
54 check_func (bool ok, int line)
55 {
56 if (!ok)
57 {
58 fprintf (stderr, "%s:%d: check failed\n", __FILE__, line);
59 check_die ();
60 }
61 }
62
63 /* Verifies that EXPR evaluates to true.
64 If not, prints a message citing the calling line number and
65 terminates. */
66 #define check(EXPR) check_func ((EXPR), __LINE__)
67
68 /* A contiguous region. */
69 struct region
70 {
71 unsigned long int start; /* Start of region. */
72 unsigned long int end; /* One past the end. */
73 };
74
75 /* Number of bits in an unsigned int. */
76 #define UINT_BIT (CHAR_BIT * sizeof (unsigned int))
77
78 /* Returns the number of contiguous 1-bits in X starting from bit
79 0.
80 This implementation is designed to be obviously correct, not
81 to be efficient. */
82 static int
83 count_one_bits (unsigned long int x)
84 {
85 int count = 0;
86 while (x & 1)
87 {
88 count++;
89 x >>= 1;
90 }
91 return count;
92 }
93
94 /* Searches the bits in PATTERN from right to left starting from
95 bit OFFSET for one or more 1-bits. If any are found, sets
96 *START to the bit index of the first and *WIDTH to the number
97 of contiguous 1-bits and returns true. Otherwise, returns
98 false.
99 This implementation is designed to be obviously correct, not
100 to be efficient. */
101 static bool
102 next_region (unsigned int pattern, unsigned int offset,
103 unsigned long int *start, unsigned long int *width)
104 {
105 unsigned int i;
106
107 assert (offset <= UINT_BIT);
108 for (i = offset; i < UINT_BIT; i++)
109 if (pattern & (1u << i))
110 {
111 *start = i;
112 *width = count_one_bits (pattern >> i);
113 return true;
114 }
115 return false;
116 }
117
118 /* Searches the bits in PATTERN from left to right starting from
119 just beyond bit OFFSET for one or more 1-bits. If any are
120 found, sets *START to the bit index of the first and *WIDTH to
121 the number of contiguous 1-bits and returns true. Otherwise,
122 returns false.
123 This implementation is designed to be obviously correct, not
124 to be efficient. */
125 static bool
126 prev_region (unsigned int pattern, unsigned int offset,
127 unsigned long int *start, unsigned long int *width)
128 {
129 unsigned int i;
130
131 assert (offset <= UINT_BIT);
132 for (i = offset; i-- > 0; )
133 if (pattern & (1u << i))
134 {
135 *start = i;
136 *width = 1;
137 while (i-- > 0 && pattern & (1u << i))
138 {
139 ++*width;
140 --*start;
141 }
142 return true;
143 }
144 return false;
145 }
146
147 /* Searches the bits in PATTERN from right to left starting from
148 bit OFFSET. Returns the bit index of the first 1-bit found,
149 or ULONG_MAX if none is found. */
150 static unsigned long int
151 next_1bit (unsigned int pattern, unsigned int offset,
152 unsigned long int pattern_offset)
153 {
154 for (; offset < UINT_BIT; offset++)
155 if (pattern & (1u << offset))
156 return offset + pattern_offset;
157 return ULONG_MAX;
158 }
159
160 static void
161 print_structure (const struct abt_node *node_)
162 {
163 struct range_tower_node *node;
164
165 if (node_ == NULL)
166 return;
167 node = abt_data (node_, struct range_tower_node, abt_node);
168 printf ("%lu+%lu/%d", node->n_zeros, node->n_ones, node->abt_node.level);
169 if (node->abt_node.down[0] || node->abt_node.down[1])
170 {
171 printf ("(");
172 print_structure (node->abt_node.down[0]);
173 printf (",");
174 print_structure (node->abt_node.down[1]);
175 printf (")");
176 }
177 }
178
179 /* Prints the regions in RT to stdout. */
180 static void UNUSED
181 print_regions (const struct range_tower *rt)
182 {
183 const struct range_tower_node *node;
184
185 printf ("contents:");
186 for (node = range_tower_first__ (rt); node != NULL;
187 node = range_tower_next__ (rt, node))
188 printf (" (%lu,%lu)", node->n_zeros, node->n_ones);
189 printf ("\n");
190 printf ("structure:");
191 print_structure (rt->abt.root);
192 printf ("\n");
193 }
194
195 static void
196 check_tree (const struct abt_node *abt_node, unsigned long int *subtree_width)
197 {
198 const struct range_tower_node *node = range_tower_node_from_abt__ (abt_node);
199 unsigned long int left_width, right_width;
200
201 if (node == NULL)
202 {
203 *subtree_width = 0;
204 return;
205 }
206
207 check_tree (node->abt_node.down[0], &left_width);
208 check_tree (node->abt_node.down[1], &right_width);
209
210 *subtree_width = node->n_zeros + node->n_ones + left_width + right_width;
211 check (node->subtree_width == *subtree_width);
212 }
213
214 /* Checks that the regions in RT match the bits in PATTERN. */
215 static void
216 check_pattern (const struct range_tower *rt, unsigned int pattern,
217 unsigned long int offset)
218 {
219 const struct range_tower_node *node;
220 unsigned long int start, start2, width;
221 unsigned long int tree_width;
222 unsigned long int s1, s2;
223 int i;
224
225 check_tree (rt->abt.root, &tree_width);
226 check (tree_width == ULONG_MAX);
227
228 if (offset > ULONG_MAX - 32)
229 {
230 pattern <<= offset - (ULONG_MAX - 32);
231 offset = ULONG_MAX - 32;
232 }
233
234 for (node = rand () % 2 ? range_tower_first (rt) : range_tower_next (rt, NULL),
235 start = width = 0;
236 next_region (pattern, start + width, &start, &width);
237 node = range_tower_next (rt, node))
238 {
239 unsigned long int node_start;
240 unsigned long int x;
241
242 check (node != NULL);
243 check (range_tower_node_get_start (node) == start + offset);
244 check (range_tower_node_get_end (node) == start + offset + width);
245 check (range_tower_node_get_width (node) == width);
246
247 x = start + offset - node->n_zeros;
248 check (range_tower_lookup (rt, x, &node_start) == node);
249 check (node_start == start + offset - node->n_zeros);
250
251 x = start + offset + width - 1;
252 check (range_tower_lookup (rt, x, &node_start) == node);
253 check (node_start == start + offset - node->n_zeros);
254 }
255 check (node == NULL);
256
257 start = width = 0;
258 RANGE_TOWER_FOR_EACH (node, start2, rt)
259 {
260 check (next_region (pattern, start + width, &start, &width));
261 check (start + offset == start2);
262 check (range_tower_node_get_width (node) == width);
263 }
264 check (!next_region (pattern, start + width, &start, &width));
265
266 for (node = rand () % 2 ? range_tower_last (rt) : range_tower_prev (rt, NULL),
267 start = UINT_BIT;
268 prev_region (pattern, start, &start, &width);
269 node = range_tower_prev (rt, node))
270 {
271 check (node != NULL);
272 check (range_tower_node_get_start (node) == offset + start);
273 check (range_tower_node_get_end (node) == offset + start + width);
274 check (range_tower_node_get_width (node) == width);
275 }
276 check (node == NULL);
277
278 /* Scan from all possible positions, resetting the cache each
279 time, to ensure that we get the correct answers without
280 caching. */
281 for (start = 0; start <= 32; start++)
282 {
283 struct range_tower *nonconst_rt = CONST_CAST (struct range_tower *, rt);
284
285 nonconst_rt->cache_end = 0;
286 s1 = range_tower_scan (rt, offset + start);
287 s2 = next_1bit (pattern, start, offset);
288 check (s1 == s2);
289 }
290
291 /* Scan in forward order to exercise expected cache behavior. */
292 for (s1 = range_tower_scan (rt, 0), s2 = next_1bit (pattern, 0, offset); ;
293 s1 = range_tower_scan (rt, s1 + 1), s2 = next_1bit (pattern, (s2 - offset) + 1, offset))
294 {
295 check (s1 == s2);
296 if (s1 == ULONG_MAX)
297 break;
298 }
299
300 /* Scan in random order to frustrate cache. */
301 for (i = 0; i < 32; i++)
302 {
303 start = rand () % 32;
304 s1 = range_tower_scan (rt, start + offset);
305 s2 = next_1bit (pattern, start, offset);
306 check (s1 == s2);
307 }
308
309 /* Test range_tower_scan() with negative cache. */
310 check (!range_tower_contains (rt, 999));
311 if (offset < 1111)
312 check (range_tower_scan (rt, 1111) == ULONG_MAX);
313
314 /* Check for containment without caching. */
315 for (i = 0; i < UINT_BIT; i++)
316 {
317 struct range_tower *nonconst_rt = CONST_CAST (struct range_tower *, rt);
318 nonconst_rt->cache_end = 0;
319 check (range_tower_contains (rt, i + offset)
320 == ((pattern & (1u << i)) != 0));
321 }
322
323 /* Check for containment with caching. */
324 for (i = 0; i < UINT_BIT; i++)
325 check (range_tower_contains (rt, i + offset)
326 == ((pattern & (1u << i)) != 0));
327
328 check (!range_tower_contains (rt,
329 UINT_BIT + rand () % (ULONG_MAX - UINT_BIT * 2)));
330
331 check (range_tower_is_empty (rt) == (pattern == 0));
332 }
333
334 /* Creates and returns a range tower that contains regions for the
335 bits tower in PATTERN. */
336 static struct range_tower *
337 make_pattern (unsigned int pattern, unsigned long int offset)
338 {
339 unsigned long int start = 0;
340 unsigned long int width = 0;
341 struct range_tower *rt = range_tower_create_pool (NULL);
342 while (next_region (pattern, start + width, &start, &width))
343 range_tower_set1 (rt, start + offset, width);
344 check_pattern (rt, pattern, offset);
345 return rt;
346 }
347
348 /* Returns an unsigned int with bits OFS...OFS+CNT (exclusive)
349 tower to 1, other bits tower to 0. */
350 static unsigned int
351 bit_range (unsigned int ofs, unsigned int cnt)
352 {
353 assert (ofs < UINT_BIT);
354 assert (cnt <= UINT_BIT);
355 assert (ofs + cnt <= UINT_BIT);
356
357 return cnt < UINT_BIT ? ((1u << cnt) - 1) << ofs : UINT_MAX;
358 }
359
360 /* Tests setting all possible ranges of 1s into all possible range sets (up to
361 a small maximum number of bits). */
362 static void
363 test_set1 (void)
364 {
365 const int positions = 9;
366 unsigned int init_pat;
367 int start, width;
368 int k;
369
370 for (k = 0; k < 2; k++)
371 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
372 for (start = 0; start < positions; start++)
373 for (width = 0; width + start <= positions; width++)
374 {
375 unsigned long int offset = k ? ULONG_MAX - positions : 0;
376 struct range_tower *rt, *rt2;
377 unsigned int final_pat;
378
379 rt = make_pattern (init_pat, offset);
380 range_tower_set1 (rt, offset + start, width);
381 final_pat = init_pat | bit_range (start, width);
382 check_pattern (rt, final_pat, offset);
383 rt2 = range_tower_clone (rt, NULL);
384 check_pattern (rt2, final_pat, offset);
385 range_tower_destroy (rt);
386 range_tower_destroy (rt2);
387 }
388 }
389
390 /* Tests setting all possible ranges of 0s into all possible range sets (up to
391 a small maximum number of bits). */
392 static void
393 test_set0 (void)
394 {
395 const int positions = 9;
396 unsigned int init_pat;
397 int start, width, k;
398
399 for (k = 0; k < 2; k++)
400 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
401 for (start = 0; start < positions; start++)
402 for (width = 0; start + width <= positions; width++)
403 {
404 unsigned long int offset = k ? ULONG_MAX - positions : 0;
405 struct range_tower *rt;
406 unsigned int final_pat;
407
408 rt = make_pattern (init_pat, offset);
409 range_tower_set0 (rt, offset + start, width);
410 final_pat = init_pat & ~bit_range (start, width);
411 check_pattern (rt, final_pat, offset);
412 range_tower_destroy (rt);
413 }
414 }
415
416 /* Tests inserting all possible ranges of 0s into all possible range sets (up
417 to a small maximum number of bits). */
418 static void
419 test_insert0 (void)
420 {
421 const int positions = 9;
422 unsigned int init_pat;
423 int start, width, k;
424
425 for (k = 0; k < 2; k++)
426 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
427 for (start = 0; start < positions; start++)
428 for (width = 0; start + width <= positions; width++)
429 {
430 unsigned long int offset = k ? ULONG_MAX - positions : 0;
431 struct range_tower *rt;
432 unsigned int final_pat;
433
434 rt = make_pattern (init_pat, offset);
435 range_tower_insert0 (rt, offset + start, width);
436 final_pat = init_pat & bit_range (0, start);
437 final_pat |= (init_pat & bit_range (start, positions - start)) << width;
438 check_pattern (rt, final_pat, offset);
439 range_tower_destroy (rt);
440 }
441 }
442
443 /* Tests inserting all possible ranges of 1s into all possible range sets (up
444 to a small maximum number of bits). */
445 static void
446 test_insert1 (void)
447 {
448 const int positions = 9;
449 unsigned int init_pat;
450 int start, width, k;
451
452 for (k = 0; k < 2; k++)
453 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
454 for (start = 0; start < positions; start++)
455 for (width = 0; start + width <= positions; width++)
456 {
457 struct range_tower *rt;
458 unsigned int final_pat;
459
460 rt = make_pattern (init_pat, 0);
461 range_tower_insert1 (rt, start, width);
462 final_pat = init_pat & bit_range (0, start);
463 final_pat |= bit_range (start, width);
464 final_pat |= (init_pat & bit_range (start, positions - start)) << width;
465 check_pattern (rt, final_pat, 0);
466 range_tower_destroy (rt);
467 }
468 }
469
470 /* Tests setting all possible ranges from all possible range sets (up to a
471 small maximum number of bits). */
472 static void
473 test_delete (void)
474 {
475 const int positions = 9;
476 unsigned int init_pat;
477 int start, width, k;
478
479 for (k = 0; k < 2; k++)
480 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
481 for (start = 0; start < positions; start++)
482 for (width = 0; start + width <= positions; width++)
483 {
484 unsigned long int offset = k ? ULONG_MAX - positions : 0;
485 struct range_tower *rt;
486 unsigned int final_pat;
487
488 rt = make_pattern (init_pat, offset);
489 range_tower_delete (rt, start + offset, width);
490 final_pat = init_pat & bit_range (0, start);
491 final_pat |= (init_pat & (UINT_MAX << (start + width))) >> width;
492 check_pattern (rt, final_pat, offset);
493 range_tower_destroy (rt);
494 }
495 }
496
497 /* Tests moving all possible ranges (up to a small maximum number of bits). */
498 static void
499 test_move (void)
500 {
501 const int positions = 9;
502 unsigned int init_pat;
503 int new_start, old_start, width, k;
504
505 for (k = 0; k < 2; k++)
506 for (init_pat = 0; init_pat < (1u << positions); init_pat++)
507 for (width = 0; width <= positions; width++)
508 for (new_start = 0; new_start + width <= positions; new_start++)
509 for (old_start = 0; old_start + width <= positions; old_start++)
510 {
511 unsigned long int offset = k ? ULONG_MAX - positions : 0;
512 struct range_tower *rt;
513 unsigned int final_pat;
514
515 if (new_start == old_start || width == 0)
516 final_pat = init_pat;
517 else if (new_start < old_start)
518 {
519 final_pat = init_pat & bit_range (0, new_start);
520 final_pat |= (init_pat & bit_range (old_start, width)) >> (old_start - new_start);
521 final_pat |= (init_pat & bit_range (new_start, old_start - new_start)) << width;
522 final_pat |= init_pat & bit_range (old_start + width, positions - (old_start + width));
523 }
524 else
525 {
526 final_pat = init_pat & bit_range (0, old_start);
527 final_pat |= (init_pat & bit_range (old_start + width, new_start - old_start)) >> width;
528 final_pat |= (init_pat & bit_range (old_start, width)) << (new_start - old_start);
529 final_pat |= init_pat & bit_range (new_start + width, positions - (new_start + width));
530 }
531
532 rt = make_pattern (init_pat, offset);
533 range_tower_move (rt, old_start + offset, new_start + offset,
534 width);
535 check_pattern (rt, final_pat, offset);
536 range_tower_destroy (rt);
537 }
538 }
539
540 /* Tests freeing a range tower through a pool. */
541 static void
542 test_pool (void)
543 {
544 struct pool *pool;
545 struct range_tower *rt;
546
547 /* Destroy the range tower, then the pool.
548 Makes sure that this doesn't cause a double-free. */
549 pool = pool_create ();
550 rt = range_tower_create_pool (pool);
551 range_tower_set1 (rt, 1, 10);
552 range_tower_destroy (rt);
553 pool_destroy (pool);
554
555 /* Just destroy the pool.
556 Makes sure that this doesn't cause a leak. */
557 pool = pool_create ();
558 rt = range_tower_create_pool (pool);
559 range_tower_set1 (rt, 1, 10);
560 pool_destroy (pool);
561 }
562
563 /* Tests range_tower_destroy(NULL). */
564 static void
565 test_destroy_null (void)
566 {
567 range_tower_destroy (NULL);
568 }
569
570 /* Main program. */
571
572 struct test
573 {
574 const char *name;
575 const char *description;
576 void (*function) (void);
577 };
578
579 static const struct test tests[] =
580 {
581 {
582 "set1",
583 "set1",
584 test_set1
585 },
586 {
587 "set0",
588 "set0",
589 test_set0
590 },
591 {
592 "insert0",
593 "insert0",
594 test_insert0
595 },
596 {
597 "insert1",
598 "insert1",
599 test_insert1
600 },
601 {
602 "delete",
603 "delete",
604 test_delete
605 },
606 {
607 "move",
608 "move",
609 test_move
610 },
611 {
612 "pool",
613 "pool",
614 test_pool
615 },
616 {
617 "destroy-null",
618 "destroy null",
619 test_destroy_null
620 },
621 };
622
623 enum { N_TESTS = sizeof tests / sizeof *tests };
624
625 int
626 main (int argc, char *argv[])
627 {
628 int i;
629
630 if (argc != 2)
631 {
632 fprintf (stderr, "exactly one argument required; use --help for help\n");
633 return EXIT_FAILURE;
634 }
635 else if (!strcmp (argv[1], "--help"))
636 {
637 printf ("%s: test range tower library\n"
638 "usage: %s TEST-NAME\n"
639 "where TEST-NAME is one of the following:\n",
640 argv[0], argv[0]);
641 for (i = 0; i < N_TESTS; i++)
642 printf (" %s\n %s\n", tests[i].name, tests[i].description);
643 return 0;
644 }
645 else
646 {
647 for (i = 0; i < N_TESTS; i++)
648 if (!strcmp (argv[1], tests[i].name))
649 {
650 tests[i].function ();
651 return 0;
652 }
653
654 fprintf (stderr, "unknown test %s; use --help for help\n", argv[1]);
655 return EXIT_FAILURE;
656 }
657 }
0 AT_BANNER([range tower library])
1
2 m4_define([CHECK_RANGE_TOWER],
3 [AT_SETUP([range-tower -- $1])
4 AT_CHECK([range-tower-test $1])
5 AT_CLEANUP])
6
7 CHECK_RANGE_TOWER([set1])
8 CHECK_RANGE_TOWER([set0])
9 CHECK_RANGE_TOWER([insert0])
10 CHECK_RANGE_TOWER([insert1])
11 CHECK_RANGE_TOWER([delete])
12 CHECK_RANGE_TOWER([move])
13 CHECK_RANGE_TOWER([pool])
14 CHECK_RANGE_TOWER([destroy-null])
554554 /DEPENDENT= x y
555555 /STATISTICS=COEFF R ANOVA.
556556 ])
557 AT_CHECK([pspp ascii.sps], [1], [dnl
557 AT_CHECK([pspp ascii.sps], [0], [dnl
558558 SET PRINTBACK=ON.
559559
560560 DATA LIST LIST /x * y * a (a23).
576576
577577 REGRESSION
578578 /VARIABLES= a
579
580 ascii.sps:11: warning: REGRESSION: a is not a numeric variable. It will not be
581 included in the variable list.
582
579583 /DEPENDENT= x y
580584 /STATISTICS=COEFF R ANOVA.
581
582 ascii.sps:12: error: REGRESSION: REGRESSION requires numeric variables.
583 ])
585 ])
586
584587 AT_CLEANUP
1818 end input program.
1919
2020 examine x y by a
21 /plot = histogram, npplot
21 /plot = histogram, npplot spreadlevel(1)
2222 .
2323
2424 examine x y by a
117117 AT_CHECK([pspp -O format=csv scree.sps], [0], [ignore])
118118
119119 AT_CLEANUP
120
121
122 AT_SETUP([Histogram])
123 AT_DATA([histogram.sps],[
124 * This test is designed to "torture" the code which
125 generates histograms. It is no-crash test. However
126 the code is rich in assertions, so any problems we
127 hope will be caught there.
128
129
130 input program.
131 loop #i = 1 to 1000.
132 compute pos = rv.normal (56, 3) + rv.uniform (1, 1).
133 compute neg = rv.normal (-86, 2) + rv.uniform (1, 1).
134 compute pn = rv.normal (0, 2) + rv.uniform (1, 2).
135 compute A = rv.uniform (-1, 1).
136 compute A = (A > 0).
137 end case.
138 end loop.
139 end file.
140 end input program.
141
142
143 examine pos neg pn by a
144 /plot = histogram
145 .
146
147 frequencies pos neg pn
148 /format=notable
149 /histogram=normal.
150 ])
151
152
153 AT_CHECK([pspp -O format=csv histogram.sps], [0], [ignore])
154
155 AT_CLEANUP