1 ;;;$Id: w3-speak-table.el,v 1.4 2001/05/25 14:05:05 wmperry Exp $
2 ;;;Authors: Thierry Emery <Thierry.Emery@nmu.alcatel.fr>, T.V. Raman <raman@Adobe.COM>
3 ;;;Description: Speak W3 tables
5 (eval-when-compile (require 'cl))
9 (defsubst w3-table-inside-table-display-p ()
10 "Indicates by looking at `w3-table-structure' whether (point) is inside a W3 table"
11 (loop for table-info in w3-table-structure
12 if (and (>= (point) (car table-info))
13 (<= (point) (cadr table-info)))
16 (defmacro w3-within-cell (cell-info table-info &rest forms)
17 "Enables to recursively enter the current cell using `extract-rectangle'
18 using CELL-INFO and TABLE-INFO and process FORMS inside it (for instance to process subtables)"
19 `(let* ((cell-row (w3-cell-info-row ,cell-info))
20 (cell-col (w3-cell-info-column ,cell-info))
21 (cell-beg (w3-cell-info-start ,cell-info))
22 (cell-end (w3-cell-info-end ,cell-info))
23 (cell-contents (extract-rectangle cell-beg cell-end))
24 (cell-x (count-lines (save-excursion (goto-char cell-beg) (beginning-of-line) (point))
25 (save-excursion (beginning-of-line) (point))))
26 (current-col (current-column))
27 (cell-y (save-excursion (forward-line (- cell-x))
28 (move-to-column current-col)
29 (- (point) cell-beg)))
31 ;; really inside cell ?
34 (<= (point) cell-end))
35 ;; find current subtables structure
36 (loop for subtable in (w3-table-info-subtables ,table-info)
37 if (and (= cell-row (car subtable))
38 (= cell-col (cadr subtable)))
39 do (setq cell-table-structure (cons (cddr subtable) cell-table-structure)))
41 (mapc (lambda (s) (insert s ?\n)) cell-contents)
42 ;; remove end of line padding
43 (when cell-table-structure
44 (goto-char (point-min))
47 (delete-horizontal-space)
51 (goto-char (point-min))
53 (move-to-column cell-y)
54 (setq w3-table-structure (nreverse cell-table-structure))
57 (put 'w3-within-cell 'lisp-indent-function 2)
58 (put 'w3-within-cell 'edebug-form-spec '(sexp sexp &rest form))
60 (defmacro w3-table-compute-relative-movement (&rest forms)
61 "Record a movement done by &rest FORMS (e.g. inside a temporary buffer)
62 and return it as (horizontal-offset . vertical-offset)"
63 `(let ((origin-line-beg (save-excursion (beginning-of-line) (point)))
64 (origin-char-col (current-column)))
66 (cons (- (current-column) origin-char-col)
67 (let* ((new-line-beg (save-excursion (beginning-of-line) (point)))
68 (line-diff (count-lines new-line-beg origin-line-beg)))
69 (if (< new-line-beg origin-line-beg)
72 (put 'w3-table-compute-relative-movement 'lisp-indent-function 0)
73 (put 'w3-table-compute-relative-movement 'edebug-form-spec '(&rest form))
75 (defsubst w3-table-redo-relative-movement (movement)
76 "Redo a movement indicated as (horizontal-offset . vertical-offset)"
78 (let ((to-col (+ (current-column) (car movement)))
79 (vertical (cdr movement)))
80 (forward-line vertical)
81 (move-to-column to-col))))
83 (defmacro w3-table-move-within-cell (at-depth cell-info move-function)
84 "Move within a cell (in a temporary buffer) and reflect the same movement
85 in the containing table in the original buffer"
86 `(if (null ,cell-info)
87 (error "Not inside a W3 cell")
89 (w3-within-cell ,cell-info table-info
91 (w3-table-compute-relative-movement
92 (funcall ,move-function (1- at-depth)))))
93 (w3-table-redo-relative-movement table-movement))))
94 (put 'w3-table-move-within-cell 'lisp-indent-function 2)
95 (put 'w3-table-move-within-cell 'edebug-form-spec '(sexp sexp &rest form))
97 (defmacro w3-table-move-within-subtable (at-depth cell-info move-function)
98 "Move within a subtable (in a temporary buffer) and reflect the same movement
99 in the containing table in the original buffer"
100 `(if (null ,cell-info)
101 (error "Not inside a W3 cell")
102 (let ((subtable-info (w3-cell-info-current-subtable ,cell-info))
104 (if (null subtable-info)
105 (error "Not inside a W3 table")
106 (w3-within-cell ,cell-info table-info
108 (w3-table-compute-relative-movement
109 (funcall ,move-function (1- at-depth) subtable-info))))
110 (w3-table-redo-relative-movement table-movement)))))
112 (put 'w3-table-move-within-subtable 'lisp-indent-function 2)
113 (put 'w3-table-move-within-subtable 'edebug-form-spec '(sexp sexp &rest form))
118 (defun w3-find-table (&optional at-depth)
119 "Search forward for a table, go to its start and return (start . end)"
121 (let* ((table-info (w3-table-info 1 t))
122 (cell-info (and table-info (w3-table-info-current-cell table-info))))
123 (if (and (numberp at-depth) (> at-depth 1))
125 (error "Not inside a W3 table cell")
126 (w3-table-move-within-cell at-depth cell-info
128 (if (or (not w3-table-structure)
129 (> (point) (car (car w3-table-structure))))
130 (error "No other W3 table")
132 (loop for table-info in w3-table-structure
133 until (> (point) (car table-info))
134 do (setq table-found table-info)
135 finally return (progn
136 (goto-char (car table-found))
137 (cons (car table-found) (cdr table-found)))))))))
142 ;;; Return table info if inside a table cell.
143 (defstruct w3-table-info
144 start ; starting point in buffer
145 end ; end point in buffer
146 subtables ; w3-table-structure extract
147 current-cell ; `w3-cell-info' struct
148 rows ; number of rows
149 columns ; number of columns
155 (defun w3-table-info (&optional to-depth noerror)
156 "Give table info as a `w3-table-info' struct, limited to TO-DEPTH if it is a number.
157 TO-DEPTH = 0 means without current-cell info.
158 TO-DEPTH = n > 0 means without nth subtable info in the nth current-cell info.
159 If no table is found and NOERROR is nil, an error is signaled."
160 (let ((origin (point))
161 start end subtables dimensions)
162 (loop for info in w3-table-structure
163 if (and (>= origin (car info))
164 (<= origin (cadr info)))
165 do (setq start (car info)
167 subtables (caddr info)
168 dimensions (cdddr info)))
171 (error "Not inside a W3 table"))
172 (let ((table-info (make-w3-table-info)))
173 (setf (w3-table-info-start table-info)
175 (setf (w3-table-info-end table-info)
177 (setf (w3-table-info-subtables table-info)
179 (setf (w3-table-info-rows table-info)
181 (setf (w3-table-info-columns table-info)
183 (setf (w3-table-info-row-heights table-info)
185 (setf (w3-table-info-column-widths table-info)
187 (setf (w3-table-info-rowspans table-info)
189 (setf (w3-table-info-colspans table-info)
192 (when (or (null to-depth)
193 (and (numberp to-depth) (> to-depth 0)))
194 (setf (w3-table-info-current-cell table-info)
195 (w3-cell-info table-info to-depth)))
201 (defun w3-table-current-row-number (&optional table-info)
202 "Return spanless row number"
203 (let* ((table-info (or table-info (w3-table-info 0)))
204 (start (w3-table-info-start table-info))
205 (line-count (1+ (count-lines (save-excursion (goto-char start) (beginning-of-line) (point))
206 (save-excursion (beginning-of-line) (point)))))
207 (num-rows (w3-table-info-rows table-info))
208 (row-heights (w3-table-info-row-heights table-info))
210 (while (and (< row num-rows)
211 (< (aref row-heights row) line-count))
212 (setq line-count (- line-count (aref row-heights row))
214 (when (< row num-rows)
217 (defun w3-table-current-column-number (&optional table-info)
218 "Return spanless column number"
219 (let* ((table-info (or table-info (w3-table-info 0)))
220 (start (w3-table-info-start table-info))
221 (char-col (current-column))
222 (num-cols (w3-table-info-columns table-info))
223 (col-widths (w3-table-info-column-widths table-info))
225 (while (and (< col num-cols)
226 (< (aref col-widths col) char-col))
227 (setq char-col (- char-col (aref col-widths col) 1)
229 (when (< col num-cols)
232 (defun w3-table-row-column-spans (&optional table-info)
233 "Return spanning cell ((row . rowspan) . (column . colspan))"
234 (let* ((table-info (or table-info (w3-table-info 0)))
235 (start (w3-table-info-start table-info))
236 (line-count (1+ (count-lines (save-excursion (goto-char start) (beginning-of-line) (point))
237 (save-excursion (beginning-of-line) (point)))))
238 (num-rows (w3-table-info-rows table-info))
239 (row-heights (w3-table-info-row-heights table-info))
240 (table-rowspans (w3-table-info-rowspans table-info))
243 (char-col (current-column))
244 (num-cols (w3-table-info-columns table-info))
245 (col-widths (w3-table-info-column-widths table-info))
246 (table-colspans (w3-table-info-colspans table-info))
248 ;; look for spanning cell origin row
249 (while (and (< row num-rows)
251 (setq row (+ row rowspan))
252 (when (< row num-rows)
253 (let ((row-rowspans (aref table-rowspans row))
254 (row-colspans (aref table-colspans row))
255 (row-char-col char-col))
258 ;; look for spanning cell origin column for this candidate spanning cell origin row
259 (while (and (< col num-cols)
261 (setq col (+ col colspan))
262 (when (< col num-cols)
263 (setq colspan (aref row-colspans col))
264 (loop for i from 0 to (1- colspan)
265 do (setq row-char-col (- row-char-col (aref col-widths (+ col i)) 1)))))
266 ;; take into account row-span from this candidate spanning cell origin column
267 (setq rowspan (if (< col num-cols)
268 (aref row-rowspans col)
270 (loop for i from 0 to (1- rowspan)
271 do (setq line-count (- line-count (aref row-heights (+ row i))))))))
274 (and (< row num-rows) (cons (1+ row) rowspan))
275 (and (< col num-cols) (cons (1+ col) colspan)))))
280 ;;; Return cell info if inside a table cell.
281 (defstruct w3-cell-info
282 row ; row number of this cell in its table
283 column ; column number of this cell in its table
286 start ; starting point of cell contents in buffer (for `extract-rectangle')
287 end ; end point of cell contents in buffer (for `extract-rectangle')
288 current-subtable ; `w3-table-info' struct
291 (defun w3-cell-info (&optional table-info to-depth)
292 "If inside a table, tell which cell it is in, its rowspan, colspan,
293 start and end points, and its current subtable as a `w3-cell-info' struct.
294 NB: row and col start from 1
295 beg and end delimit the interior of the cell, so they can be passed on
296 to `extract-rectangle' in order to get cell contents."
297 (let* ((origin (point))
298 (table-info (or table-info (w3-table-info 0)))
299 (table-row-col-spans (w3-table-row-column-spans table-info))
300 (table-row (caar table-row-col-spans))
301 (rowspan (cdar table-row-col-spans))
302 (table-col (cadr table-row-col-spans))
303 (colspan (cddr table-row-col-spans)))
304 (when (and table-row table-col)
305 (let* ((cell-info (make-w3-cell-info))
306 (start (w3-table-info-start table-info))
307 (table-row-heights (w3-table-info-row-heights table-info))
308 (table-col-widths (w3-table-info-column-widths table-info))
309 (table-width (+ (apply '+ (map 'list '1+ table-col-widths)) 2))
310 (table-row-index (1- table-row))
311 (table-col-index (1- table-col))
318 (loop for i from 0 to (1- table-row-index)
319 do (next-line (aref table-row-heights i)))
320 (loop for i from 0 to (1- table-col-index)
321 do (setq cell-beg-offset (+ cell-beg-offset (aref table-col-widths i) 1)))
322 (move-to-column (+ (current-column) cell-beg-offset))
325 (move-to-column (1+ (current-column)))
326 (setq cell-beg (point)))
328 (loop for i from 0 to (1- rowspan)
329 do (next-line (aref table-row-heights (+ table-row-index i))))
330 (loop for i from 0 to (1- colspan)
331 do (setq cell-end-offset
332 (+ cell-end-offset (aref table-col-widths (+ table-col-index i)) 1)))
333 (move-to-column (+ (current-column) cell-end-offset))
335 (setq cell-end (point))
338 (setf (w3-cell-info-row cell-info) table-row)
339 (setf (w3-cell-info-column cell-info) table-col)
340 (setf (w3-cell-info-rowspan cell-info) rowspan)
341 (setf (w3-cell-info-colspan cell-info) colspan)
342 (setf (w3-cell-info-start cell-info) cell-beg)
343 (setf (w3-cell-info-end cell-info) cell-end)
344 ;; if inside cell, current subtable info (recursive call to w3-table-info)
345 (when (and (or (null to-depth)
346 (and (numberp to-depth) (> to-depth 1)))
347 (<= cell-beg (point)) (<= (point) cell-end))
348 (w3-within-cell cell-info table-info
349 (when w3-table-structure
350 (setf (w3-cell-info-current-subtable cell-info)
351 (w3-table-info (and (numberp to-depth) (1- to-depth)) t)))))
355 ;;{{{ extracting table elements
357 (defun w3-table-this-cell-contents (&optional at-depth table-info)
358 "Return formatted contents of this cell as a list if strings.
359 Prefix arg can be used to specify the desired table nesting."
361 (let* ((table-info (or table-info (w3-table-info at-depth)))
362 (cell-info (w3-table-info-current-cell table-info)))
364 (error "Not inside a W3 table cell")
365 (if (and (numberp at-depth) (> at-depth 1))
366 (let ((subtable-info (w3-cell-info-current-subtable cell-info)))
367 (if (null subtable-info)
368 (error "Not inside a W3 table")
369 (w3-within-cell cell-info table-info
370 (w3-table-this-cell-contents (1- at-depth) subtable-info))))
372 (extract-rectangle (w3-cell-info-start cell-info)
373 (w3-cell-info-end cell-info))
376 (defun w3-table-speak-this-cell-info (&optional at-depth)
377 "Speak coordinates of current table cell.
378 Prefix arg can be used to specify the desired table nesting."
381 ((table-info (w3-table-info at-depth))
382 (cell-info (w3-table-info-current-cell table-info)))
383 (message "Row %s Column %s of a %s by %s table %s"
384 (w3-cell-info-row cell-info)
385 (w3-cell-info-column cell-info)
386 (w3-table-info-rows table-info)
387 (w3-table-info-columns table-info)
389 (format " at nesting level %s" at-depth)
392 (defun w3-table-focus-on-this-cell (&optional at-depth)
393 "Focus on current cell --optional argument at-depth
394 specifies nesting level. Focusing on a cell results in its
395 contents being displayed in a separate buffer in W3 mode.
396 This is useful to navigate pages that use a single table
397 cell for a newspaper style column"
399 (setq at-depth (or at-depth 1))
400 (let ((contents (w3-table-this-cell-contents at-depth))
401 (buffer (get-buffer-create
402 (format "Cell-%s" (buffer-name))))
403 (inhibit-read-only t))
409 (goto-char (point-min))
410 (w3-resurrect-hyperlinks)
411 (w3-resurrect-images))
412 (switch-to-buffer buffer)))
415 (defun w3-table-speak-this-cell (&optional at-depth)
416 "Speak contents of current table cell.
417 Prefix arg can be used to specify the desired table nesting."
419 (let ((contents (w3-table-this-cell-contents at-depth)))
420 (dtk-speak contents)))
423 ;;{{{ Table navigation
425 (defun w3-table-move-to-table-start (&optional at-depth table-info)
426 "If inside a table, move to its top left corner.
427 Prefix arg can be used to specify the desired table nesting."
429 (let* ((table-info (or table-info (w3-table-info at-depth)))
430 (cell-info (w3-table-info-current-cell table-info)))
431 (if (and (numberp at-depth) (> at-depth 1))
432 (w3-table-move-within-subtable at-depth cell-info
433 'w3-table-move-to-table-start)
434 (goto-char (w3-table-info-start table-info))
435 (when (and (interactive-p)
436 (featurep 'emacspeak))
437 (emacspeak-auditory-icon 'large-movement)
438 (emacspeak-speak-line)))))
440 (defun w3-table-move-to-table-end (&optional at-depth table-info)
441 "If inside a table, move to its bottom right corner.
442 Prefix arg can be used to specify the desired table nesting."
444 (let* ((table-info (or table-info (w3-table-info at-depth)))
445 (cell-info (w3-table-info-current-cell table-info)))
446 (if (and (numberp at-depth) (> at-depth 1))
447 (w3-table-move-within-subtable at-depth cell-info
448 'w3-table-move-to-table-end)
449 (goto-char (1- (w3-table-info-end table-info)))
450 (when (and (interactive-p)
451 (featurep 'emacspeak))
452 (emacspeak-auditory-icon 'large-movement)
453 (emacspeak-speak-line)))))
455 (defun w3-table-move-to-beginning-of-previous-table-row (&optional at-depth table-info)
456 "Move to previous table row. Prefix arg can be used to specify the desired table nesting."
458 (let* ((table-info (or table-info (w3-table-info at-depth)))
459 (cell-info (w3-table-info-current-cell table-info)))
460 (if (and (numberp at-depth) (> at-depth 1))
461 (w3-table-move-within-subtable at-depth cell-info
462 'w3-table-move-to-beginning-of-previous-table-row)
463 (when (= 1 (w3-cell-info-row cell-info))
465 (goto-char (w3-cell-info-start cell-info))
469 (when (featurep 'emacspeak)
470 (dtk-speak (w3-table-this-cell-contents at-depth))
471 (emacspeak-auditory-icon 'select-object)))))
473 (defun w3-table-move-to-beginning-of-next-table-row (&optional at-depth table-info)
474 "Move to next table row. Prefix arg can be used to specify the desired table nesting."
476 (let* ((table-info (or table-info (w3-table-info at-depth)))
477 (cell-info (w3-table-info-current-cell table-info)))
478 (if (and (numberp at-depth) (> at-depth 1))
479 (w3-table-move-within-subtable at-depth cell-info
480 'w3-table-move-to-beginning-of-next-table-row)
481 (when (= (w3-table-info-rows table-info) (w3-cell-info-row cell-info))
483 (goto-char (w3-cell-info-end cell-info))
487 (when (featurep 'emacspeak)
488 (dtk-speak (w3-table-this-cell-contents at-depth))
489 (emacspeak-auditory-icon 'select-object)))))
491 (defun w3-table-move-to-previous-table-row (&optional at-depth table-info)
492 "Move to previous table row. Prefix arg can be used to specify the desired table nesting."
494 (let* ((table-info (or table-info (w3-table-info at-depth)))
495 (cell-info (w3-table-info-current-cell table-info)))
496 (if (and (numberp at-depth) (> at-depth 1))
497 (w3-table-move-within-subtable at-depth cell-info
498 'w3-table-move-to-previous-table-row)
499 (let ((char-col (current-column)))
500 (when (= 1 (w3-cell-info-row cell-info))
502 (goto-char (w3-cell-info-start cell-info))
504 (move-to-column char-col)
505 (setq cell-info (w3-cell-info table-info))
506 (goto-char (w3-cell-info-start cell-info))
507 (when (featurep 'emacspeak)
508 (dtk-speak (w3-table-this-cell-contents at-depth))
509 (emacspeak-auditory-icon 'select-object))))))
511 (defun w3-table-move-to-next-table-row (&optional at-depth table-info)
512 "Move to next table row. Prefix arg can be used to specify the desired table nesting."
514 (let* ((table-info (or table-info (w3-table-info at-depth)))
515 (cell-info (w3-table-info-current-cell table-info)))
516 (if (and (numberp at-depth) (> at-depth 1))
517 (w3-table-move-within-subtable at-depth cell-info
518 'w3-table-move-to-next-table-row)
519 (let ((char-col (current-column)))
520 (when (= (w3-table-info-rows table-info) (w3-cell-info-row cell-info))
522 (goto-char (w3-cell-info-end cell-info))
524 (move-to-column char-col)
525 (setq cell-info (w3-cell-info table-info))
526 (goto-char (w3-cell-info-start cell-info))
527 (when (featurep 'emacspeak)
528 (dtk-speak (w3-table-this-cell-contents at-depth))
529 (emacspeak-auditory-icon 'select-object))))))
531 (defun w3-table-move-to-previous-table-column (&optional at-depth table-info)
532 "Moves to the start of the previous table column.
533 Prefix arg can be used to specify the desired table nesting."
535 (let* ((table-info (or table-info (w3-table-info at-depth)))
536 (cell-info (w3-table-info-current-cell table-info)))
537 (if (and (numberp at-depth) (> at-depth 1))
538 (w3-table-move-within-subtable at-depth cell-info
539 'w3-table-move-to-previous-table-column)
540 (let* ((column (w3-table-current-column-number table-info))
541 (column-index (if (numberp column)
543 (w3-table-info-columns table-info)))
545 (widths (w3-table-info-column-widths table-info))
547 (when (= 0 column-index)
548 (error "First column"))
549 (loop for w across widths
550 while (< c column-index)
553 (incf position (1+ w)))
555 (move-to-column (1+ position))
556 (when (featurep 'emacspeak)
557 (dtk-speak (w3-table-this-cell-contents at-depth))
558 (emacspeak-auditory-icon 'select-object))))))
560 (defun w3-table-move-to-next-table-column (&optional at-depth table-info)
561 "Move to next column. Prefix arg can be used to specify the desired table nesting."
563 (let* ((table-info (or table-info (w3-table-info at-depth)))
564 (cell-info (w3-table-info-current-cell table-info)))
565 (if (and (numberp at-depth) (> at-depth 1))
566 (w3-table-move-within-subtable at-depth cell-info
567 'w3-table-move-to-next-table-column)
568 (let* ((current (current-column))
569 (column (w3-table-current-column-number table-info))
570 (column-index (if (numberp column)
572 (w3-table-info-columns table-info)))
574 (widths (w3-table-info-column-widths table-info)))
575 (when (= (1- (w3-table-info-columns table-info)) column-index)
576 (error "Last column"))
577 (loop for w across widths
578 until (> check current)
580 (setq check (+ check w 1 )))
582 (move-to-column (1+ check))
583 (when (featurep 'emacspeak)
584 (dtk-speak (w3-table-this-cell-contents at-depth))
585 (emacspeak-auditory-icon 'select-object))))))
587 (defun w3-table-move-to-top-of-table-column (&optional at-depth table-info)
588 "Move to top of current column. Prefix arg can be used to specify the desired table nesting."
590 (let* ((table-info (or table-info (w3-table-info at-depth)))
591 (cell-info (w3-table-info-current-cell table-info)))
592 (if (and (numberp at-depth) (> at-depth 1))
593 (w3-table-move-within-subtable at-depth cell-info
594 'w3-table-move-to-top-of-table-column)
595 (let ((table-start nil)
597 (column (w3-table-current-column-number table-info))
600 (widths (w3-table-info-column-widths table-info)))
603 (w3-table-move-to-table-start table-info)
604 (setq table-start (point)))
605 (goto-char table-start)
607 (loop for c from 1 to (1- column)
609 (incf motion (1+ (aref widths (1- c)))))
610 (move-to-column (1+ motion))
611 (when (featurep 'emacspeak)
612 (emacspeak-auditory-icon 'large-movement)
613 (dtk-speak (w3-table-this-cell-contents at-depth)))))))
616 ;;{{{ Column browsing
619 (defun w3-table-speak-current-table-column (&optional at-depth table-info)
620 "Speak current table column. Prefix arg can be used to specify the desired table nesting."
622 (let* ((table-info (or table-info (w3-table-info at-depth)))
623 (cell-info (w3-table-info-current-cell table-info)))
624 (if (and (numberp at-depth) (> at-depth 1))
626 (error "Not inside a W3 cell")
627 (let ((subtable-info (w3-cell-info-current-subtable cell-info)))
628 (if (null subtable-info)
629 (error "Not inside a W3 table")
630 (w3-within-cell cell-info table-info
631 'w3-table-speak-current-table-column))))
635 (column (w3-table-current-column-number table-info))
638 (widths (w3-table-info-column-widths table-info)))
641 (w3-table-move-to-table-start table-info)
642 (setq table-start (point))
643 (w3-table-move-to-table-end table-info)
644 (setq table-end (point))
645 (narrow-to-region table-start table-end)
646 (goto-char table-start)
647 (loop for c from 1 to (1- column)
649 (forward-char (1+ (aref widths (1- c)))))
650 (setq top-left (point))
651 (goto-char table-end)
653 (loop for c from 1 to column
655 (forward-char (1+ (aref widths (1- c)))))
656 (setq bottom-right (point))))
657 (emacspeak-speak-rectangle top-left bottom-right)))))
660 ;;{{{ bind them to useful keys
664 (defun w3-table-setup-keys ()
665 "Setup emacspeak table browsing keys in w3 mode"
666 (declare (special emacspeak-prefix w3-mode-map))
667 (let ((key (make-vector 1 (aref emacspeak-prefix 0))))
668 (define-key w3-mode-map ","
669 'w3-table-focus-on-this-cell)
670 (define-key w3-mode-map "." 'w3-table-speak-this-cell)
671 (define-key w3-mode-map
672 (concat emacspeak-prefix "=")
673 'w3-table-move-to-top-of-table-column)
674 (define-key w3-mode-map "=" 'w3-table-speak-this-cell-info)
675 (define-key w3-mode-map
676 (concat emacspeak-prefix ".")
677 'w3-table-speak-this-cell)
678 (define-key w3-mode-map
679 (concat emacspeak-prefix "<")
680 'w3-table-move-to-table-start)
681 (define-key w3-mode-map
682 (concat emacspeak-prefix ">")
683 'w3-table-move-to-table-end)
684 (define-key w3-mode-map
685 (concatenate 'vector key "-")
686 'w3-table-move-to-beginning-of-previous-table-row)
687 (define-key w3-mode-map
688 (concatenate 'vector key "+")
689 'w3-table-move-to-beginning-of-next-table-row)
690 (define-key w3-mode-map
691 (concatenate 'vector key '[up])
692 'w3-table-move-to-previous-table-row)
693 (define-key w3-mode-map
695 'w3-table-speak-current-table-column)
696 (define-key w3-mode-map
697 (concatenate 'vector key '[down])
698 'w3-table-move-to-next-table-row)
699 (define-key w3-mode-map
700 (concatenate 'vector key '[left])
701 'w3-table-move-to-previous-table-column)
702 (define-key w3-mode-map
703 (concatenate 'vector key '[right])
704 'w3-table-move-to-next-table-column)
707 (add-hook 'w3-mode-hook 'w3-table-setup-keys)
710 (provide 'w3-structure)