;;;;; -*-coding: x-ctext;-*- ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: header.el,v 44.7 2003/08/24 18:41:36 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: header.el ;;;; ;;;; Code that needs to go before everything else ;;;; ;;; Check the version of Emacs when compiling ;;; ;;; If the version of Emacs is too old, signal an error. ;;; We require Gnu Emacs 19.34 or 20.3 or XEmacs 21.1. (eval-and-compile (if (or (not (boundp 'emacs-major-version)) (not (boundp 'emacs-minor-version)) (and (string-match "XEmacs" (emacs-version)) (or (< emacs-major-version 20) (and (= emacs-major-version 20) (< emacs-minor-version 4)) (and (= emacs-major-version 21) (< emacs-minor-version 1)))) (and (not (string-match "XEmacs" (emacs-version))) (or (< emacs-major-version 19) (and (= emacs-major-version 19) (< emacs-minor-version 34)) (and (= emacs-major-version 20) (< emacs-minor-version 2))))) (error "Emacs 19.34, XEmacs 21.1 or later, or Emacs 20.2 or later is required"))) (cond ((or (not (boundp 'emacs-major-version)) (not (boundp 'emacs-minor-version)) (< emacs-major-version (eval-when-compile emacs-major-version))) (error "LysKOM was compiled for a newer version of Emacs")) ((and (eq (eval-when-compile emacs-major-version) 19) (> emacs-major-version 19)) (error "A LysKOM client compiled for Emacs 19 will not run in newer versions of Emacs."))) ;;; Check some basic misfeatures that are still all too common (eval-and-compile (defmacro lyskom-detect-read-kbd-macro-bug () `(and (stringp (read-kbd-macro "")) (string-equal (read-kbd-macro "") ""))) (let ((libraries-to-try '("edmacro"))) (while libraries-to-try (if (lyskom-detect-read-kbd-macro-bug) (progn (condition-case nil (load-library (car libraries-to-try)) (error nil)) (setq libraries-to-try (cdr libraries-to-try))) (setq libraries-to-try nil))) (if (lyskom-detect-read-kbd-macro-bug) (let ((elc-location (locate-library "macedit.elc")) (el-location (locate-library "macedit.el")) (elz-location (locate-library "macedit.el.gz"))) (cond ((or el-location elc-location) (message "\ You probably have a file named macedit.elc in Emacs' load path. This file is included in some versions of the calc package and is no longer required as the functions that it provides are also provided by more modern packages. You will need to remove macedit.el and all references to it from Emacs. These are the files you need to remove: %s To fully remove macedit you will also have to remove any autoloads that refer to it. These may be found in a file named auto-autoloads.elc (or auto-autoloads.el), located in the same directory as macedit or in a file named loaddefs.el, located elsewhere. With Gnu Emacs you may be successful in removing references by using the command update-autoloads-from-directories. " (mapconcat (lambda (x) (or x "")) (list elc-location el-location elz-location) "\n")) (error "Unable to run or compile due to obsolete macedit package.")) (t (message "\ Your definition of read-kbd-macro appears to be obsolete. This is usually caused by having a package called macedit in Emacs load path, but I am unable to find this package. LysKOM cannot run with your version of read-kbd-macro. ") (error "Unable to run or compile due to obsolete definition of read-kbd-macro."))))))) (eval-and-compile (defvar lyskom-debug-compile (eval-when-compile (getenv "LYSKOM_DEBUG_COMPILE")))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: defvar.el,v 44.19 2004/07/12 18:11:16 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: defvar.el ;;;; Authos: David Byers ;;;; ;;;; This file contains definitions used to define variables ;;;; (defvar lyskom-clientversion-long "$Id: defvar.el,v 44.19 2004/07/12 18:11:16 byers Exp $\n" "Version for every file in the client.") (provide 'lyskom) ;; Just to get rid of a compiler warning (defvar kom-dont-read-saved-variables) (defvar lyskom-local-variables nil "List of variables to make local in a LysKOM buffer") (defvar lyskom-local-hooks nil "List of hooks to make local in a LysKOM buffer.") (defvar lyskom-protected-variables nil "List of variables that are protected from kill-buffer") (defvar lyskom-inherited-variables nil "List of variables inherited from the LysKOM buffer") (defvar lyskom-elisp-variables nil "Tells the client what flags and hooks that are to be saved in the server. These are the flags that are saved in the elisp-client part of the server.") (defvar lyskom-transition-variables nil "Tells the client what variables are not to be saved in the server, but are to be read from the server. This is for transitioning.") (defvar lyskom-minibuffer-variables nil "These are variables that should be set in the minibuffer by lyskom-with-lyskom-minibuffer.") (defvar lyskom-minibuffer-values nil "Dynamic binding of values that minibuffer variables are to take on") (defvar lyskom-global-variables nil "List of flags that are to be saved as booleans in the common block. Don't change these. They are defined by the protocol.") (defmacro lyskom-save-variables (var-list &rest forms) "Save the values and property list of symbols in VAR-LIST and execute FORMS The symbol value, property list and buffer-local property of all variables is saved before executing FORMS and restored when FORMS have finished." (let ((sym1 (make-symbol "lyskom-saved-variables")) (sym2 (make-symbol "lyskom-saved-symbols")) (sym3 (make-symbol "lyskom-saved-local")) (sym4 (make-symbol "lyskom-saved-plist"))) (` (let* (((, sym2) (quote (, var-list))) ((, sym1) (mapcar 'symbol-value (, sym2))) ((, sym4) (mapcar 'symbol-plist (, sym2))) ((, sym3) (mapcar (function (lambda (v) (local-variable-p v (current-buffer)))) (, sym2)))) (unwind-protect (progn (,@ forms)) (while (, sym1) (if (car (, sym3)) (make-local-variable (car (, sym2)))) (set (car (, sym2)) (car (, sym1))) (setplist (car (, sym2)) (car (, sym4))) (setq (, sym1) (cdr (, sym1)) (, sym2) (cdr (, sym2)) (, sym3) (cdr (, sym3)) (, sym4) (cdr (, sym4))))))))) (put 'lyskom-save-variables 'edebug-form-spec '(sexp body)) (defmacro lyskom-with-lyskom-minibuffer (&rest forms) "Run FORMS after ensuring that LysKOM minibuffer variables will be set." (` (let* ((lyskom-minibuffer-values (mapcar 'symbol-value lyskom-minibuffer-variables))) (unwind-protect (progn (add-hook 'minibuffer-setup-hook 'lyskom-setup-minibuffer-variables) (,@ forms)) (remove-hook 'minibuffer-setup-hook 'lyskom-setup-minibuffer-variables))))) (put 'lyskom-with-lyskom-minibuffer 'edebug-form-spec '(body)) (defun lyskom-setup-minibuffer-variables () (let ((syms lyskom-minibuffer-variables) (vals lyskom-minibuffer-values)) (while syms (make-local-variable (car syms)) (set (car syms) (car vals)) (setq syms (cdr syms) vals (cdr vals))))) (defmacro def-kom-var (name value &rest args) "Define a variable with name NAME and initial value VALUE. Remaining args, ARGS may be A string Used as the documentation string for the variable A symbol A predefined property of the variable A list A widget specification for the variable Predefined (and tested) properties are the following server Save the variable in the elisp block. Implies local. local Make the variable buffer-local. inherited The variable is inherited from parent buffer. Implies protected protected The variable is marked as permanent local. Implies local. minibuffer Inherit the variable as a local variable in the minibuffer. server-hook A hook stored in the server. local-hook A hook variable that is made local in LysKOM buffers. language-force A language-variable whose value is to be forced." (let ((inherited nil) (protected nil) (elisp-block nil) (transition-block nil) (buffer-local nil) (widget-spec nil) (doc-string nil) (minibuffer nil) (local-hook-doc nil) (local-var-doc nil) (server-doc nil) (language-force nil) (arglist args)) ; (message "%S" name) (while arglist (cond ((stringp (car arglist)) (setq doc-string (car arglist))) ((consp (car arglist)) (setq widget-spec (` ((setq lyskom-custom-variables (cons (quote (, (list name (car arglist)))) lyskom-custom-variables)))))) ((symbolp (car arglist)) (cond ((eq (car arglist) 'server) (setq local-var-doc t server-doc t) (setq elisp-block `((add-to-list 'lyskom-elisp-variables ', name) (add-to-list 'lyskom-local-variables ', name)))) ((eq (car arglist) 'common) (setq local-var-doc t server-doc t) (let ((common-name (car (cdr arglist))) (type (car (cdr (cdr arglist))))) (setq arglist (cdr (cdr arglist))) (setq elisp-block `((add-to-list 'lyskom-local-variables ',name) (add-to-list 'lyskom-global-variables (vector ',common-name ',name ',type)))))) ((eq (car arglist) 'transition) (let ((converter (car (cdr arglist)))) (setq arglist (cdr arglist)) (setq local-var-doc t server-doc t) (setq transition-block `((add-to-list 'lyskom-transition-variables '(,name . ,converter)) (add-to-list 'lyskom-local-variables ',name))))) ((eq (car arglist) 'server-hook) (setq local-hook-doc t server-doc t) (setq elisp-block (` ((add-to-list 'lyskom-elisp-variables (quote (, name))) (add-to-list 'lyskom-local-hooks (quote (, name))))))) ((eq (car arglist) 'protected) (setq local-var-doc t) (setq protected (` ((put (quote (, name)) 'permanent-local t) (add-to-list 'lyskom-protected-variables (quote (, name))) (add-to-list 'lyskom-local-variables (quote (, name))))))) ((eq (car arglist) 'inherited) (setq local-var-doc t) (setq inherited (` ((add-to-list 'lyskom-inherited-variables (quote (, name))) (put (quote (, name)) 'permanent-local t) (add-to-list 'lyskom-protected-variables (quote (, name))) (add-to-list 'lyskom-local-variables (quote (, name))))))) ((eq (car arglist) 'local) (setq local-var-doc t) (setq buffer-local (` ((add-to-list 'lyskom-local-variables (quote (, name))))))) ((eq (car arglist) 'local-hook) (setq local-hook-doc t) (setq buffer-local (` ((add-to-list 'lyskom-local-hooks (quote (, name))))))) ((eq (car arglist) 'minibuffer) (setq minibuffer (` ((add-to-list 'lyskom-minibuffer-variables (quote (, name))))))) ((eq (car arglist) 'language-force) (setq language-force `((put ',name 'lyskom-language-force t)))) (t (error "LysKOM: Unknown variable property: %S" (car arglist))))) (t (error "LysKOM: Strange variable argument type: %S" (car arglist)))) (setq arglist (cdr arglist))) (if (null doc-string) (setq doc-string "This variable is not documented.")) (if doc-string (if (if (or local-var-doc local-hook-doc) (setq doc-string (concat doc-string "\n"))) (if local-var-doc (setq doc-string (concat doc-string "\nThis variable is buffer-local."))) (if local-hook-doc (setq doc-string (concat doc-string "\nThis variable is a buffer-local hook."))) (setq doc-string (concat doc-string "\n\n\ Setting this variable in .emacs may not yield the results you expect since that will affect all LysKOM sessions.")))) (if (and doc-string server-doc) (setq doc-string (concat doc-string " This variable is normally stored on a per-session basis in the LysKOM server, but can be set in your .emacs simply by setting it using setq or defvar."))) (` (progn (dont-compile (if (and (boundp (quote (, name))) (or (not (boundp lyskom-is-loaded)) (not lyskom-is-loaded)) (listp kom-dont-read-saved-variables)) (add-to-list 'kom-dont-read-saved-variables (quote (, name))))) (defvar (, name) (, value) (, doc-string)) (,@ (apply 'append (list inherited protected elisp-block transition-block buffer-local minibuffer widget-spec language-force ))))))) (put 'def-kom-var 'edebug-form-spec '(&define name form &rest sexp)) (eval-and-compile (provide 'lyskom-defvar)) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: feature.el,v 1.8 2003/08/16 16:58:45 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: feature.el ;;;; ;;;; Functions for determining if we have a particular feature or not ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: feature.el,v 1.8 2003/08/16 16:58:45 byers Exp $\n")) (def-kom-var lyskom-feature-defaults nil "Alist with default values of all feature variables") (eval-and-compile (defun lyskom-feature-variable (name) (intern (format "lyskom-%s-feature-flag" name)))) (defmacro lyskom-define-feature (name default) "Define a feature variable NAME with default value DEFAULT" `(progn (setq lyskom-feature-defaults (cons (cons ',name ,default) lyskom-feature-defaults)) (def-kom-var ,(lyskom-feature-variable name) ,default "LysKOM feature flag variable." inherited minibuffer local))) (defmacro lyskom-set-feature (name value) "Set the value of feature NAME to VALUE" `(setq ,(lyskom-feature-variable name) ,value)) (defmacro lyskom-have-feature (name) "Return non-nil if feature NAME is non-nil" (lyskom-feature-variable name)) (defmacro lyskom-feature-value (name) "Return the value of feature NAME" (lyskom-feature-variable name)) (defun lyskom-clear-features () "Set the feature variables to their defaults" (mapcar (lambda (feature) (set (lyskom-feature-variable (car feature)) (cdr feature))) lyskom-feature-defaults)) ;;UNUSED: lyskom-list-features (defun lyskom-list-features () "List all feature values. mapcar ROCKS!" (mapcar 'lyskom-insert-before-prompt (mapcar (lambda (x) (apply 'format "%S: %S\n" x)) (lyskom-mapcar2 'list (mapcar 'car lyskom-feature-defaults) (mapcar 'symbol-value (mapcar 'lyskom-feature-variable (mapcar 'car lyskom-feature-defaults))))))) ;;; ====================================================================== ;;; ====================================================================== ;;; Utility functions (defmacro lyskom-have-call (call-no) "Non-nil if call CALL-NO is supported by the server" `(<= ,call-no (lyskom-feature-value highest-call))) ;;; ====================================================================== ;;; ====================================================================== ;;; The features (lyskom-define-feature bcc-misc nil) (lyskom-define-feature read-ranges nil) (lyskom-define-feature aux-items nil) (lyskom-define-feature highest-call 0) (lyskom-define-feature local-to-global nil) (lyskom-define-feature dynamic-session-info nil) (lyskom-define-feature idle-time nil) (lyskom-define-feature long-conf-types nil) (provide 'lyskom-feature) ;;;;; -*-coding: raw-text;mode: emacs-lisp;-*- ;;;;; $Id: vars.el.in,v 44.313 2005/01/12 11:42:14 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: vars.el ;;;; ;;;; This file contains almost all the variables used in lyskom. ;;;; ;;;; Note: put "**" at the front of docstrings that are ready ;;;; for use in DocBook autogeneration. ;;;; ;;;; Rules for documentation that can be translated to DocBook ;;;; is in interndoc/vardoc (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: vars.el.in,v 44.313 2005/01/12 11:42:14 _cvs_pont_lyskomelisp Exp $\n")) (defvar lyskom-dummy-variable-to-fool-the-byte-compiler) (defvar lyskom-mule-compiled (eval-when-compile (and (fboundp 'multibyte-string-p) (multibyte-string-p "ÅÄÖ"))) "Non-nil if the client was compiled with multibyte characters enabled") (provide 'lyskom) (require 'lyskom-defvar "defvar") (defconst lyskom-global-variable-types '((boolean (read . lyskom-flag-read-boolean) (write . lyskom-flag-write-boolean)) (integer (read . lyskom-flag-read-integer) (write . lyskom-flag-write-integer)) (symbol-list (read . lyskom-flag-read-symbol-list) (write . lyskom-flag-write-symbol-list)) (t (read . lyskom-flag-read-from-string) (write . prin1-to-string)))) (defun lyskom-protect-variable (sym) "Protect SYM from being killed when deleting local variables." (put sym 'permanent-local t) (lyskom-local-variable sym) (add-to-list 'lyskom-protected-variables sym)) (defun lyskom-local-variable (sym) "Define SYM as a buffer-local variable" (add-to-list 'lyskom-local-variables sym)) (defun lyskom-inherited-variable (sym) "Define SYM as a variable that is inherited when creating new buffers. Inheritance only works with the LysKOM buffer handling functions." (add-to-list 'lyskom-inherited-variable sym) (lyskom-protect-variable sym)) (defun lyskom-setup-local-variables () "Set up all globally defined local variables in the current buffer." (mapcar 'make-local-variable lyskom-local-variables) (mapcar 'lyskom-make-local-hook lyskom-local-hooks)) (defvar lyskom-is-loaded nil "Non-nil when lyskom has been loaded.") (defvar lyskom-have-one-login nil "Non-nil after the first login") (def-kom-var kom-dont-read-saved-variables '(kom-dont-read-saved-variables lyskom-login-hook) "**Determines which LysKOM variables to not store in the server. For the most part you do not have to modify this variable. Any variables set before LysKOM is loaded will not be read from the server. This variable should `nil', `t' or a list of symbols. The value `nil' means read all variables from the server. The value `t' means read no variables from the server. When the value is a list of symbols, those variables will not be read from the server. Any other values are reserved for future use.") (defmacro lyskom-maybe-setq (var value) "This is a wrapper around setq that does nothing if the variable is in kom-dont-read-saved-variables." `(cond ((eq kom-dont-read-saved-variables t) nil) ((memq ,var kom-dont-read-saved-variables) nil) (t (set ,var ,value)))) (defmacro lyskom-maybe-setq-default (var value) "This is a wrapper around setq-default that does nothing if the variable is in kom-dont-read-saved-variables." `(cond ((eq kom-dont-read-saved-variables t) nil) ((memq ,var kom-dont-read-saved-variables) nil) (t (set-default ',var ,value)))) ;;;; ================================================================ ;;;; Variables and constants. ;;; User flags (def-kom-var kom-auto-confirm-new-conferences nil "**Determines behavior of `kom-list-new-conferences' and `kom-list-new-persons'. When this variable is set to `t', `kom-list-new-conferences' and `kom-list-new-persons' will automatically mark all listed conferences and persons as known. When set to `nil', these commands will ask for confirmation before marking the listed conferences and persons as known. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-dont-complain-about-missing-presentation nil "**Controls whether the client complains when you don't have a presentation. When set to non-nil, the client will never complain. This variable should not be documented. Anybody asocial enough to want this feature ought to have to work to find it." server) (def-kom-var kom-show-sync-messages nil "**Controls display of database saving message. When this variable is set to `t', the client will show a message in the echo area when the LysKOM server signals that it is saving the database. When set to `nil', no message is shown (the mode line is changed regardless of the setting of this variable). Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-text-links '((t ("\\" "http://bugzilla.lysator.liu.se/show_bug.cgi?id=\\1" 0 t))) "**Defines patterns for automatic links in the text. This variable defines patterns to look for in text and convert to links to URLs. The value of this variable must be an alist, where the key (car) is a conference number and the value (cdr) is a list of link specifications for that conference. The special value `t' for the key indicates a list of patterns to apply in all conferences. Key values other than positive integers and `t' are reserved for future use. Each link specification is in turn a list \(`PATTERN' `REPLACEMENT' `HIGHLIGHT' `IGNORE-CASE'), where `PATTERN' is a regular expression to look for in the text, `REPLACEMENT' is used to generate a URL from the text matching `PATTERN', `HIGHLIGHT' is the pattern group to highlight as a URL and `IGNORE-CASE' specifies whether matching is case-sensitive or not. Each text is examined for each `PATTERN'. If a match is found, a URL is created from `REPLACEMENT'. All characters except backslash are copied verbatim. The backslash character starts one of the following sequences: Sequence Meaning ----------------------------------------------------------------- `\\&' Substitute the matched text `\\N' Substitute match for text matching the Nth (...) group in `PATTERN' `\\\\' Insert one backslash. ----------------------------------------------------------------- The `HIGHLIGHT' parameter specifies which (...) group in `PATTERN' to highlight as an URL. Use 0 to highlight the entire match. Finally, if `IGNORE-CASE' is `t', then ignore character case while looking for `PATTERN'. Values other than `t' and `nil' are reserved for future use. When a text has more than one recipient, links will be generated for all recipients. The order in which the recipients are examined and the priority among links that match the same text is undefined." server) (def-kom-var lyskom-default-conference-strategy '((kom-start-anew (what-is-your-name (default . (lyskom-default-conference-empty)))) (kom-delete-conf (what-conf-to-delete (default . (lyskom-default-conference-empty)))) (kom-sub-self (leave-what-conf (filter . (lyskom-default-conference-not-self)))) (kom-change-priority (what-to-change-pres-you (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-change-presentation (what-to-change-pres-you (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-change-conf-motd (who-to-put-motd-for (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-set-presentation (what-to-set-pres-you (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-set-motd-text (what-to-set-motd-you (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-remove-presentation (who-to-remove-pres-for (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-unset-conf-motd (who-to-remove-motd-for (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-go-to-conf (go-to-conf-p (default . (lyskom-default-conference-at-point lyskom-default-conference-self)) (filter . (lyskom-default-conference-not-current)))) (kom-list-created-conferences (list-confs-created-by (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-change-name (name-to-be-changed (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-change-parenthesis (name-to-be-changed (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-change-password (whos-passwd (default . (lyskom-default-conference-at-point lyskom-default-conference-self)))) (kom-redirect-comments (redirect-for-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-self))) (redirect-to-which-conf)) (kom-filter-author (filter-author (default . (lyskom-default-conference-at-point lyskom-default-conference-last-author)) (filter . (lyskom-default-conference-not-self))) (filter-in-conf (filter . (lyskom-default-conference-not-self)))) (kom-review-by-to (review-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (review-to-conf)) (kom-review-first (review-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (review-to-conf)) (kom-review-all (review-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (review-to-conf)) (kom-unread-by-to (unread-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (unread-to-conf)) (kom-unread-first (unread-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (unread-to-conf)) (kom-unread-all (unread-by-whom (default . (lyskom-default-conference-at-point lyskom-default-conference-empty))) (unread-to-conf)) (kom-set-permitted-submitters (conf-to-set-permitted-submitters-q) (new-permitted-submitters-q (default . (lyskom-default-conference-empty)))) (lyskom (what-is-your-name (default . (lyskom-default-conference-empty)))) (kom-add-recipient (who-to-add-q (default . ((lyskom-default-conference-saved last-added-rcpt))) (save last-added-rcpt))) (kom-add-copy (who-to-add-copy-q (default . ((lyskom-default-conference-saved last-added-cc))) (save last-added-cc))) (kom-add-bcc (who-to-add-bcc-q (default . ((lyskom-default-conference-saved last-added-bcc))) (save last-added-bcc))) (kom-sub-recipient (who-to-sub-q (default . (lyskom-default-conference-at-point (lyskom-default-conference-saved last-sub-recipient) lyskom-default-conference-current lyskom-default-conference-restriction)) (save last-sub-recipient))) (kom-move-text (who-to-move-from-q (default . (lyskom-default-conference-at-point (lyskom-default-conference-saved last-sub-recipient) lyskom-default-conference-current lyskom-default-conference-restriction)) (save last-sub-recipient)) (who-to-move-to-q (default . ((lyskom-default-conference-saved last-added-rcpt) lyskom-default-conference-current)) (save last-added-rcpt))) (kom-move-text-tree (who-to-move-from-q (default . (lyskom-default-conference-at-point (lyskom-default-conference-saved last-sub-recipient) lyskom-default-conference-current lyskom-default-conference-restriction)) (save last-sub-recipient)) (who-to-move-to-or-sub-q (default . ((lyskom-default-conference-saved last-added-rcpt) lyskom-default-conference-current)) (save last-added-rcpt)) (who-to-move-to-q (default . ((lyskom-default-conference-saved last-added-rcpt) lyskom-default-conference-current)) (save last-added-rcpt)) (who-to-add-q (default . ((lyskom-default-conference-saved last-added-rcpt) lyskom-default-conference-current)) (save last-added-rcpt))) (kom-send-message (who-to-send-message-to (default . (lyskom-default-conference-for-send-message)))) (kom-send-alarm (who-to-send-message-to (default . (lyskom-default-conference-for-send-message)))) (kom-is-person-member-of-conference (pers-to-check-mship-for) (conf-to-check-mship-of)) ;; Defaults and commands that use the defaults (kom-remote-autoreply (remote-control-who)) (kom-remote-set-message (remote-control-who)) (kom-remote-list-messages (remote-control-who)) (kom-remote-erase-messages (remote-control-who)) (kom-remote-quit (remote-control-who)) (kom-review-presentation (presentation-for-whom)) (kom-unread-presentation (unread-presentation-for-whom)) (kom-add-member (who-to-add) (where-to-add)) (kom-add-self (where-to-add-self)) (kom-change-priority (change-priority-for-q)) (kom-sub-member (who-to-exclude) (where-from-exclude)) (kom-write-text (who-send-text-to)) (kom-send-letter (who-letter-to)) (kom-force-logoout (who-to-throw-out)) (kom-change-supervisor (what-to-change-supervisor-for) (new-supervisor)) (kom-who-is-on-in-conference (who-is-on-in-what-conference)) (kom-who-is-present-in-conference (who-is-present-in-what-conference)) (kom-add-cross-reference (which-conf-to-xref) (which-pers-to-xref)) (kom-edit-add-cross-reference (which-conf-to-xref) (which-pers-to-xref)) (kom-edit-insert-link (which-conf-to-link) (which-pers-to-link)) (kom-status-conf (conf-for-status)) (kom-status-session (session-for-status)) (kom-force-logout (who-to-throw-out)) (kom-status-person (pers-for-status)) (kom-set-garb-nice (conf-to-set-garb-nice-q)) (kom-set-super-conf (conf-to-set-super-conf-q) (new-super-conf-q)) (kom-set-personal-label (label-what-pers) (label-what-conf)) (kom-will-person-read-text (pers-to-check-will-read-for)) (kom-create-aux-item (which-conf-to-add-aux-to)) (kom-recommend-conference (recommend-which-conf)) (kom-limit-import (limit-import-to-conf)) (kom-edit-add-recipient (added-recipient)) (kom-edit-add-bcc (added-blank-carbon-copy)) (kom-edit-add-copy (added-carbon-copy)) (kom-edit-move-text (who-to-move-to-q)) (kom-add-faq (conf-to-add-faq)) (kom-del-faq (conf-to-del-faq)) (kom-review-faq (view-which-faq)) (kom-unread-faq (unread-which-faq)) (kom-change-conf-faq (what-to-change-faq-you)) (kom-list-faqs (conf-to-list-faqs)) (kom-filter-subject (filter-in-conf)) (kom-filter-recipient (filter-recipient)) (kom-filter-text (filter-in-conf)) (kom-change-conf-type (what-conf-to-change)) (kom-change-privileges (what-pers-privs-to-change)) (kom-change-message-flag (set-message-flag-for-conf)) (t (t (default . (lyskom-default-conference-at-point lyskom-default-conference-current)))) ) "Strategy for the initial value for conference defaults. Each element in this list identifies an Emacs och LysKOM command, and defines the initial values for queries it makes for conference names. Each element has the following format: \(COMMAND . \(\(PROMPT-1 . \(\(default . \(INITIAL-VALUES\\)\\) \(filter . \(EXCLUDED-CONFS\)\) \(save . \(SAVE-GROUPS\)\)\)\) \(PROMPT-2 . \(\(default . \(INITIAL-VALUES\)\) \(filter . \(EXCLUDED-CONFS\)\) \(save . \(SAVE-GROUPS\)\)\)\) ...\)\) COMMAND is the name of a LysKOM or Emacs command. PROMPT-1 and PROMPT-2 \(there can be any number of prompts liste in a single command\) are symbols representing the prompt. These are defined in lyskom-messages in swedish-strings.el and english-strings.el. INITIAL-VALUES are functions to call to generate a list of possible initial values for the prompt. These functions must return lists of conference numbers. EXCLUDED-CONFS are functions that are called to eliminate possible initial values. These must take a single argument, an uconf-stat, and should return the uconf-stat itself if it is a valid candidate for the initial value, or nil if it is not. Finally, SAVE-GROUPS are symbols under which the value the user inputs will be saved. As a special case, a list in INITIAL-VALUES is interpreted as a function with arguments. The first element in the list is applied to the remaining elements. If `t' is used for COMMAND, it indicates the default to use when no COMMAND listed matches the current command. If `t' is used for PROMPT, it indicates defaults, filters and save groups to use when no other PROMPT matches. Some useful functions for INITIAL-VALUES are: lyskom-default-conference-at-point returns the conference shown where point is. If point is on a conference name, that name will be used as the initial value. lyskom-default-conference-current returns the current conference. lyskom-default-conference-self returns the logged-in person. lyskom-default-conference-last-author returns the author of the most recently read text. lyskom-default-conference-saved returns saved input. This must be specified as a list in INITAL-VALUES, where the argument (second element of the list) is the symbol under which the input was saved, from \(SAVE-GROUPS\) in one or more commands. Some useful functions for EXCLUDE-CONFS are: lyskom-default-conference-not-self excludes the logged-in person. lyskom-default-conference-not-current excludes the current conference. The format of this variable may change in the future. ") (defconst kom-old-farts-text-prompt-strategy '((kom-comment-previous (nil lyskom-get-previous-text)) (kom-view-previous-commented-text (nil lyskom-get-previous-text)) (kom-private-answer-previous (nil lyskom-get-previous-text)) (t (t lyskom-get-last-read-text) (nil lyskom-get-last-read-text) (0 lyskom-get-text-at-point) (lyskom-eq-dash (lambda () (lyskom-get-text-above-point 1))) (listp (lambda () (lyskom-tnpa-prompt (lyskom-get-last-read-text)))) (plusp current-prefix-arg) (minusp (lambda () (lyskom-get-text-above-point (- current-prefix-arg)))))) "Put in your `kom-pick-text-no-strategy-alist' to get the 0.46 behaviour: * No prefix argument refers to the most recently read text. * The prefix argument zero refers to the text under point. * A positive prefix argument is interpreted as a text-no. * A negative prefix argument will try to find the text-no of the text `arg' messages above point from the current kom buffer.") (defconst lyskom-old-farts-text-prompt-strategy kom-old-farts-text-prompt-strategy "Obsolete: Alias for kom-old-farts-text-prompt-strategy.") (def-kom-var kom-pick-text-no-strategy-alist '( ;; Abstract specifications (read-or-written (t (lambda () (lyskom-tnpa-prompt (lyskom-get-text-at-point)))) (nil lyskom-get-text-at-point (lambda () (lyskom-tnpa-valid (lyskom-tnpa-prompt (lyskom-get-last-written-or-read-by-me)))) :constraint lyskom-text-written-by-me-p)) (previous-text (nil lyskom-get-previous-text)) (commented-text (nil lyskom-maybe-get-commented-text)) (footnoted-text (nil lyskom-maybe-get-footnoted-text)) ;; Specifications for actual commands (kom-comment-previous :refer previous-text) (kom-view-previous-commented-text :refer previous-text) (kom-unread-previous-commented-text :refer previous-text) (kom-private-answer-previous :refer previous-text) (kom-sub-comment :refer commented-text) (kom-sub-footnote :refer footnoted-text) (kom-write-footnote :refer read-or-written) (kom-add-no-comments :refer read-or-written) (kom-add-private-answer :refer read-or-written) (kom-add-request-confirm :refer read-or-written) ;; Default specification (t (nil lyskom-get-text-at-point) (0 (lambda () (lyskom-tnpa-prompt (lyskom-get-text-at-point)))) (lyskom-eq-dash (lambda () (lyskom-get-text-above-point 1))) (car (lambda () (lyskom-get-text-at-point-ancestor (/ (logb (car current-prefix-arg)) 2)))) (plusp (lambda () (lyskom-get-text-below-point current-prefix-arg))) (minusp (lambda () (lyskom-get-text-above-point (- current-prefix-arg)))) (t (lambda () (lyskom-tnpa-prompt (lyskom-get-text-at-point)))) :constraint nil :filter nil ) ) "**Defines how prefix arguments are used by commands to find a text to operate on. The format of this list is as follows: < \((FN-KEY . ((PFX-KEY-1 . (FN1 FN2 ... PROP1 VAL1 PROP2 VAL2 ...)) (PFX-KEY-2 . (FN1 FN2 ... PROP1 VAL1 PROP2 VAL2 ...)) GPROP1 GVAL1 GPROP2 GVAL2 ...)) ...) > `FN-KEY' is the name of a command, `t' or a symbol that does not correspond to any function. Keys corresponding to commands indicate configuration for that command. The `t' key indicates fallback condiguration that applies to all commands, unless overridden by a command-specific configuration. Other keys can be referenced from command-specific configurations. `PFX-KEY' is a key that indicates a prefix. If it is an atom not bound to a function, it indicates configuration for prefix arguments eq to the atom \(e.g. 0, - or `nil'). The special key `t' indicates fallback configuration, used when all prefix-specific configurationas failed to generate valid values. `FN' is a function or variable used to generate lists of text numbers. If a variable name, the value of the variable is used to generate a list of text numbers. If a function, the function is called with no arguments, and is expected to return a list of text numbers. `PROP' is a property name \(see below) and VAL is the corresponding value. Properties defined at the inner level apply only to results generated for that prefix. Properties defined at the outer level apply irrespective of prefix arguments. Properties defined in the default element \(with `FN-KEY' set to `t'\) always apply, unless overridden by non-nil properties in command-specific elements. The following properties are available: Key Value ------------------------------------------------------------------ `:filter' A function that is called on all text numbers. The filter function is expected to return a new or modified text number. This can be used to indicate that the command should prompt or bypass the constraint. `:constraint' A function that is called on all text numbers. It should return non-nil for text numbers that are valid for the command. `:refer' A symbol indicating a configuration to use. Useful when several commands share the same (complex) configuration. May not be used in the default element. ------------------------------------------------------------------ The following filter functions may be useful: Name What it does ------------------------------------------------------------------ `lyskom-tnpa-prompt' Prompt the user for the text number. The number used as the argument will be the default. `lyskom-tnpa-valid' Declare that the text number is valid, regardless of any constraint functions. ------------------------------------------------------------------ When `lyskom-read-text-no-prefix-arg' is called, this list is searched both for a command-specific element and for the default element. Any `:refer' links are resolved in the command-specific element. The filter and constraint properties are extracted. These elements are then searched for prefix-specific elements that match the current prefix argument. The first text number that is generated that passes the filter and constraint functions is used as the text number argument for the command." ) (def-kom-var kom-url-transformation-rules '( ("^http://[^/]*aftonbladet\\.se/.*/story/.*html?$" . "\\&.") ) "**An alist specifying transformations to be applied to URLs. Elements in this list are of the form \(`PATTERN' . `REPLACEMENT'). Before an URL is opened, it is transformed by matching the URL against each `PATTERN' in turn, and when a match is found, generating a new URL according to `REPLACEMENT'. All characters in `REPLACEMENT' except \\ are copied verbatim. The backslash character starts one of the following sequences: Sequence Meaning --------------------------------------------------------------- `\\&' Substitute the matched text `\\N' Substitute match for text matching the Nth (...) group in `PATTERN' `\\\\' Insert one backslash. --------------------------------------------------------------- " server ) (def-kom-var kom-check-configuration-on-startup t "**When non-nil, check Emacs configuration on client startup. Valid values for this variable are `t' and `nil'. All other values are reserved for future extensions. When non-nil, several checks will be performed: * Check that multibyte character support is enabled, if available. * Check that the character coding Emacs uses matches the coding system used by the server. Warnings will be shown in the LysKOM buffer on logon. ") (def-kom-var kom-keyboard-menu-immediate-selection nil "**Controls how keyboard menus work. When displaying text-based menus (typically by pressing the `=' key when the cursor is on an active area), there are two modes of selection. Setting this variable to `t' means pressing the letter corresponding to an item selects that item. When this variable is `nil', selection has to be confirmed by pressing enter. Values other tha `t' and `nil' are reserved for future use." server) (def-kom-var kom-edit-hide-add-button nil "**Controls the \"add\" button in the edit buffer. When set to `t', hide the add button shown after the headers when editing a text. When set to `nil' (the default), show the button. Values other than `t' and `nil' are reserved for future use." server ) (def-kom-var kom-max-overlays 120 "**Maximum number of overlays to use to highlight texts. When a text is displayed with its own background color (see `kom-highlight-text-body', `kom-highlight-first-line', `kom-highlight-dashed-lines', `kom-async-highlight-text-body' and `kom-async-highlight-dashed-lines') one or more overlays are created. Since a large number of overlays has a serious impact on performance, the total number of overlays in the buffer can be limited using this variable. When set to a positive integer, limit the number of overlays to that number. When set to `nil', do not limit the number of overlays. Values other than a positive integer and `nil' are reserved for future use and may cause unpredictible results." server ) (def-kom-var kom-highlight-text-body t "**Controls highlighting of text bodies. If `t', overlay `kom-text-body-face' on printed text bodies in LysKOM. When this is enabled, an overlay or extent will be created that may override certain aspects of the underlying text's formatting. Values other than `t' or `nil' are reserved for future use. See `kom-max-overlays' for information on how to limit the number of overlays." server ) (def-kom-var kom-highlight-first-line t "**Controls highlighting of the first line of text headers. If `t', overlay `kom-first-line-face' on the first header line of texts. When this is enabled, an overlay or extent will be created that may override certain aspects of the underlying text's formatting. Values other than `t' or `nil' are reserved for future use. See `kom-max-overlays' for information on how to limit the number of overlays." server ) (def-kom-var kom-highlight-dashed-lines t "**Controls highlighting of dashed lines around texts. If `t', overlay `kom-dashed-lines-face' on the lines surrounding texts. When this is enabled, an overlay or extent will be created that may override certain aspects of the underlying text's formatting. Values other than `t' or `nil' are reserved for future use. See `kom-max-overlays' for information on how to limit the number of overlays." server ) (def-kom-var kom-async-highlight-text-body t "**Controls highlighting of asynchronous messages. If `t', overlay `kom-async-text-body-face' on asynchronous messages in LysKOM. When this is enabled, an overlay or extent will be created that may override certain aspects of the underlying text's formatting. Values other than `t' or `nil' are reserved for future use. See `kom-max-overlays' for information on how to limit the number of overlays." server ) (def-kom-var kom-async-highlight-dashed-lines t "**Controls highlighting of dashed lines around asynchronous messages. If `t', overlay `kom-dashed-lines-face' on the lines surrounding messages. When this is enabled, an overlay or extent will be created that may override certain aspects of the underlying text's formatting. Values other than `t' or `nil' are reserved for future use. See `kom-max-overlays' for information on how to limit the number of overlays." server ) (def-kom-var kom-extended-status-information nil "**Controls display of extra information when displaying LysKOM objects. If `t', extended status information is listed for all objects in LysKOM. If set to an association list, each element is a pair of tag and value. The tag specifies a type of extended information. If the corresponding value is `t', the information is shown. If the corresponding value is `nil', the information is not shown. Valid tags are: Tag Meaning ------------------------------------------------------------------ `conf' Show all extended information for conferences `pers' Show all extended information for persons `server' Show all extended information for the server `read-faq' Show read FAQs `raw-server-stats' Show raw server statistics `raw-boottime-info' Show raw boot-time server information `t' Any information not explicitly listed ------------------------------------------------------------------ The information controlled by this variable is the kind of data that most users are not interested in, and, if displayed, would make more important information hard to find. Currently this includes read FAQs (for letterboxes) and full statistics and boot-time information (for the server). Values other than those specified are reserved for future extensions." server ) (def-kom-var kom-auto-list-faqs t "**Controls automatic display of FAQs. When this variable is set to `t', list unread FAQs when entering a conference or logging on to the server. When entering a conference, list FAQs for that conference that have not been read. When logging on, list FAQs for the server that have not been read. Values other than `t' or `nil' are reserved for future extension." server ) (def-kom-var kom-auto-review-faqs t "**Controls automatic review of FAQs. When set to `t', automatically review unread FAQs when entering a conference or logging on to the server. When entering a conference, FAQs that are unread for that conference will be reviewed. When logging on, FAQs that are unread for the server will be reviewed. Values other than `t' or `nil' are reserved for future use." server ) (def-kom-var kom-allow-incompleteness nil "**Allow or disallow operation on incomplete membership information. If `nil', commands like `kom-list-news' will wait for all membership information to be read. If this flag is set to `t', commands will not wait for all membership information. Not waiting for complete information allows certain commands to execute faster, particularly during the login phase, but may result in incorrect or incomplete answers. Values other than `t' or `nil' are reserved for future use." server ) (def-kom-var kom-bury-buffers t "**Controls the behaviour of `kom-next-kom' and its cousins. If this variable is `t' the current buffer is sent to the back of the buffer list when one of the commands `kom-next-kom', `kom-previous-kom' or `kom-next-unread-kom' is invoked. Values other than `t' or `nil' are reserved for future use." server) (def-kom-var kom-write-texts-in-window nil "**Determines where to edit texts. The value must be one of `nil', `other', `new-frame', `other-frame', a string or a buffer. When set to `nil', edit texts in the same window as the LysKOM buffer. When set to `other', edit in another window, creating it if necessary. When set to `other-frame', edit in another frame, if there is one \(otherwise edit in the same window as the LysKOM buffer). When set to `new-frame', create a new frame for editing. This frame will be removed when editing is finished. A string means edit in the buffer with that name. A buffer means edit in that buffer." server) (def-kom-var kom-view-commented-in-window 'other "**Where to view commented texts. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-edit-filters-in-window nil "**Where to edit filters with `kom-filter-edit'. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-list-membership-in-window 'other "**Where to list membership with `kom-list-membership'. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-personal-messages-in-window 'other "**Where to display personal messages. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-customize-format 'long "**Determines the format of the customize buffer. This variable currently only controls initial display of documentation in the customize buffer (the buffer shown by `kom-customize'. When set to the symbol `long', display documentation. When set to the symbol `short', don't display documentation. Values other than `long' or `short' are reserved for future use." server) (def-kom-var kom-user-prompt-format "%[%c% %m%] - " "**Format of LysKOM prompt when waiting for input. The value of this variable must be a string, which is displayed as the LysKOM prompt, while waiting for a command. The string may contain the following special sequences: Sequence Meaning ----------------------------------------------------------------- `%c' Inserts the current default command. `%[' Inserts `[' if the ansaphone is on. `%]' Inserts `]' is the ansaphone is on. `%m' Inserts information about recorded messages. `%s' Inserts the name of the LysKOM system `%S' Inserts the server name. `%p' Inserts the name of the user currently logged on. `%w' Inserts the name of the current conference. `%a' Inserts `anonymous' in the current language. `%A' Inserts `Anonymous' in the current language. `%#' Inserts the current session number. `% ' Inserts a space if it seems necessary (percent SPC). `%%' Inserts a percent sign. ----------------------------------------------------------------- Here are a few examples: Format string What it does ----------------------------------------------------------------- `\"%[%c% %m%] - \"' The default prompt `\"%[%s: %c% %m%] - \"' Could display \"LysKOM: Time - \" ----------------------------------------------------------------- Note that multiline prompts are not supported." server) (def-kom-var kom-user-prompt-format-executing "%[%c% %m%]." "**Format of LysKOM prompt when executing a default command. The value of this variable must be a string. See `kom-user-prompt-format' for details." server) (def-kom-var kom-enabled-prompt-format "%[%c% %m%] # " "**Format of LysKOM prompt when privileges are enabled.. The value of this variable must be a string. See `kom-user-prompt-format' for details." server) (def-kom-var kom-enabled-prompt-format-executing "%[%c% %m%]." "**Format of LysKOM prompt when executing a default command when privileges are enabled. The value of this variable must be a string. See `kom-user-prompt-format' for details." server) (def-kom-var kom-anonymous-prompt-format "%[%c% %m%] (%a) - " "**Format of the LysKOM prompt when running anonymously. The value of this variable must be a string. See `kom-user-prompt-format' for details. See `kom-become-anonymous' for information on anonymous mode. " server) (def-kom-var kom-anonymous-prompt-format-executing "%[%c% %m%] (%a)." "**Format of the LysKOM prompt when executing a command anonymously. The value of this variable must be a string. See `kom-user-prompt-format' for details. See `kom-become-anonymous' for information on anonymous mode." server) (def-kom-var kom-show-week-number t "**Controls display of week numbers in `kom-display-time'. If set to `t' show the ISO week number when displaying the time. If set to `nil', don't display the time. All other values are reserved for future use. For this feature to work, the calendar package must be installed." server) (def-kom-var kom-cite-string ">" "**String to insert before each line of a commented text. When citing a text in edit-mode, this string will be inserted before each line. Although citing is not common and usually not useful in LysKOM, there is occasionally reason to cite a commented text." server) (def-kom-var kom-created-texts-are-saved nil "**If non-nil, save all created texts to a file. The value of this variable is the file name on which to save new texts. Each time a text is created, it is appended to this file. Values other than a string may produce unpredictible results, and are reserved for future extensions." server inherited) (def-kom-var kom-created-texts-are-read nil "**non-nil means automatically mark texts that you create as read. When set to `t', all text you write are automatically marked as read, except when running in anonymous mode. When set to `nil', your texts will be shown as all others. Values other than `t' and `nil' are reserved for future extensions." common created-texts-are-read boolean) (def-kom-var kom-mark-read-texts-as-read-in-new-recipient t "**Controls whether to mark read texts as read in new recipients the acquire. When this is set to `t', silently mark texts as read when they are added to a new recipient, if they have been read in any conference. When `nil', do not mark as read. This feature only works when you are logged on. Texts added to new conferences while you are not logged on will not be marked as read in the new recipient. Values other than `t' or `nil' are reserved for future extensions." server) (def-kom-var kom-customize-in-window nil "**Where to customize LysKOM with `kom-customize'. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-prioritize-in-window nil "**Where to prioritize conferences with `kom-prioritize'. See the documentation for `kom-write-texts-in-window' for details." server) (def-kom-var kom-default-mark nil "**The default mark used by `kom-mark-text'. When set to an integer, `kom-mark-text' will not ask for a mark, but simply mark with that number. When set to `nil', `kom-mark-text' will ask for a mark. Values other than integers and `nil' are reserved for future use." common default-mark integer server) (def-kom-var kom-symbolic-marks-alist '(("Standard" . 100)) "**Association list that maps symbolic marks to mark numbers. Internally, texts can only be marked with numbers. The elisp client implements symbolic marks through this mapping from mark names to numbers. Each element of this list is a pair \(`NAME' . `MARK'), where `NAME' is the name of the mark, and `MARK' is the corresponding numeric mark." server) (def-kom-var kom-reading-puts-comments-in-pointers-last t "**Controls the location where comment pointers are shown. When set to `t', comment references are shwon at the end of texts. When set to `nil', comment references are shwon in the headers. `kom-reading-puts-comments-in-pointers-last' set to `nil' < 398331 1996-09-24 13:22 /2 lines/ George Berkeley Recipient: Philosophy <1226> Comment in text 398374 by John Locke Subject: ------------------------------------------------------------ An abstract idea is a contradiction in terms. (398331) ----------------------------------- > `kom-reading-puts-comments-in-pointers-last' set to `t' < 398331 1996-09-24 13:22 /2 lines/ George Berkeley Recipient: Philosophy <1226> Subject: ------------------------------------------------------------ An abstract idea is a contradiction in terms. (398331) ----------------------------------- Comment in text 398374 by John Locke > " common reading-puts-comments-in-pointers-last boolean inherited) (def-kom-var kom-review-uses-cache t "**Controls whether review commands use the cache or not. When set to `t', review commands (such as `kom-review-by-to') will get texts from the client cache, if possible. This improves performance, but texts may have changed since they were cached. When set to `nil', review commands will always get texts from the server. Values other than `t' and `nil' are reserved for future use." server inherited) (def-kom-var kom-review-marks-texts-as-read nil "**Controls whether viewing texts with review commands marks then as read. When set to `t', viewing texts with review commands (e.g. `kom-review-by-to') will mark unread texts as read. When set to `nil', texts are not marked as read. It is possible to change this setting for a single review command with the key sequence for `kom-toggle-mark-as-read-prefix'. The value can be changed for the entire session by using `kom-make-review-mark-as-read' or `kom-make-review-not-mark-as-read'. Values other than `t' and `nil' are reserved for future use." server inherited) (def-kom-var kom-postpone-default 17 "**The default number of texts to postpone with `kom-postpone'. The value of this variable must be a positive integer or zero. All other values are reserved for future use." server) (def-kom-var kom-dashed-lines t "**Controls display of dashed lines before and after texts. when set to `t' display dashed lines. When set to `nil', don't display dashed lines. `kom-dashed-lines' set to `t' < 892343 1996-09-24 19:21 /2 lines/ Tycho Brahe Recipien: Presentation (of new) Members Subject: Tycho Brahe ------------------------------------------------------------ Astronomer and discoverer of stars resident on the island of Ven. (892343) ----------------------------------- > `kom-dashed-lines' set to `nil' < 892343 1996-09-24 19:21 /2 lines/ Tycho Brahe Recipien: Presentation (of new) Members Subject: Tycho Brahe Astronomer and discoverer of stars resident on the island of Ven. (892343) > Values other than `t' and `nil' are reserved for future use. See `kom-highlight-dashed-lines' and `kom-async-highlight-dashed-lines' for additional settings that affect these lines." common dashed-lines boolean inherited) (def-kom-var kom-long-lines nil "**If non-nil, some lines and borders will be made longer. When set to `t', most dashed lines will be longer than the default. When set to `nil', use the standard length. See `kom-text-footer-dash-length', `kom-text-header-dash-length' and `kom-text-footer-format' for other related settings." server inherited) (def-kom-var kom-text-footer-dash-length 52 "**Control the length of the text footer. When dashed lines (see `kom-dashed-lines') are in effect, and this is set to a positive integer, make the text footer at least that many characters long. Values other than a positive integer are reserved for future use. Note that the footer may end up longer than this if one or more elements together are longer than this length. This length is currently ignored when `kom-text-footer-format' is used." server inherited) (def-kom-var kom-text-header-dash-length 60 "**Control the length of the text footer. When dashed lines (see `kom-dashed-lines') are in effect, and this is set to a positive integer, make the dashed line before the text that many characters long. Values other than a positive integer are reserved for future use." server inherited) (def-kom-var kom-text-footer-format nil "**Defines the format of the text footer. When set to a string, use that string as the text footer, overriding all other settings that affect the text footer. The string may contain the following special sequences: Directive Meaning ------------------------------------------------------------- `%n' Insert the text number `%p' Insert the number of the author `%P' Insert the name of the author `%-' Insert a bunch of dashes `%f' Insert special formatting information ------------------------------------------------------------- Format directives can be prefixed with a number specifying the minimum field width (e.g. `%20-'. The field width can be prefixed with an equals sign (e.g. `%=20p' which means that the field is exactly as wide as specified (contents may be truncated). A negative field width means left justify the contents. The field width of %- is special. It specifies the maximum number of dashes printed. The actual number will be the maximum minus the length of the author's name, if it is included anywhere in the format string. When set, this variable overrides `kom-dashed-lines' and `kom-show-author-at-end'. The default format is equivalent to the following strings, depending on the settings of kom-dashed-lines and kom-show-author-at-end. `kom-dashed-lines' `kom-show-author-at-end' Format -------------------------------------------------------------------- `t' `t' `\"(%n) /%P/%42-%f\"' `t' `nil' `\"(%n) %42-%f\"' `nil' `t' `\"(%n) /%P/ %f\"' `nil' `nil' `\"(%n) %f\"' -------------------------------------------------------------------- " server inherited) (def-kom-var kom-show-creating-software nil "**Controls display of the software used to create each text. When creating a text, it is possible to attach information about which client was used to create the text. When this variable is set to `t', this information, when available, is displayed in all text headers. When this variable is set to `nil', the information is not shown. To display creating software for a text when this is off, review the text using `kom-review-noconversion'. Values other than `t' and `nil' are reserved for future use." server inherited) (def-kom-var kom-show-author-at-end t "**Controls display of author information in the text footer. When this is set to `t', display the author of each text immediately after the text. When set to `nil', the author is not displayed. `kom-show-author-at-end' set to `t' (with dashed lines on): < 892342 1996-09-24 19:21 /2 lines/ Claude Shannon Mottagare: Presentation (of new) Members Ärende: Claude Shannon ------------------------------------------------------------ Information theoretician (892342) /Claude Shannon/------------------------------ > `kom-show-author-at-end' set to `nil': < 892342 1996-09-24 19:21 /2 lines/ Claude Shannon Recipient: Presentation (of new) Members Subject: Claude Shannon ------------------------------------------------------------ Information theoretician (892342) ----------------------------------- > If `kom-text-footer-format' is set, the value of this variable is ignored. Values other than `t' and `nil' are reserved for future use." server inherited) (def-kom-var kom-truncate-threshold nil "**Controls truncation of text when reviewing. When set to a positive integer, truncate long texts when reviewing. If the text has more lines than the value of this variable, it will be truncated to `kom-truncate-show-lines' lines. When a message is truncated, a note to that effect will be shown in the message footer unless `kom-text-footer-format' has been set to a string that does not include the `%f' directive. When set to `nil', no truncation will occur. Values other than positive integers and `nil' are reserved for future use." server) (def-kom-var kom-truncate-show-lines 10 "**Number of lines to display when truncating texts. The value must be a positive integer. When a text is truncated \(see `kom-truncate-threshold', the minimum of `kom-truncate-threshold' and `kom-truncate-show-lines' determines the number of lines to show. Values other than positive integers are reserved for future use." server) (def-kom-var kom-print-number-of-unread-on-entrance t "**Controls display of number of unread when entering a conference. When set to `t', the number of unread texts in a conference is displayed when entering that conference. When set to `nil', the number of unread texts is not shown. Shortly after logging on, using `kom-set-unread' or using `kom-recover', the number shown may be incorrect. Values other than `t' and `nil' are reserved for future use." common print-number-of-unread-on-entrance boolean) (def-kom-var kom-show-unread-in-frame-title t "**Controls display of the unread indicator in the frame title. When set to `t', an indicator will be shown in the title of each frame containing a selected LysKOM session with unread texts. When set to `nil' no indicator will be shown. Values other than `t' and `nil' are reserved for future extensions." server) ;; In the common block of the user-area is a simple boolean variable ;; `presence-messages'. The control of presence messages in the Emacs ;; Lisp client is more advanced, using two non-boolean variables instead ;; (`kom-presence-messages-in-echo' and `kom-presence-messages-in-buffer'). ;; ;; Keep track of the common block variable too, although it isn't used here. ;; `lyskom-save-options' sets it before saving it in obvious cases, ;; but generally it's not possible to know what value it should have. ;; (It could also be used for default values for the presence options for ;; users converting from another client, but that isn't done.) (def-kom-var kom-presence-messages t "Equivalent to the variable `presence-messages' in the user-area. This is a boolean where other clients may store whether the user wants messages about people logging in and out of LysKOM. Here this is instead controlled by `kom-presence-messages-in-echo-area' and `kom-presence-messages-in-buffer', so only use this variable to influence what this client stores in the common block of the user-area." common presence-messages boolean) (def-kom-var kom-presence-messages-in-echo-area t "**Controls display of presence messages in the echo area. If non-nil, LysKOM prints continuous info about what other people are doing. Info is printed on the echo area and never in the buffer. If minibuffer is used, no message is printed. A list of integers means show messages for those users. The value `friends' means show messages for the users in `kom-friends'. The value `morons' means show messages for the users in `kom-morons'. The value `friends-and-morons' means show messages for the users in `kom-friends' and `kom-morons'. If you want the messages in the buffer, set the variable `kom-presence-messages-in-buffer'. Values other than those listed are reserved for future use." server) (def-kom-var kom-unread-mode-line-type nil "**Controls how information about unread sessions is shown in the mode line. If this variable is `nil', there will be a single prompt indicating whether you have unread texts or letters in any active session. If this variable is `t', the mode line will indicate each session with unread texts. Unread letters are indicated by upper-casing the session name or (if the session name is in upper case already) surrounding it with asterisks. All other values are reserved for future use." ) (def-kom-var kom-presence-messages-in-buffer nil "**Controls display of presence messages in the LysKOM buffer. If non-nil, LysKOM prints information about what other people are doing in the LysKOM buffer. All printing is done just before the prompt. If `nil' no messages are printed. If `presence', messages about people logging in, out and people changing name are printed. All other values are reserved for future use." server) (def-kom-var kom-show-where-and-what t "**Controls display of hostname and activity information in `kom-who-is-on'. When this is set to `t', `kom-who-is-on' and related commands will display the machine the session is connected from and what the user is doing. When set to `nil', this information will not be shwon. Listing frmo `kom-who-is-on' with `kom-show-where-and-what' set to `t': < User Is in conference At Activity -------------------------------------------------------------------------- 6810 George Berkeley Philosophy berkeley@emp1.tcd.ie (Writing a comment.) 7571 John Locke Philosophy eridy@cc.ox.ac.uk (Waiting.) -------------------------------------------------------------------------- > Listing frmo `kom-who-is-on' with `kom-show-where-and-what' set to `nil': < User Is in conference -------------------------------------------------------------------------- 6810 George Berkeley Philosophy 7571 John Locke Philosophy -------------------------------------------------------------------------- > Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-show-since-and-when nil "**Controls display of connection time in `kom-who-is-on'. When set to `t', `kom-who-is-on' and related commands will display the time when each session connected to the server and when each session last indicated activity. Listing frmo `kom-who-is-on' with `kom-show-since-and-when' set to `t': < User Is in conference Connected Active last -------------------------------------------------------------------------- 6810 George Berkeley Philosophy Thursday 2003-01-09 09:24:56 Active 7571 John Locke Philosophy Saturday 2003-01-11 14:02:47 12 minutes -------------------------------------------------------------------------- > Listing frmo `kom-who-is-on' with `kom-show-since-and-when' set to `nil': < User Is in conference -------------------------------------------------------------------------- 6810 George Berkeley Philosophy 7571 John Locke Philosophy -------------------------------------------------------------------------- > Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-idle-hide 30 "**Controls display of idle sessions in `kom-who-is-on'. When set to a positive integer, the number of minutes of idletime before a user is excluded from the list of users shown by `kom-who-is-on' and related commands. This can be overridden by a prefix argument to these commands. When set to `nil', do not hide idle sessions. Variables other than positive integers and `nil' are reserved for future use." server) (def-kom-var kom-show-footnotes-immediately t "**Controls display of footnotes. When set to `t', footnotes will be displayed immediately following the text. When set to `nil', footnotes will be displayed like regular comments. Values other than t and `nil' are reserved for future use." server) (def-kom-var kom-follow-comments-outside-membership nil "**Controls display of comments in conferences you are not a member of. If this variable is set to `nil', texts with no recipient you are a member of will be ignored when selecting comments to display when reading. When set to `t', the client will follow comment links regardless of whether you are a member of any of the recipients of the comment. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-follow-attachments t "**Controls how attachments to imported e-mail messages are handled. When this is set to `t', attachments are followed like regular comments. When set to `nil', attachments are not followed. To see them you have to review them manually. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-read-depth-first t "**Determines the order in which to read texts. When set to `t' \(the default), texts are read in comment order. When set to `nil', texts are read in chronological order. When reading in comment order, the next text to read is the first comment of the most recently read text. If there are no comments, the next text is a comment to another text. Reading in comment order lets you view threads of discussion. Values other than `t' or `nil' are reserved for future use." common read-depth-first boolean) (def-kom-var kom-continuous-scrolling t "**Controls frequency of scrolling. When set to `t', the LysKOM buffer is scrolled whenever text is inserted. The last viewed position \(usually the most recent prompt) will always be visible. When set to `nil', scrolling takes place less frequently. This is a suitable setting when running Emacs over a slow link, such as an old modem. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-deferred-printing t "**Controls background display of non-cached information. When set to `t', delay display of \(some) information that has to be retreived from the server. A placeholder is shown where the information will be printed, until it is available. This setting results in a significant improvement in interactive performance. When set to `nil', do not delay display of any information. This lowers interactive performance, but may be suitable when running Emacs over a slow connection. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var lyskom-overlay-pool nil "Pool of overlays" local) (def-kom-var lyskom-defer-indicator "[...]" "String to display while LysKOM is waiting for the real string.") (def-kom-var kom-review-priority nil "**Priority to use when reviewing texts. When set to a positive integer, use that as the priority to use when reviewing texts. By setting `kom-review-priority' higher than 255 (the maximum conference priority), new texts to conferences will not break in while reviewing. If set to `nil', use the current priority while reviewing. This allows texts to conferences with priorities higher than that of the current conference to break in while reviewing (depending on the setting of `kom-higher-priority-breaks'). Values other than positive integers and `nil' are reserved for future use." server) (def-kom-var kom-higher-priority-breaks nil "**Controls how conference priorities are handled. When set to `express', texts to conferences with a higher priority than the current conferences will be shown as soon as the arrive. When set to `t', texts to prioritized conferences will be shown after the current comment tree. When set to `nil', prioritized conferences will be visited when all texts in the current conference have been read. Values other than `express', `t' and `nil' are reserved for future use." server) (def-kom-var kom-server-priority-breaks nil "**Controls how server priorities are handled. A non-nil value allows servers with a higher priority than the current server to break in when new texts arrive. This can be used to give a work-related server a higher priority than a server used for frivolous purposes (or, indeed, the other way around). The following settings are available: Value Meaning -------------------------------------------------------------------- `express' Break in immediately when there are unread texts. `express-letters' Break in immediately when there are unread letters. `t' Break in after the current comment chain when there are unread texts. `letters' Break in after the current comment-chain when there are unread letters. `after-conf' Break in after the current conference when there are unread texts. `after-conf-letters' Break in after the current conference when there are unread letters. `when-done' Prompt the user to go to the next session with unreads after everything has been read. This overrides `kom-do-when-done' as long as there are sessions with unread texts. -------------------------------------------------------------------- Values other than those listed above are reserved for future use and may result in unpredictible behavior. See `kom-server-priority' for information on setting the server priority." server) (def-kom-var kom-session-nickname nil "**Nickname for the current LysKOM session. This variable contains the name of the current LysKOM session (a string) or `nil'. If set, it will be used as the nickname for this LysKOM session. See also `kom-server-aliases' and `kom-builtin-server-aliases'." server) (def-kom-var kom-view-text-hook nil "**Hook that is called before a text is shown. When the hooks are called, `kom-view-text-text' is bound to the text mass of the text and `kom-view-text-text-stat' to the text-stat of the text to be shown." local-hook) (def-kom-var lyskom-view-text-hook nil "Obsolete synonym for kom-view-text-hook." local-hook) (def-kom-var lyskom-send-message-hook nil "Obsolete synonym for lyskom-send-message-hook." local-hook) (def-kom-var kom-send-message-hook '(lyskom-send-message-trim-newlines) "**Hook that is called before a personal, group or common message is sent. When called, `lyskom-message-string' is bound to the message that will be sent and `lyskom-message-recipient' to the conf-stat of the recipient or nil if the recipient does not exist or if the message is a common message. If `lyskom-message-string' is set to nil by a hook, the message will not be sent." local-hook) (def-kom-var kom-send-message-setup-hook nil "**Hook that is called when the minibuffer is entered to read a message. This hook can be used to set up the minibuffer in a way suitable for writing messages. For example, the hook might enable `auto-fill-mode' or set up automatic resizing of the minibuffer." local-hook) (def-kom-var lyskom-send-message-setup-hook nil "Obsolete synonym for kom-send-message-setup-hook." local-hook) (def-kom-var kom-send-message-exit-hook nil "**Hook that is called when the minibuffer is exited after reading a message. Typically this hook will be used to undo the effects of `kom-send-message-setup-hook'." local-hook) (def-kom-var lyskom-send-message-exit-hook nil "Obsolete synonym for kom-send-message-exit-hook." local-hook) (def-kom-var kom-send-text-hook nil "**Hook that is called before sending a text. This hook is called before the headers are parsed, so it is possible for the headers to be modified after this hook is called. It is also possible that the text will not be sent at all." local-hook) (def-kom-var lyskom-send-text-hook nil "Obsolete synonym for kom-send-text-hook." local-hook) (def-kom-var kom-after-load-hook nil "**Hook to run once after LysKOM is loaded. This is similar in effect to using `eval-after-load', but is independent of the file name of the client.") (def-kom-var lyskom-after-load-hook nil "Obsolete synonym for kom-after-load-hook.") (def-kom-var kom-change-conf-hook nil "**Hook to run when changing conferences. The functions in this list are run with two arguments. The first is the current conference number and the second is the number of the conference being changed to. This hook is run before `lyskom-current-conf' is changed, and before any standard messages have been printed." local-hook) (def-kom-var lyskom-change-conf-hook nil "Obsolete synonym for kom-change-conf-hook" local-hook) (def-kom-var kom-after-change-conf-hook nil "**Hook to run when changing conferences. The functions in this list are run with two arguments. The first is the current conference number and the second is the conference number being changed to. This hook is run after `lyskom-current-conf' is changed, and after any standard messages have been printed." local-hook) (def-kom-var lyskom-after-change-conf-hook nil "Obsolete synonym for kom-after-change-conf-hook." local-hook) (def-kom-var lyskom-login-hook nil "**Hook called while logging in. This hook is called after the session is logged in but before any command is accepted from the keyboard. It is called immediately before `kom-login-hook'." local-hook) (def-kom-var kom-login-hook nil "**Hook called while logging in. This hook is called after the session is logged in but before any command is accepted from the keyboard. Unlike `lyskom-login-hook' it can be stored in the server." server) (def-kom-var kom-relogin-inhibit-commands '(kom-next-kom kom-previous-kom kom-where-is kom-next-unread-kom) "**Commands for which relogin is disabled. This should be set to a list of commands for which relogin should not be offered or used." server) (def-kom-var kom-relogin-behaviour 'ask "**Controls how to behave when commands are issued in dead sessions. When this is set to `t', the client will try to login automatically. When set to `ask', the client will ask whatever the user wants to reattach. When set to `nil', the client will not attempt to reattach." server) (def-kom-var kom-remember-password nil "**Controls whatever to store the password in the session buffer. When this is set to `t', the client will store the password for the current session as a buffert local variable. This can be used in conjunction with `kom-relogin-behaviour' to reattach dead sessions automatically." server) (def-kom-var kom-confirm-add-recipients t "**Controls confirmation when adding recipients. When this is set to `t', confirm the recipient type when adding recipients. Commands like `kom-add-recipient' will pose a question to determine the type of recipient to add. When set to `nil', assume that the user always wants full recipients when using `kom-add-recipient' and similar commands. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-do-when-done '(kom-review-all-marked-texts kom-display-time) "**What to do when all texts are read. This is a list of commands and lists of commands that are prompted for and executed when there are no more new texts. The last command in the list will be prompted for over and over until new texts arrive. The values in the list can be a LysKOM command (a symbol), an Emacs command or a keyboard macro (a string). Values other than those listed are reserved for future use." server) (def-kom-var kom-page-before-command nil "**Controls clearing of the screen prior to certain commands. When this variable is set to `t', all commands will execute at the top of the LysKOM window. When a command is issued, the buffer will be scroll so the last prompt is on the first line of the buffer. When set to a list of LysKOM commands \(symbols), those commands will execute at the top of the window. All others will execute without scrolling the buffer. When set to `nil', never scroll the buffer in the way described. Values other than those listed are reserved for future use." server) (def-kom-var kom-permissive-completion t "**Controls completion of logged-in sessions. When the client reads names of logged-in users in the minibuffer \(e.g. `kom-status-session'), it can permit completion of all users or just those that are logged on. If this variable is set to `t', completion will include all users, including those that are not logged in. If this variable is set to `nil', completion will be restricted to users who are logged in. Setting this variable to `t' may improve performance significantly, particularly on servers with many sessions. Values other than `t' or `nil' are reserved for future use." server) (def-kom-var kom-unsubscribe-makes-passive t "**Controls behavior of `kom-sub-self'. If this variable is set to `t', leaving a conference with `kom-sub-self' will make the membership passive. Leaving a second time \(while the membership is still passive) will remove the membership entirely. When set to `nil', `kom-sub-self' removes the membership immediately. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-membership-default-priority 'ask "**Default priority when joining a new conference. If set to a valid priority (integer from 0 to 255) then new conferences are read with this priority. When set to the symbol `ask', the client will ask for a priority when joining new conferences. Values other than those listed are reserved for future use." server) (def-kom-var kom-membership-default-message-flag 'ask "**Default message flag when joining a new conference. If set to `nil', messages will not be received for new conferences, if set to `t', messages will be received. When set to the symbol `ask', the client will ask if you want to receive messages when you join new conferences. Values other than those listed are reserved for future use." server) (def-kom-var kom-membership-default-placement 'last "**Default placement of new memberships. This variable controls the placement of memberships within the membership list when you join a conference. Note that the membership priority has precedence over this position. The value can be `first', `last' or a number. When set to `first', the membership will be entered before all others. When set to `last', it will be entered after all others. When set to an integer, the membership is entered at that position in the list. All other values are reserved for future use." server) (def-kom-var lyskom-current-prompt nil "The current prompt or nil. This is either nil, indicating that there is currently no prompt, or a symbol indicating which command is prompted in the LysKOM buffer." local) (def-kom-var lyskom-current-prompt-text nil "The current prompt text or nil. This is either nil, indicating that there is currently no prompt, or a string indicating the prompt shown in the LysKOM buffer." local) (def-kom-var lyskom-current-prompt-args nil "The current prompt arguments. These are arguments used to format the current prompt." local) (def-kom-var lyskom-current-prompt-timestamp nil "The creationtime of the current prompt. This is used when updating the prompt and on `lyskom-start-of-command'." local) (def-kom-var lyskom-need-prompt-update nil "Non-nil if all prompts need to be updated." local) (def-kom-var kom-show-personal-messages-in-buffer t "**Buffer to show personal, group and alarm messages in. This variable controls which buffer personal, group and alarm messages are shown in. When set to `nil', all messages are silently discarded. When set to `t', messages are shown in the main LysKOM buffer. When set to a string, messages will be inserted in a buffer by that name \(one will be created if necessary). When set to a buffer, messages are inserted in that buffer. All values other than those listed are reserved for future use." server) (def-kom-var kom-pop-personal-messages nil "**Non-nil means pop up a buffer with personal messages as they arrive. When this variable is set to `nil', personal, group and alarm messages are simply inserted in the appropriate buffer \(see `kom-show-personal-messages-in-buffer'). The buffer is not displayed automatically. When this variable is set to `t', the buffer in which a new message is shown will be displayed automatically, possibly splitting windows and uniconifying frames. When this variable is set to `yes', the behavior is identical to when it is set to `t', but frames will not be uniconified. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-ding-pause-amount 0.1 "**Number of seconds to wait between successive beeps. When multiple beeps are used as audible notification, this determines the amount of time (in seconds) to wait between successive beeps. The value must be a positive number (it may be a floating point number).") (def-kom-var kom-ding-on-priority-break 1 "**Non-nil means ding if a higher priority text or conference breaks in. This variable must be set to a `t', `nil', a positive integer, a string or a function. When set to `t' use the default beep. When set to `nil', do not beep. When set to a number, beep that many times \(see `kom-ding-pause-amount' for additional settings). When set to a function, call that function. When set to a string, run the program indicated by `kom-audio-player' with the string as its sole argument." server) (def-kom-var kom-ding-on-new-letter nil "**Non-nil means ding if a message arrives in the letter box. See `kom-ding-on-priority-break' for valid values." server) (def-kom-var kom-ding-on-wait-done 1 "**Non-nil means ding when `kom-busy-wait' terminates. See `kom-ding-on-priority-break' for valid values." server) (def-kom-var kom-ding-on-common-messages 0 "**Non-nil means ding when an alarm message arrives. See `kom-ding-no-priority-break' for valid values. In addition to those listed there, the value of this variable may be a list of elements like \(`KEY' . `VALUE'). If the sender (a conference number) is found as the key of any element, the value of that element will be used to generate the ding (valid values are those listed for `kom-ding-on-priority-break'). The special key `t' is used when no other key matches the sender." server) (def-kom-var kom-ding-on-group-messages 1 "**non-nil means ding when a group messages arrives. See `kom-ding-on-common-messages' for valid values." server) (def-kom-var kom-ding-on-personal-messages 2 "**non-nil means ding when a personal message arrives. See `kom-ding-on-common-messages' for valid values." server) (def-kom-var kom-ding-on-no-subject 2 "**How to ding if the user has not entered a subject line. When attempting to submit a text without a subject line, this variable determines how to beep. See `kom-ding-on-priority-break' for valid values." server) (def-kom-var kom-audio-player "audioplay" "**Program used to play audio files. If a of the variables that control audio signals (dings, beeps) is set to a string, the command (shell command, not Emacs command) indicated by this variable will be called with that string as an argument. Therefore, this variable should be set to the name of an external command that takes a single argument: a sound file to play. Non-string values are reserved for future use." server) (def-kom-var kom-ignore-message-senders nil "**List of senders whose personal, group and alarm messages are ignored. The value of this variable must be a list of person numbers. Personal, group and alarm messages sent by users in this list will be silently ignored. Values other than those listed are reserved for future use." server) (def-kom-var kom-ignore-message-recipients nil "**List of recipients you do not want group messages to. The value of this variable must be a list of conference numbers. Messages sent to a recipient listed will be silently ignored. Values other than those listed are reserved for future use." server) (def-kom-var kom-show-personal-message-date t "**Controls display of date on personal messages. When set to `t', display the date and time when personal, group and alarm messages arrived. When set to `nil', only display the time. `kom-show-personal-message-date' set to `t'>: < ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Alarm message from Claude Chappe (1805-01-23 17:34): Je me donne la mort our éviter l'ennui de la vie qui m'accable; je n'ai point de reproches à me faire. ---------------------------------------------------------------- > `kom-show-personal-message-date' set to `nil': < ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Alarm message from Claude Chappe (17:34): Je me donne la mort our éviter l'ennui de la vie qui m'accable; je n'ai point de reproches à me faire. ---------------------------------------------------------------- > See Bulletin of Les Amis de Paris Central Télégraphe, no. 20, July 1993 for information on the quote above. " server) (def-kom-var kom-default-message-recipient 'group "**Determines default recipient of personal messages. When set to `everybody', the default recipient of all messages will be all users (i.e. the default is to send alarm messages). This may not work properly. If set to `group', the default recipient depends on the message most recently received. If that message was a group message, then the default recipient will be the recipient of that message. If that message was a personal message or an alarm message, the default recipient will be the sender of the most recent message. If set to `sender', the default recipient is always the sender of the most recently received message, regardless of its type. Values other than those listed are reserved for future use." server) (def-kom-var kom-filter-outgoing-messages t "**Determines whether automatic outgoing messages are shown. When set to `t', outgoing remote control messages and automatic replies are not displayed. When set to `nil', these messages are shown the same way normal messages are shown when sent. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-highlight-conferences '((kom-friends . kom-friends-face) (kom-morons . kom-morons-face) (lyskom-highlight-has-no-presentation . kom-active-strikethrough-face) (lyskom-pers-no . kom-me-face) (lyskom-highlight-i-am-supervisor . kom-active-highlight-face)) "**How to highlight conference an person names. The value of this variable is an alist whose keys are matched against conference numbers and whose values are the names of faces to use for matching conferences. The following values are legal for keys: Value Meaning ----------------------------------------------------------------- Symbol If the value is a list, matches if the conference number is in the list. If the value is an integer, matches if the conference number matches the integer. List Matches if the conference number is in the list. Function Matches if the function returns non-nil (see below). ----------------------------------------------------------------- When using a function as the key, the function will be called with a single argument, the object to be printed. The type of the argument will vary depending on how it is printed. Functions should be written so they work regardless of what is passed to them. All other values are reserved for future use." server) (def-kom-var kom-friends nil "**List of friends and other nice people. The value of this variable is a list of person numbers. People listed here will be displayed using the face in `kom-friends-face'. They can also receive special treatment in other cases (see `kom-presence-messages'). See `kom-morons' for a related variable. Values other than a list of integers are reserved for future use." server) (def-kom-var kom-morons nil "**List of people morons and other nasty people. The value of this variable is a list of person numbers. People listed here will be displayed using the face in `kom-morons-face'. See `kom-friends' for a related variable. Values other than a list of integers are reserved for future use." server) (def-kom-var kom-dont-check-commented-authors nil "**A list of recipients that don't need to see comments to their texts. When writing a comment, the client can check that the author of the commented text is a member of at least one of the recipients. If that is not the case, the user will be offered to add the author as a recipient. This variable lists authors who shold not be checked in this manner. Typically it will contain a list of import agents. Values other than a list of integers are reserved for future use." server inherited) (def-kom-var kom-smileys t "**Controls display of graphical smileys. When set to `t', display graphical smileys instead of `:-)' and similar character sequences. When set to `nil', do not display graphical smileys. For this to work at all you must have the `smiley' or `smiley-ems' installed (usually installed with Gnus) and support for graphics (part of XEmacs and Gnu Emacs 21.x and later). Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-text-properties t "**Controls use of text properties in LysKOM (fonts and stuff). When set to `t', the client will freely use text properties, like fonts. When set to `nil', the client will not use text properties. This will disable all font usage and clickable stuff. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-fontify-text t "**Controls whether plaintext messages are fontified. When set to `t', the client will make words and phrases delimited by asterisks bold, and words and phrases delimited by underscore italic. Other similar features may be added in the future. Values other than `t' or `nil' are reserved for future use." server) (def-kom-var kom-use-button-hints t "**Controls use of context sensitive actions on clickable areas. When set to `t', clickable areas of the same type may behave differently depending on what command created them. For example, in one case clicking a conference name may show the presentation of that conference and in another it will go to the conference. Values other than `t' and `nil' are reserved for future use.") (def-kom-var kom-autowrap t "**Controls automatic text wrapping. When set to `t', automatically break long lines in texts. A set of rules attempts to limit line breaking to regular, unformatted text. This works most of the time, but occasionally fails (in which case `kom-review-noconversion' comes in handy). When set to an integer, perform automatic line breaking in text no longer than that many characters. When set to `nil', do not break lines automatically at all. Values other than `t', `nil' and integers are reserved for future use." server) (def-kom-var kom-autowrap-timeout 5 "**Limits how much time automatic text wrapping may take. When set to an integer, limits the number of seconds automatic line breaking may take. Without a limitation, breaking lines of a very long text can take a very, very long time. Note that this setting is approximate; the actual time spent breaking lines may be several seconds longer than this value. Furthermore, using this setting slows down all text display slightly. When set to `nil', do not limit the amout of time automatic line breaking may take. Values other than `nil' and integers are reserved for future use." server) (def-kom-var kom-keep-alive-interval 180 "**Polling interval for `kom-keep-alive'. The command `kom-keep-alive' polls the server periodically to keep the connection active. This variable specifies how many seconds to wait between these periodic requests to the server. Values other than integers are reserved for future use." server) (defvar lyskom-transforming-external-text nil "Dynamically bound to non-nil when transforming text in which text, conference and person buttons are not expected.") (def-kom-var lyskom-url-protocol-regexp "\\(file\\|ftp\\|gopher\\|http\\|https\\|news\\|wais\\|mailto\\|telnet\\):" "Regexp to match the protocol part of a URL.") (def-kom-var lyskom-text-buttons '( ;; Text numbers ("\\(\\<[0-9][0-9][0-9][0-9]\\([0-9]\\)?\\([0-9]\\)?\\([0-9]\\)?\\([0-9]\\)?\\([0-9]\\)?\\>\\)" ; Match text ; Button type 0 ; Portion that's a button 1 ; Portion that's the arg nil ; Face or nil (=default) ) ;; Email ("\\(\\b\\|^\\)[^()<>@,;:\"\\\\\000- ]+@[^\000- <>;,.'\"!:?) \t\012\014]+\\(\\.[^\000- <>;,.'\"!:?)]+\\)+" email 0 0 kom-url-face) ;; URLs ("\\b\\(www\\|ftp\\|home\\)\\.[^\t \012\014\"<>|\\]*[^][\t \012\014\"<>|.,!(){}?'`:;]" pseudo-url 0 nil kom-url-face) ("\\(file://\\|ftp://\\|gopher://\\|rtsp://\\|http://\\|https://\\|news:\\|wais://\\|mailto:\\|telnet:\\)[^\t \012\014\"<>|\\]*[^][\t \012\014\"<>|.,!(){}?'`:;]" url 0 nil kom-url-face) ("]+\\)>" pseudo-url 1 1 kom-url-face lyskom-is-url) ("<\\([^<>]+\\)>" pseudo-url 1 1 kom-url-face lyskom-is-url) ;; JySKom enhancements ("<(?m[|ö]te[ \t\n\r]*\\([0-9]+\\)\\([^0-9>]?\\|[^0-9>][^>]*\\))?>" conf 0 1 nil) ("<(?text[ \t\n\r]*\\([0-9]+\\)\\([^0-9>]?\\|[^0-9>][^>]*\\))?>" text 0 1 nil) ("<(?person[ \t\n\r]*\\([0-9]+\\)\\([^0-9>]?\\|[^0-9>][^>]*\\))?>" pers 0 1 nil) ;; Info node reference ("\\*Note[ \n\t]+\\([^:\n]*\\(\n[^:\n]*\\)?\\):\\s-*\\(\\(([^\)]+)\\)?[^.,\t\n]*\\(\n[^.,\t\n]*\\)?\\)[.,\t]" info-node 1 3 kom-url-face) ) "List of buttons to install in the text mass of LysKOM objects. Each element is a list consisting of REGEXP TYPE BUTTON-MATCH BUTTON-ARG-MATCH FACE &optional PRED. REGEXP is the regexp to look for in the text. TYPE is the button type. Valid button types are defined in lyskom-button-actions. BUTTON-MATCH is the number of the parenthesized expression that is the actual button. BUTTON-ARG-MATCH is the number of the expression to be used as the button argument. FACE is the text face to apply to the button, or nil to use the default face. If PRED is given, it is a function that will be passed the matched string; if it returns non-nil, the match is considered valid.") (def-kom-var kom-url-viewer-preferences '("emacs" "windows" "w3") "**Specifies application preferences for opening URLs. This is a list of URL handlers to try when opening a URL. Each handler is associated with a set of protocols. An URL will be opened by the first handler in the list that is associated with the URLs protocol. Value values for elements in the list are: Handler What it does Handles protocols ------------------------------------------------------------------------ \"default\" Use `browse-url' to open URLs All \"windows\" Microsoft Windows default All \"netscape\" Opens URLs in Netscape/Mozilla All \"mosaic\" Opens URLs in NCSA Mosaic All common \"lynx\" Opens URLs in Lynx All common \"galeon\" Opens URLs in Galeon All common \"w3\" Opens URLs in Emacs W3 http,gopher,ftp \"emacs\" Opens URLs in Emacs ftp,telnet,file,mailto \"dired\" Opens URLs in Emacs ftp,file \"telnet-mode\" Opens URLs in Emacs telnet \"mail-mode\" Opens URLs in Emacs mailto ------------------------------------------------------------------------ The variable `kom-url-managers' contains a list of all handlers. See `kom-mosaic-command', `kom-netscape-command', `kom-galeon-command', `kom-lynx-terminal-command', `kom-lynx-xterm-command', and `kom-windows-browser-command' for additional settings that affect opening URLs." server) (def-kom-var kom-url-managers '(("default" ".*" "Browse-URL" lyskom-view-url-browse-url) ("w3" "\\(http\\|gopher\\|ftp\\)" "Emacs W3" lyskom-view-url-w3) ("windows" ".*" "web browser" lyskom-view-url-windows) ("netscape" ".*" "Netscape Navigator/Mozilla" lyskom-view-url-netscape) ("\\(emacs\\|dired\\)" "\\(ftp\\|file\\)" "dired" lyskom-view-url-dired) ("\\(emacs\\|telnet-mode\\)" "telnet" "emacs telnet" lyskom-view-url-telnet) ("\\(emacs\\|mail-mode\\)" "mailto" "mail-mode" lyskom-view-url-mailmode) ("mosaic" "\\(http\\|gopher\\|ftp\\|mailto\\|news\\|wais\\|file\\|telnet\\)" "NCSA Mosaic" lyskom-view-url-mosaic) ("lynx" "\\(http\\|gopher\\|ftp\\|mailto\\|news\\|wais\\|file\\|telnet\\)" "Lynx" lyskom-view-url-lynx) ("galeon" "\\(http\\|gopher\\|ftp\\|mailto\\|news\\|wais\\|file\\|telnet\\)" "Galeon" lyskom-view-url-galeon)) "List of URL managers. Each element is a list consisting of \(MANAGER-REGEXP PROTOCOLS NAME VIEW-FUNCTION). When LysKOM attempts to view a URL, kom-url-viewer-preferences is scanned, and the URL -manager whose MANAGER-REGEXP first matches an element in kom-url-viewer-preferences and whose PROTOCOLS matches the protocol of the selected URL is used to view the URL by calling its VIEW-FUNCTION with the URL and the manager entry as arguments.") (def-kom-var kom-windows-browser-command "" "**Program to open a URL in Windows. If it is the empty string, a couple of commands that are likely to work on Windows will be tried." server) (def-kom-var kom-mosaic-command "/usr/local/bin/mosaic" "**Command to run Mosaic. Note that Mosaic uses its own special conventions to open URLs remotely that are probably not suitable for other browsers." server) (def-kom-var kom-netscape-command "netscape" "**Command to start Netscape or Mozilla. If set to a string, it should be a command that starts Netscape or Mozilla with no arguments. If a list, the first element must be a command that starts Netscape. The remaining elements are used as arguments to Netscape. For instance, a value of \"netscape\" is valid, but \"netscape -d host:0\" is not. Instead, the latter should be \(\"netscape\" \"-d\" \"host:0\"\)" server) (def-kom-var kom-netscape-variant nil "**Netscape-specific options. When set to `nil', open URLs in whatever window Netscape or Mozilla chooses. Usually an old window is recycled. When set to `new-window', open URLs in a new window. When set to `new-tab', open URLs in a new tab. These options may not work with all versions of Netscape or Mozilla, or on all operating systems. Values other than those listed above are reserved for future use." server) (def-kom-var kom-galeon-command "galeon" "**Command used to run to start Galeon. If a string, it should be a command that starts Galeon with no arguments. If a list, the first element must be a command that starts Galeon. The remaining elements are used as arguments to Galeon. For instance, a value of \"galeon\" is valid, but \"galeon --display host:0\" is not. Instead, the latter should be \(\"galeon\" \"--display\" \"host:0\"\)" server) (def-kom-var kom-lynx-terminal 'xterm "**Where to start Lynx when opening URLs. Valid values are `xterm' \(start Lynx in an xterm) and `terminal' \(start Lynx in Emacs terminal mode)." server) (def-kom-var kom-lynx-xterm-command '("xterm" "-geometry" "90x50+100+100" "-e" "lynx") "**Command to run to start Lynx in an xterm. Must be a list of strings, where the first element is the name of the xterm program, and the remaining elements are arguments to the xterm. The last elements should be \"-e\" \"lynx\", or something similar, to start Lynx." server) (def-kom-var kom-lynx-terminal-command "lynx" "**Command to run Lynx in Emacs terminal mode. This can be either a string, to start Lynx with no arguments, or a list of strings, where the first element is the command, and the rest are arguments to Lynx." server) (def-kom-var kom-confirm-multiple-recipients 'after "**Non-nil means ask the user for confirmation about recipients. When the user writes a comment to a text with more than one recipient, ask for confirmation that all recipients are relevant, or one question for each recipient. If this variable is set to `before', ask once for each recipient before opening the edit buffer. If this variable is set to `after', ask once for all recipients after editing the text. This is the preferred value since it is difficult to judge the relevance of a recipient until the text has been written. Values other than those listed are reserved for future use." common confirm-multiple-recipients boolean) (def-kom-var kom-check-for-new-comments t "**Controls check for new comments when writing comments. When posting a comment, the client can check if the text being commented has unread comments. This frequently happens when several people attempt to answer the same question at the same time. If this variable is set to `t' check for new comments before posting a comment. If there are new comments, ask for confirmation before posting. If this variable is `nil', dont' check. If this variable is set to a function name, call the function to see if check should be performed. The function is called with the commented text's text-stat as its sole argument. If it returns non-nil, the check is performed. A list of conference numbers means perform the check for all conferences other than those listed. All other values are reserved for future use." server) (def-kom-var kom-check-commented-author-membership t "**Controls check that authors of commented texts will see a new comment. When writing a comment, the client can check that the author of the commented text is a member of at least one of the recipients. If that is not the case, the user will be offered to add the author as a recipient. If this variable is set to `t', perform the check. If not, don't perform the check. See `kom-dont-check-commented-authors' for a way to exclude certain authors from this check. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-inhibit-typeahead nil "**Controls how command typed while the client is busy are handled. When this variable is set to `t', input that arrives while a command is running will be discarded before the next prompt is shown. When set to `nil', that input will be handled normally. If you find yourself accidentally executing commands, it may make sense to set this variable to `t'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-max-buffer-size nil "**Controls the maximum size of the LysKOM buffer. When this variable is set to an integer, limit the size of the LysKOM buffer to that many characters. When set to `nil', don't limit the buffer size. Before anything is deleted, `lyskom-trim-buffer-hook' (note that this hook variable will probably be renamed in the future). Also see `kom-trim-buffer-minimum' for more information. Values other than `nil' and positive integers are reserved for future use." server) (def-kom-var kom-trim-buffer-minimum 4096 "**The amount of text to trim from the buffer when limiting its size. To avoid cutting tiny bits from the top of the buffer all the time, delete this many bytes (rounded to a whole line) from the buffer at a time. See `kom-max-buffer-size' for information on how to limit the buffer size. Values other than positive integers are reserved for future use." server) (def-kom-var kom-print-relative-dates t "**Controls display of relative dates. When set to `t', print today's date as \"today\" and yesterday's as \"yesterday\" in most places. When set to `nil', print all dates using the default numeric format. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-print-seconds-in-time-strings nil "**Controls display of seconds in timestamps. When set to `t', display many timestamps with seconds. When set to `nil', only show hours and minutes. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-show-namedays nil "**Controls display of namedays. When this variable is set to a non-nil value,`kom-display-time' can display names of the day. If set to `t', show the namedays for the currently selected languag \(if there are any). If set to a symbol, that symbol should indicate a list of names (use `kom-list-nameday-lists' to see a list of all possible lists). If set to a list, each element should be a symbol indicating a list of names; display namedays from all indicated lists. All values other than those listed are reserved for future use." server) (def-kom-var kom-ssh-relay-host nil "**Controls relay of LysKOM sessions through ssh. It is possible to automatically tunnel LysKOM sessions through ssh. For this to work you need to have command-line ssh installed, and connecting to the remote host indicated by this variable must succeed without asking for a password or passphrase. This variable, when set to a string, enables tunneling ssh to the host indicated by the value of this variable. Note that storing this variable in the LysKOM server makes no sense. See `kom-ssh-command' for additional configuration options. Values other than strings are reserved for future use.") (def-kom-var kom-ssh-command "ssh" "**Command to start ssh. This variable should be set to a command that runs ssh. Note that it is not possible to specify command-line arguments using this variable. See `kom-ssh-relay-host' for more information. Non-string values are reserved for future use.") (def-kom-var lyskom-ssh-proxy nil "When non-nil, the ssh proxy used for this buffer." local protected) (def-kom-var kom-www-proxy nil "**Controls use of an HTTP proxy for the LysKOM session. When this variable is set to a string, it should be the host name of an HTTP proxy that supports the CONNECT method. All LysKOM sessions will be transparently tunneled through this proxy. When set to a list, each element must be a pair \(`SERVER' . `PROXY'), where `SERVER' is a LysKOM server and `PROXY' is the proxy to use for that server (or `nil' to not use a proxy). The special value `t' for `SERVER' indicates the proxy to use for unlisted servers. The proxy string has the form \"`HOST':`PORT'\", where `HOST' is the proxy host and `POSRT' is the port on which the proxy is running. The port part is optional. If it is not specified, port 80 is assumed. Values other than those described are reserved for future use.") (def-kom-var kom-www-proxy-headers "User-Agent: Mozilla/4.7C-CCK-MCD [en] (X11; I; SunOS 5.6 sun4u)" "**Extra HTTP headers to use when connecting through a Proxy. The value of this variable should either be a single string, which is sent verbatim to the proxy, or a list of strings which will be sent to the proxy separated by CRLF, or a list of elements like \(`NAME' `H1' `H2' ... `Hn') where `NAME' is the name of a proxy and the remaining elements are headers to send when connecting through that proxy. Do not use this variable for proxy authentication. Values other than those listed are reserved for future use.") (def-kom-var kom-server-aliases nil "**An alist mapping server names to shorter identification strings. Each value in this string should be of the form \(`SERVER' . `NICKNAME'), where `NICKNAME' is the short name for the server `SERVER'. You can set this in init files before loading LysKOM. See `kom-builtin-server-aliases' for more information. Values other than those described are reserved for future use.") (def-kom-var kom-builtin-server-aliases '(("kom.lysator.liu.se" . "LysKOM") ("com.lysator.liu.se" . "LysCOM (LysKOM in English)") ("kom.ludd.luth.se" . "LuddKOM") ("kom.hem.liu.se" . "RydKOM") ("kom.update.uu.se" . "UppKOM") ("kom.mds.mdh.se" . "MdS-KOM") ("kom.stacken.kth.se" . "TokKOM") ("com.helsinki.fi" . "HesaKOM") ("kom.cd.chalmers.se" . "CD-KOM") ("community.roxen.com" . "Roxen Community KOM") ("kom.ds.hj.se" . "DSKOM") ("kom.sno.pp.se" . "SnoppKOM") ("myskom.kfib.org" . "MysKOM")) "**An alist mapping server names to shorter identification strings. Each value in this string should be of the form (`SERVER' . `NICKNAME'), where `NICKNAME' is the short name for the server `SERVER'. Avoid setting this variable since that will override the list compiled into the client. Use `kom-server-aliases' instead. Values other than those described are reserved for future use.") (def-kom-var kom-ansaphone-on nil "*'Controls automatic replies to personal messages. When set to `t', send automatically send replies to personal messages. See `kom-ansaphone-replies' and `kom-ansaphone-default-reply' for ways to configure the replies to send. When set to `nil', don't send automatic replies. This can be set temporarily with `kom-toggle-auto-reply'. The reply message can be changed temporarily with `kom-change-auto-reply'. Values other than `t' and `nil' are reserved for future use." local) (def-kom-var kom-silent-ansaphone nil "**Controls beeps when automatic replies are enabled. When set to `t', don't beep or otherwise signal receipt of personal messages while automatic replies are enabled (see `kom-ansaphone-on'). When set to `nil', signal receipt of personal messages as usual. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-ansaphone-record-messages t "**Controls recording of personal messages while automatic replies are on. When set to `t', record personal messages that are received while automatic replies are on. Recorded messages can be listed with `kom-list-messages' and erased with `kom-erase-messages'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-ansaphone-show-messages t "**Controls display or personal messages while automatic replies are on. When set to `t', personal messages received while automatic replies are enabled will be shown as usual. When set to `nil' the will not be shown. Note that if this variable is set to `nil' and `kom-ansaphone-record-messages' is also set to `nil', messages are simply discarded. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var lyskom-ansaphone-messages nil "Messages collected by the automatic reply facility. The most recent message is the first message in the list." local) (def-kom-var lyskom-ansaphone-when-set (current-time-string) "Time when the auto-reply facility was enabled." local) (def-kom-var kom-remote-control t "**Enables and disable remote control. When this is set to `t', it will be possible to control the client from other sessions using `kom-remote-autoreply', `kom-remote-list-messages', `kom-remote-set-message', `kom-remote-erase-messages' and `kom-remote-quit' (and possibly others in the future). When set to `nil', remote control is disabled. See `kom-remote-controllers' and `kom-self-control' for ways to control access through remote control. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-remote-controllers nil "**List of people who may use remote control. This should be `nil' or a list of person numbers. The persons listed may control the session using remote control commands (see `kom-remote-control' for more information). See `kom-self-control' for another variable that affects remote control. Values other than `nil' and a list of persons are reserved for future use." server) (def-kom-var kom-self-control t "**Enable or disable remote control for the logged-in user. When set to `t', the user who is currently logged in may control the session remotely from sessions that where the same user is logged in. When set to `nil', only permit users listed in `kom-remote-controllers'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-ansaphone-replies '((group nil nil nil nil) (common nil nil nil nil)) "**List of automatic replies to various messages. This variable determines non-default automatic replies to personal messages. Automatic replies are only send when `kom-ansaphone-on' is set to `t'. The value of this variable is a list of rules. Each rule is a list with five elements: `MESSAGE-TYPE', `SENDER', `RECIPIENT', `TEXT', and `REPLY'. Incoming messages are compared against these rules in order. A message matches a rule if it matches all non-nil elements of the rule. If `MESSAGE-TYPE' is non-nil, match against the message type. Valid values are `personal', `group' and `common' (for alarm messages). If `SENDER' is non-nil, match against the message sender. The value is either an integer (a person number) or a list of person numbers. A message matches if its sender is any of the listed persons. If `RECIPIENT' is non-nil, match against the message recipient. The value is either an integer (a conference number) or a list of conference numbers. A message matches if its recipient is any of the listed conferences. If `TEXT' is non-nil, match against the message text. The value is a regular expression. A message matches if it contains a match for the regular expression. If all non-nil components of a rule match, rule processing is terminated. If `REPLY' is a string, send that string as the reply. If `REPLY' is `nil', don't send a reply. If all rules are processed without finding a match, the value of `kom-ansaphone-default-reply' is sent. The default value for this variable disables automatic replies to all group and alarm messages." server) (def-kom-var kom-agree-text nil "**Determines the text used in `kom-agree'. When non-nil, this is the default text for `kom-agree'. The value may be a string, which is used verbatim as the default text; a function, which is called and should return a text to use; or a list whose elements must be strings, functions or lists, and from which an element will be chosen at random and used in the same manner as `kom-agree-text' itself. Values other than those described are reserved for future use." server) (def-kom-var kom-default-language nil "**The default language for LysKOM. When set to non-nil, this variable should be set to a list of symbols or a symbol indicating the prefered language(s) for LysKOM. Each symbol name must be the ISO 630 code for a desired language (e.g. `sv' for Swedish and `en' for English). Available languages depend on how LysKOM was built. All valid choices are listed in `lyskom-languages'." common language symbol-list transition (lambda (x) (cond ((listp x) x) (t (list x)))) inherited protected) (def-kom-var lyskom-language kom-default-language local inherited minibuffer protected "The language currently in use for messages.") (def-kom-var lyskom-global-language kom-default-language "The language for language-specific things that affect multiple sessions.") (def-kom-var lyskom-edit-mode-map nil "Mode map for LysKOM edit." local) (def-kom-var lyskom-edit-prefix nil "Mode map for LysKOM edit mode.") (def-kom-var lyskom-customize-map nil "Keymap for the customize buffer" local) (def-kom-var lyskom-command-alternatives nil "Possible command completions." local minibuffer) ;;; ================================================================= ;;; ;;; Language-dependent variables ;;; (def-kom-var lyskom-month-names nil "A list of month names. Each element is a cons cell consisting of the name of the month \(a symbol) and the number of the month (1-12). Each month may appear more than once, but the first occurence should be the preferred name of the month." local inherited language-force) (def-kom-var lyskom-help-data nil "Help strings." local language-force) (def-kom-var lyskom-onoff-table nil "A completion table for on and off selections." local language-force) (def-kom-var lyskom-move-tree-actions nil "A completion table for actions in kom-move-text-tree" local language-force) (def-kom-var lyskom-language-codes nil "A list of ISO 639 language codes" local language-force) (def-kom-var lyskom-filter-predicate-list nil "A list of legal filter comparison predicates." local language-force) (def-kom-var lyskom-filter-what nil "A list of legal filter conditions and their textual representation." local language-force) (def-kom-var lyskom-filter-actions nil "A list of legal filter actions an their textual representation." local language-force) (def-kom-var lyskom-filter-edit-map nil "Keymap for LysKOM filter edit." local) (def-kom-var lyskom-prioritize-mode-map nil "Keymap used in lyskom-prioritize-mode." local) (def-kom-var kom-ansaphone-default-reply nil "**Default message to send when automatic replies are on. The value of this variable must be a string or `nil'. When set to `nil', no automatic replies are generated. See `kom-ansaphone-replies' for a more flexible way of specifying automatic replies. Values other than strings ans `nil' are reserved for future use." server) (def-kom-var kom-ispell-dictionary nil "**Dictionary to use for spell checking. When spell checking is used when writing texts, this variable can be used to specify an alternate dictionary. When set to `nil', use the default dictionary. When set, it should be set to a string indicating the alternate dictionary (see `ispell-dictionary'). Values other than `nil' and strings are reserved for future use." server inherited) (def-kom-var lyskom-unread-mode-line nil "This variable will become part of mode-line-format" language-force) (def-kom-var lyskom-unread-title-format nil "This variable will become part of frame-title-format" language-force) (def-kom-var lyskom-button-actions '((text text-popup-title lyskom-button-view-text ((lyskom-button-view-text-action . lyskom-button-view-text) (lyskom-button-unread-text-action . lyskom-button-unread-text) (lyskom-button-copy-text-no-action . lyskom-button-copy-text-no) (lyskom-button-review-noconversion-action . lyskom-button-review-noconversion) (lyskom-button-review-converted-action . lyskom-button-review-converted) (lyskom-button-review-rot13-action . lyskom-button-review-rot13) (lyskom-button-find-root-review-action . lyskom-button-find-root-review) (lyskom-button-find-root-action . lyskom-button-find-root) (lyskom-button-review-comments-action . lyskom-button-review-comments) (lyskom-button-review-tree-action . lyskom-button-review-tree) (lyskom-button-comment-text-action . lyskom-button-comment-text) (lyskom-button-private-comment-text-action . lyskom-button-private-comment-text) (lyskom-button-write-footnote-action . lyskom-button-write-footnote) (lyskom-button-fast-reply-action . lyskom-button-fast-reply) (lyskom-button-mark-text-action . lyskom-button-mark-text) (lyskom-button-unmark-text-action . lyskom-button-unmark-text) (lyskom-button-save-text-action . lyskom-button-save-text) (lyskom-button-save-text-body-action . lyskom-button-save-text-body) ) nil ;; ((nil lyskom-print-text footer lyskom-button-comment-text)) ) (conf conf-popup-title lyskom-button-view-conf-presentation ((lyskom-button-view-conf-presentation-action . lyskom-button-view-conf-presentation) (lyskom-button-view-conf-status-action . lyskom-button-view-conf-status) (lyskom-button-goto-conf-action . lyskom-button-goto-conf) (lyskom-button-send-message-action . lyskom-button-send-message) (lyskom-button-add-self-action . lyskom-button-add-self) (lyskom-button-sub-self-action . lyskom-button-sub-self)) ((kom-list-news . lyskom-button-goto-conf) (kom-membership . lyskom-button-goto-conf))) (pers pers-popup-title lyskom-button-view-pers-presentation ((lyskom-button-view-pers-presentation-action . lyskom-button-view-pers-presentation) (lyskom-button-view-pers-status-action . lyskom-button-view-pers-status) (lyskom-button-view-session-status-action . lyskom-button-view-session-status) (lyskom-button-mail-action . lyskom-button-mail) (lyskom-button-send-message-action . lyskom-button-send-message)) ((kom-list-news . lyskom-button-goto-conf) (kom-membership . lyskom-button-goto-conf))) (url url-popup-title lyskom-button-open-url ((lyskom-button-open-url-action . lyskom-button-open-url) (lyskom-button-copy-url-action . lyskom-button-copy-url)) nil) (info-node generic-popup-title lyskom-button-goto-info-node ((lyskom-button-goto-info-node-action . lyskom-button-goto-info-node)) nil) (email generic-popup-title lyskom-button-open-email ((lyskom-button-open-email-action . lyskom-button-open-email) (lyskom-button-copy-email-action . lyskom-button-copy-email)) nil) (aux aux-popup-title lyskom-button-info-aux ((lyskom-button-info-aux-action . lyskom-button-info-aux) (lyskom-button-delete-aux-action . lyskom-button-delete-aux)) nil) (aux-edit-menu nil nil ((lyskom-edit-toggle-secret-aux-action . lyskom-edit-toggle-secret-aux) (lyskom-edit-toggle-anonymous-aux-action . lyskom-edit-toggle-anonymous-aux) (lyskom-edit-toggle-inherit-aux-action . lyskom-edit-toggle-inherit-aux) (lyskom-edit-delete-aux-action . lyskom-edit-delete-aux)) nil) (prioritize-flag-menu nil lyskom-prioritize-flag-toggle ((lyskom-prioritize-flag-toggle-action . lyskom-prioritize-flag-toggle) (lyskom-prioritize-flag-set-action . lyskom-prioritize-flag-set) (lyskom-prioritize-flag-clear-action . lyskom-prioritize-flag-clear)) nil) (func nil lyskom-button-apply nil nil) (timestamp timestamp-popup-title (lambda (buffer argument text) nil) ((lyskom-button-copy-timestamp-action . lyskom-button-copy-timestamp)) nil) (recpt-type recpt-type-popup-title (lambda (buffer argument text) nil) ((lyskom-button-recpt-type-recipient . (lambda (buffer recpt-and-buffer text) (lyskom-edit-do-add-recipient/copy 'RECPT (car recpt-and-buffer) (car (cdr recpt-and-buffer))))) (lyskom-button-recpt-type-copy . (lambda (buffer recpt-and-buffer text) (lyskom-edit-do-add-recipient/copy 'CC-RECPT (car recpt-and-buffer) (car (cdr recpt-and-buffer))))) (lyskom-button-recpt-type-bcc . (lambda (buffer recpt-and-buffer text) (lyskom-edit-do-add-recipient/copy 'BCC-RECPT (car recpt-and-buffer) (car (cdr recpt-and-buffer))))) (lyskom-button-recpt-type-sub . (lambda (buffer recpt-and-buffer text) (lyskom-edit-sub-recipient/copy (car recpt-and-buffer) (car (cdr recpt-and-buffer))))))) (add-recipient-or-xref add-recipient-or-xref nil ((lyskom-button-recpt-add-recipient . (lambda (buffer buffer text) (set-buffer buffer) (kom-edit-add-recipient))) (lyskom-button-recpt-add-copy . (lambda (buffer buffer text) (set-buffer buffer) (kom-edit-add-copy))) (lyskom-button-recpt-add-bcc . (lambda (buffer buffer text) (set-buffer buffer) (kom-edit-add-bcc))) (lyskom-button-aux-type-xref . (lambda (buffer recpt-and-buffer text) (save-excursion (set-buffer recpt-and-buffer) (kom-edit-add-cross-reference)))) (lyskom-button-aux-type-no-comments . (lambda (buffer recpt-and-buffer text) (save-excursion (set-buffer recpt-and-buffer) (kom-edit-add-no-comments)))) (lyskom-button-aux-type-personal-comments . (lambda (buffer recpt-and-buffer text) (save-excursion (set-buffer recpt-and-buffer) (kom-edit-add-personal-comments)))))) ) "This variable defines valid button types in LysKOM. Each element is a list consisting of (TYPE LABEL DEFAULT ACTIONS HINTS). TYPE is the button type the entry defines LABEL is a textual representation for the button type, used in menu titles. If it is a symbol, that symbol will be looked up using lyskom-get-string. DEFAULT is the default action to take on a click. It must be a function. ACTIONS are other possible actions. The format of this entry is described below. HINTS is a list of hints to override the default action. This is described below. The ACTIONS entry is used to construct a pop-up menu. It is a list consisting of lists with the format (STRING . FUNCTION). STRING is the menu label and FUNCTION is the function to call when the menu item is selected. The HINTS entry is used to generate hints that the default action should be overridden. It is a list containing elements (COMMAND . HINT) where COMMAND is as interactive LysKOM command and HINT is a function to call. When a button is generated while the command COMMAND is being executed, HINT is used as a hint for a new default action. The user has the option to ignore or used the hint. Also see the function \"lyskom-add-button-action\"." local inherited) (def-kom-var kom-show-imported-envelope-sender t "**Controls display of envelope sender of imported e-mails. When set to `t', dispaly the envelope sender of imported e-mails (if the importer has recorded such information). `kom-show-imported-envelope-sender' set to `t': < 2912231 today 10:07 +0100 /41 lines/ Super-User Sent by: root@meat.spareribs.com Imported: today 00:07 by Mailman External recipient: BBQ <531@kom.meat.com> > `kom-show-imported-envelope-sender' set to `nil': < 2912231 today 10:07 +0100 /41 lines/ Super-User Imported: today 00:07 by Mailman External recipient: BBQ <531@kom.meat.com> > Other variables that control display of imported e-mail include `kom-show-imported-importer' and `kom-show-imported-external-recipients'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-show-imported-importer t "**Controls display of the importer name in imported mail. When set to `t', display information about what imported the e-mail \(if the importer has recorded such information). When set to `nil', don't. `kom-show-imported-importer' set to `t': < 2912231 today 10:07 +0100 /41 lines/ Super-User Imported: today 00:07 by Mailman External recipient: BBQ <531@kom.meat.com> > `kom-show-imported-importer' set to `nil': < 2912231 today 10:07 +0100 /41 lines/ Super-User External recipient: BBQ <531@kom.meat.com> > Other variables that control display of imported e-mail include `kom-show-imported-importer' and `kom-show-imported-external-recipients'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-show-imported-message-id nil "**Controls display of the message id in imported mail. When set to `t', display the message id of the imported e-mail. When set to `nil', don't. `kom-show-imported-message-id' set to `t': < 2912231 today 10:07 +0100 /41 lines/ Super-User Message-ID: External recipient: BBQ <531@kom.meat.com> > `kom-show-imported-message-id' set to `nil': < 2912231 today 10:07 +0100 /41 lines/ Super-User External recipient: BBQ <531@kom.meat.com> > Other variables that control display of imported e-mail include `kom-show-imported-envelope-sender', `kom-show-imported-importer' and `kom-show-imported-external-recipients'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-show-imported-external-recipients t "**Controls display of external recipients of imported e-mail. When set to `t', display all external recipients of each imported e-mail (the to and cc headers). When set to `nil', don't display these headers. `kom-show-imported-external-recipients' set to `t': < 2912231 today 10:07 +0100 /41 lines/ Super-User Imported: today 00:07 by Mailman External recipient: BBQ <531@kom.meat.com> External recipient: \"Mac the Hack\" > `kom-show-imported-external-recipients' set to `nil': < 2912231 today 10:07 +0100 /41 lines/ Super-User Imported: today 00:07 by Mailman > Other variables that control display of imported e-mail include `kom-show-imported-envelope-sender', `kom-show-imported-importer' and `kom-show-imported-message-id'. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-complete-numbers-before-names t "**Controls completion of numeric person and conference names. When set to `t', reading conference and user names accepts the special forms \"m 4711\" or \"p 42\" as numeric references to conference 4711 and person 42 instead of trying to look for an object with a matching name. If `nil', any name matching the input will be preferred to a numeric reference. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-mercial nil "**What you are doing when you're done reading. The value of this variable should be a string. This string is sent to the server as the user's current activity when everything is read. Users are encouraged to use their best sense of humor." server) (defconst lyskom-commands-not-in-menu '( kom-unread-previous-commented-text kom-create-aux-item kom-become-nonanonymous kom-become-anonymous kom-send-alarm kom-get-abuse kom-get-appreciation kom-list-clients kom-view-previous-commented-text kom-membership kom-delete-text kom-quick-mode kom-slow-mode kom-busy-wait kom-comment-previous kom-private-answer-previous kom-change-language ) "Commands that are not supposed to appear in menus.") (defconst lyskom-commands '( kom-help kom-slow-mode kom-quick-mode kom-send-message kom-create-conf kom-delete-conf kom-delete-text kom-display-time kom-go-to-conf kom-go-to-next-conf kom-jump kom-list-created-conferences kom-list-conferences kom-list-persons kom-list-news kom-list-re kom-list-sessions kom-membership kom-list-marks kom-postpone kom-set-session-priority kom-prioritize kom-status-person kom-status-conf kom-add-self kom-change-priority kom-list-summary kom-sub-self kom-quit kom-recover kom-start-anew kom-view kom-find-root-review kom-review-comments kom-review-tree kom-review-cross-references kom-review-clear kom-review-last-normally-read kom-review-noconversion kom-review-converted kom-review-rot13 kom-review-next kom-find-root kom-review-by-to kom-review-more kom-review-first kom-review-all kom-view-commented-text kom-view-previous-commented-text kom-review-stack kom-review-presentation kom-review-backward kom-view-next-text kom-who-is-on kom-who-is-on-in-conference kom-who-is-on-and-friend kom-who-am-i ;; kom-display-who-buffer kom-list-clients kom-busy-wait kom-write-comment kom-comment-previous kom-write-footnote kom-private-answer kom-private-answer-previous kom-set-unread kom-write-text kom-send-letter kom-change-name kom-change-parenthesis kom-change-password kom-change-supervisor kom-change-presentation kom-get-appreciation kom-get-abuse kom-mark-text kom-unmark-text kom-review-marked-texts kom-review-all-marked-texts kom-add-recipient kom-add-copy kom-add-bcc kom-sub-recipient kom-move-text kom-move-text-tree kom-add-comment kom-sub-comment kom-add-cross-reference kom-add-member kom-sub-member kom-change-conf-motd kom-set-garb-nice kom-set-super-conf kom-set-permitted-submitters kom-unset-conf-motd kom-save-text kom-save-text-body kom-save-options kom-shutdown-server kom-sync-database kom-enable-adm-caps kom-disable-adm-caps kom-set-motd kom-remove-motd kom-force-logout kom-filter-author kom-filter-subject kom-filter-text kom-filter-recipient kom-super-jump kom-filter-edit kom-list-filters kom-show-user-area kom-change-conf-type kom-change-auto-reply kom-toggle-auto-reply kom-list-messages kom-erase-messages kom-remote-autoreply kom-remote-set-message kom-remote-list-messages kom-remote-erase-messages kom-remote-quit kom-status-session kom-customize kom-change-language kom-calculate kom-where-is kom-next-kom kom-previous-kom kom-next-unread-kom kom-send-alarm kom-agree kom-fast-reply kom-add-faq kom-del-faq kom-review-faq kom-add-footnote kom-sub-footnote kom-add-private-answer kom-add-no-comments kom-add-request-confirm kom-review-mail-headers kom-compare-texts kom-diff-texts kom-become-anonymous kom-become-nonanonymous kom-keep-alive kom-stop-keep-alive kom-who-is-present-in-conference kom-is-person-member-of-conference kom-change-conf-faq kom-make-review-mark-as-read kom-make-review-not-mark-as-read kom-set-presentation kom-set-motd-text kom-remove-presentation kom-create-aux-item kom-status-server kom-add-server-faq kom-del-server-faq kom-change-server-faq kom-review-server-faq kom-recommend-conference kom-redirect-comments kom-copy-options kom-mark-unread kom-unread-by-to kom-unread-last-normally-read kom-unread-root-review kom-unread-root kom-unread-tree kom-unread-comments kom-unread-previous-commented-text kom-unread-commented-text kom-unread-more kom-unread-all kom-unread-first kom-unread-all-marked-texts kom-unread-marked-texts kom-unread-faq kom-unread-server-faq kom-unread-presentation kom-join-all-conferences kom-leave-all-conferences kom-will-person-read-text kom-limit-import kom-change-message-flag kom-list-faqs kom-list-server-faqs kom-list-new-conferences kom-list-new-persons kom-change-privileges )) ;;; ================================================================ ;;; Internal variables and constants (defconst lyskom-clientversion "0.48" "Version of the LysKOM elisp client.") (def-kom-var lyskom-settings-version lyskom-clientversion "Version of saved settings." server) (defvar lyskom-max-int 8388607 "The largest int Emacs, and thus this LysKOM client, can handle.") (def-kom-var lyskom-server-uses-utc nil "When non-nil, assume that the server uses UTC timestamps." inherited local) (defconst lyskom-server-features '((10 lyskom-bcc-flag lyskom-extended-types-flag) (9 lyskom-accept-async-flag lyskom-dynamic-session-info-flag lyskom-idle-time-flag) (8 lyskom-long-conf-types-flag lyskom-set-last-read-flag lyskom-uconf-stats-flag lyskom-set-last-read-flag) (7 lyskom-z-lookup-flag)) "List describing which features a certain server has. Each element is a list containing the protocol version and what it supports. The format of each element is: \(VERSION . SUPPORTS\) Version is simply a protocol version. Protocol equal to or above the version support the supports list. SUPPORTS is a list of pairs and symbols. Cons pairs are treated as arguments to setq, symbols are interpreted as variable names set to 't'.") ;;;(defconst lyskom-server-features ;;; '(((>= 2 0 0) (lyskom-bcc-flag ;;; lyskom-aux-items-flag)) ;;; ((>= 1 9 0) (lyskom-accept-async-flag ;;; lyskom-dynamic-session-info-flag ;;; lyskom-idle-time-flag)) ;;; ((>= 1 8 0) (lyskom-long-conf-types-flag ;;; lyskom-set-last-read-flag ;;; lyskom-uconf-stats-flag)) ;;; ((>= 1 7 0) (lyskom-z-lookup-flag)) ;;; ((= 2 0 0) ((protocol-version 10))) ;;; ((= 1 9 0) ((protocol-version 9))) ;;; ((= 1 8 0) ((protocol-version 8))) ;;; ((= 1 7 0) ((protocol-version 7))) ;;; ((= 1 7 1) ((protocol-version 7))) ;;; ((< 1 7 0) ((protocol-version 6)))) ;;; "List describing which features a certain server version has. ;;;Each element is a list containing the server version and what it ;;;supports: ;;;") (def-kom-var lyskom-server-version '(0 0 0) "The version of the server. A list of three integers: major version, minor version and revision." local) (def-kom-var lyskom-server-coding-system 'iso-8859-1 "The default coding system used by the server for all strings." inherited) (def-kom-var lyskom-current-user-area 0 "Text-no of the user area last saved or read for lyskom-pers-no." local) (def-kom-var lyskom-max-packet-size lyskom-max-int "The largest possible packet size that can be transmitted to a TCP/IP connection. This should be unlimited, but in practise there are systems that limits this. This variable is automatically adjusted if any problems are detected.") (def-kom-var lyskom-pending-commands nil "Commands pending to be executed. When a command finishes, it checks this variable to see if another command should be run. It should be a list where each element should be either a symbol or an expression. If it is a symbol, it is invoked with `call-interactively', and an expression is evaluated with `eval'." local) (def-kom-var lyskom-do-when-done nil "Internal of kom-do-when-done." local) (def-kom-var lyskom-do-when-starting nil "Internal of kom-do-when-starting. Obsolete.") (def-kom-var lyskom-sessions-with-unread nil "List of LysKOM sessions with unread texts. This is not buffer-local.") (def-kom-var lyskom-sessions-with-unread-letters nil "List of LysKOM sessions with unread letters. This is not buffer-local.") (def-kom-var lyskom-session-has-unread-letters nil "Non-nil if this session has unread letters." local protected inherited) (def-kom-var lyskom-session-has-unreads nil "Non-nil if this session has unread texts." local protected inherited) (def-kom-var lyskom-buffer nil "The LysKOM buffer we are connected to." inherited minibuffer) (def-kom-var lyskom-buffer-type nil "Type of the current buffer." local protected) (def-kom-var output nil "Uaark. Just to omit a warning...") (def-kom-var lyskom-errno nil "Errno of last lyskom error." local) (def-kom-var lyskom-err-stat nil "Err-stat of last lyskom error." local) (def-kom-var lyskom-parser-recovering nil "Non-nil if the parser is recovering from an error." local) (def-kom-var lyskom-parse-pos nil "Position of parsing.") (def-kom-var lyskom-unparsed-buffer nil "Buffer containing unparsed information from the server." local) (def-kom-var lyskom-unparsed-marker nil "Where we now are inserting." local) (def-kom-var lyskom-to-be-printed-before-prompt nil "Contains the strings to be printed before the next prompt." local) (def-kom-var lyskom-other-clients-user-areas nil "Contains the parts of the user areas of unknown clients. The area is a pair: name . info (both strings)." local) (def-kom-var lyskom-saved-unknown-variables nil "Variables read from the user area that this client version knows nothing about and that will be saved back unaltered." local) (def-kom-var lyskom-pending-calls nil "Assoc list of calls to LysKOM server that have not yet completed. Each element on the list has the format (REF-NO . KOM-QUEUE) REF-NO unique number assigned by lyskom-send-packet. KOM-QUEUE is a kom-queue. (See lyskom-call-data.)" local) (def-kom-var lyskom-output-queues nil "Pending output to the server. This is a vector of ten elements, each of which is a kom-queue. Calls from queues with a higher index (priority) are always sent first. At most lyskom-max-pending-calls calls are sent at once." local) (def-kom-var lyskom-max-pending-calls 20 "Max number of calls that are transmitted to the server at once. Extra calls are queued in lyskom-output-queue and sent when the replies returns. This variable is not saved in the LysKOM server.") (def-kom-var lyskom-number-of-pending-calls 0 "Number of pending calls that are transmitted to the server." local) ;; This variable is used to prevent "starvation" of the blocking-do call. ;; When there is heavy prefetch going on in the background and a ;; blocking-do call is made there is a good chance that the ;; accept-process-output call will not return within a reasonable ;; time, because there will always be data to read from the server, ;; which means that Emacs will call lyskom-filter instead of returning ;; from accept-process-output. (defvar lyskom-ok-to-send-new-calls t "This variable controls whether calls are passed to the server. If it is nil, all outgoing calls are inhibited.") (def-kom-var lyskom-ref-no 0 "Next ref-no to use. These ref-nos are used to keep track of the different packets.") (def-kom-var lyskom-pers-no 0 "The pers-no of the current user." inherited) (def-kom-var lyskom-session-no 0 "Session number in the server for this connection." local) (def-kom-var kom-default-session-priority 0 "**The default session priority. Tha value of this variable must be an integer. Only texts in conferences with a priority equal to or higher than this will be shown by default. To set the session priority in a running session, use `kom-set-session-priority'. Setting this value directly will have no effect on the actual session priority. Non-integer values are reserved for future use." local server) (def-kom-var kom-server-priority -1 "**The default server priority. The value of this variable must be an integer. When `kom-server-priority-breaks' is set to a non-nil value, this priority is used to decide when to go to a prioritized session. For a session to be prioritized its priority must be higher than the current session's `kom-server-priority' and higher than the priority of whatever conference is currently being read. Non-integer values are reserved for future use." server) (def-kom-var lyskom-session-priority 0 "This sessions priority. Only texts in conferences with a priority equal to or higher than this will be shown." local) (def-kom-var lyskom-proc nil "The process (network connection) that is associated with this buffer." inherited minibuffer) (def-kom-var lyskom-server-info nil "Info about the server." local) (def-kom-var lyskom-server-version-info nil "Version information about the client." local) (def-kom-var lyskom-server-name "" "The name of the server." inherited) (def-kom-var lyskom-server-port nil "The port we are connected to." local) (def-kom-var lyskom-buffer-list nil "List of all LysKOM buffers.") (def-kom-var lyskom-static-session-info-cache nil "Cache of session." local) (def-kom-var lyskom-conf-cache nil "Cache of conference statuses." local) (def-kom-var lyskom-static-server-info nil "Cache of static-server-info" local) (def-kom-var lyskom-stats-description nil "Cache of get-stats-description" local) (def-kom-var lyskom-uconf-cache nil "Cache of small conference statuses." local) (def-kom-var lyskom-pers-cache nil "Cache of person statuses." local) (def-kom-var lyskom-text-cache nil "Cache of text statuses." local) (def-kom-var lyskom-text-mass-cache nil "Cache of texts." local) (def-kom-var lyskom-marked-text-cache nil "Cache of marks of all texts the current user has marked. " local) (def-kom-var lyskom-is-parsing t "True when parsing a result. This is used to prevent parallel parsing since the parser is not reentrant." local) (def-kom-var lyskom-string-bytes-missing 0 "Number of bytes missing in the unparsed buffer when parsing a string. Set when parsing a string and there were not enough bytes in the buffer with the unparsed bytes. This variable is used to prevent reparsing before the string is complete. This variable is buffer-local in the unparsed-buffer." local inherited) (def-kom-var lyskom-last-viewed 0 ; "Position of the first char of the last line that the user has had time to view. This is normally the pos of the first char of the prompt." local) (def-kom-var lyskom-mode-map nil "Keymap used in LysKOM mode." local) (def-kom-var lyskom-reading-list nil "List of articles to read in the current conference. Each element is a read-info. Only one of the elements is of the type CONF. This one is located last in the list (except for the elements of the type REVIEW, REVIEW-TREE or REVIEW-MARK). When reading an article with comments a list of the comments is built recursively if the flag kom-read-depth-first is non-nil. This is to keep track of the reading order. Articles can exist in several of the read-info elements. All unread articles in the conference are always present in the CONF type entry in this list even if also in other entries. (COMM-IN, FOOTN-IN) Some powerful reviewing commands requires to construct a list of articles that should be read. These use the type REVIEW. When reviewing trees and when every viewed article is supposed to be followed by all its comments then the type REVIEW-TREE is used. The first element is a dummy." local) (def-kom-var lyskom-to-do-list nil "List of conferences with unread texts. Each element is a read-info. All have the type 'CONF and there is one for every conference with unread articles that have already been prefetched. The list is sorted in falling priority. When going to a conference the first element (the one with the highest priority) is copied from this list to lyskom-reading-list. The first element is a dummy." local) (def-kom-var lyskom-quit-flag nil "A flag indicating if the filter was interrupted by C-g. It is set to the same value as quit-flag on filter exit.") (def-kom-var lyskom-ignoring-async-list nil "A list of async messages we are currently ignoring. Each element is a list. The car of the list is the message and the remaining elements are whatever is suitable for that type of message. See the checks in lyskom-parse-async for details." local) (def-kom-var lyskom-inhibit-minibuffer-messages nil "A flag indicating whether asynchronous minibuffer messages are allowed. If this variable is non-nil, no asynchronous messages will appear.") (def-kom-var lyskom-is-saving nil "A flag indicating whether the server is saving at the moment.") ;;; These variables control prefetch of conf-stats, text-stats and texts: (def-kom-var lyskom-prefetch-conf-tresh 50 "If fewer than lyskom-prefetch-conf-tresh texts are known, ask for more conf-stats from server. This is currently not used." local) (def-kom-var lyskom-prefetch-confs 10 "Number of confs to ask about at once when checking for unread texts. This is currently not used." local) (def-kom-var lyskom-fetch-map-nos 100 "Number of text-nos lyskom will fetch when fetching maps." local) (def-kom-var lyskom-fetch-membership-length 100 "Number of entries in the membership-list that is fetched at a time.") (def-kom-var lyskom-prefetch-limit 10 "Number of prefetch requests the client will try to keep going at a time.") ;;; (def-kom-var lyskom-unread-confs nil "List containing all unread confs." local) (def-kom-var lyskom-dont-change-prompt nil "Non-nil during the entry of a text." local) (def-kom-var lyskom-command-to-do 'unknown "Atom describing what command to do. See the function lyskom-what-to-do." local) (def-kom-var lyskom-is-waiting nil "If non-nil, this is the condition for the waiting to be stopped. If t, however, it means that the user is waiting for a text with a prompt. It is a form that will be evaluated (using eval) every time the asynchronous message \"new text\" is received. This is used by the command kom-busy-wait." local) (def-kom-var lyskom-current-conf 0 "Current conference. 0 means user is not reading any conf." local) (def-kom-var lyskom-current-text nil "Text-no of current text. nil means no text is current." local) (def-kom-var lyskom-last-written nil "Text-no of last text written. nil means no text written." local) (def-kom-var lyskom-last-seen-written nil "Text-no of last text read or written by the current user. When a new text is written, this is set to the text number of that text. When a text is read that was written by the current user, this is set to that text." local) (def-kom-var lyskom-previous-text nil "Text-no of previous text. Nil means no text." local) (def-kom-var lyskom-normally-read-texts nil "Stack of texts that are read normally. Used for kom-review-last-normally-read." local) (def-kom-var lyskom-current-subject "" "Current subject." local) (def-kom-var lyskom-current-user-area nil "Text-no of user area that current settings come from." local) (def-kom-var kom-saved-file-name (concat default-directory "kom-text") "**The default filename when saving a LysKOM text. This file name is used by `kom-save-text' as the default filename until a new filename has been chosen." server) (def-kom-var lyskom-saved-file-name nil "After saving once, the default file name when saving a LysKOM text." local) (def-kom-var lyskom-mode-hook nil "*'Hook to run when `lyskom-mode' is entered.") (def-kom-var kom-quit-hook nil "**Hook to run when the LysKOM session is ended. This hook is only run when the session ends by using `kom-quit' or `kom-remote-quit'. The hook is not run is the session is forecfully terminated." server-hook) (def-kom-var kom-quit-when-idle t "Controls automatic quitting when LysKOM is full. When set to `t', automatically end the session when LysKOM is full and the session has been idle for a predetermined amount of time. This is currently not implemented.") (def-kom-var kom-permanent-filter-list nil "List of patterns to filter permanently." server) (def-kom-var kom-session-filter-list nil "List of patterns to filter during this session." local) (def-kom-var lyskom-text-no-prompts-defaults '(kom-delete-text kom-view kom-write-footnote kom-mark-text kom-unmark-text kom-add-recipient kom-add-copy kom-add-bcc kom-sub-recipient kom-move-text kom-move-text-tree kom-add-comment kom-sub-comment kom-add-cross-reference kom-save-text-body kom-add-footnote kom-sub-footnote kom-add-faq kom-add-no-comments kom-add-private-answer kom-add-request-confirm kom-add-server-faq kom-mark-unread kom-set-presentation kom-set-motd-text kom-will-person-read-text kom-compare-texts kom-diff-texts ) "Commands that prompt for a text number rather than assume a default." inherited) (def-kom-var kom-text-no-prompts nil "**Determines which commands ask for text numbers. The value of this variable must be a list containing pairs of (`COMMAND' . `VALUE'). If `VALUE' is `t', `COMMAND' will prompt for text numbers. If `VALUE' is nil, `COMMAND' will use a suitable default value." server inherited) (def-kom-var lyskom-filter-list nil "List of patterns that are filtered." local) (def-kom-var kom-create-text-hook nil "**Hook to run before creating a new text. This hook is run just before the server call to create the text is made. The hook is currently called with the following arguments: Argument Contents ---------------------------------------------------------------- `MESSAGE' The message text `MISC-LIST' The misc-info list `AUX-LIST' The aux-item list `BUFFER' The edit buffer `IS-ANONYMOUS' Non-nil if the user is currently anonymous. ---------------------------------------------------------------- Additional arguments may be added in the future, so include `&rest reserved' as the last element of the parameter list. The hook can change the message by modifying the variable `full-message', the misc-info list by modifying `misc-list' and the aux-item list by modifying `aux-list'. This is not encouraged and may break in the future." local-hook) (def-kom-var lyskom-create-text-hook nil "Obsolete synonym for kom-create-text-hook" local-hook) (def-kom-var kom-new-text-hook nil "**Hook to run when a new text is created. This hook is run after the prompt is removed if it shall be changed but before the text \"Text 4711 created\" is printed in the message area and before the new prompt is printed." local-hook) (def-kom-var lyskom-new-text-hook nil "Obsolete synonym for kom-new-text-hook" local-hook) (def-kom-var kom-deleted-text-hook nil "**Hook to run when a text is deleted. This hook is run after the prompt is removed if it shall be changed but before the new prompt is printed." local-hook) (def-kom-var lyskom-deleted-text-hook nil "Obsolete synonym for kom-deleted-text-hook." local-hook) (def-kom-var kom-new-recipient-hook nil "**Hook to run when a text receives a new recipient. This hook is run after the prompt is removed if it shall be changed but before the new prompt is printed. It may not run if the text has been marked as read in any conference other than the person's letterbox." local-hook) (def-kom-var lyskom-new-recipient-hook nil "Obsolete synonym for kom-new-recipient-hook." local-hook) (def-kom-var kom-personal-message-hook nil "**Hook to run when a personal message is received. When the hook is run, `sender' is bound to the conf-stat of the sender of the message (or possibly `nil'), `recipient' is 0 if the message is an alarm message and otherwise the conf-stat of the recipient, and `message' is a string that holds the message." local-hook) (def-kom-var lyskom-personal-message-hook nil "Obsolete synonym for kom-personal-message-hook." local-hook) (def-kom-var lyskom-executing-command t "Non-nil means the client is executing a command. Most commands can't be interrupted by another command." local) (def-kom-var lyskom-current-command nil "The command currently being executed." local) (def-kom-var lyskom-command-point nil "The point where the most recent command was started." local) (def-kom-var lyskom-current-function nil "Sometimes set to the current high-level function being executed." local) (def-kom-var lyskom-current-function-phase nil "Sometimes set to the phase of the current high-level function being executed." local) (def-kom-var lyskom-membership-is-read nil "t when the membership has been read." local) (def-kom-var lyskom-is-writing nil "t when the user is writing a text." local) (def-kom-var lyskom-debug-communications-to-buffer nil "Non-nil means all communications with the server is stored in a buffer. The name is stored in lyskom-debug-communications-to-buffer-buffer.") (def-kom-var lyskom-debug-communications-limit 60000 "When set to an integer limits the communications log to that many bytes. When set to a non-integer, the communications log is unlimited. If a protocol error is detected, this limit will be reset to nil. See lyskom-debug-communications-to-buffer") (def-kom-var lyskom-backtrace-list nil "List containing debugging information.") (def-kom-var lyskom-debug-what-i-am-doing t "Non-nil means asynchronous message 5 will be logged to the debug buffer. ") (def-kom-var lyskom-is-anonymous nil "Non-nil means be a bit secretive about things. Not totally secretive of course, since the server doesn't allow that yet." local) (def-kom-var lyskom-debug-communications-to-buffer-buffer "*kom*-debugs" "Name of the buffer to insert the communications with the server into if lyskom-debug-communications-to-buffer is non-nil.") (def-kom-var lyskom-doing-default-command nil "Non-nil if LysKOM is executing the default command." local) (def-kom-var lyskom-first-time-around nil "Non-nil if LysKOM is being entered for the first time." local) (def-kom-var lyskom-experimental-features nil "If non-nil, LysKOM is likely to blow up in your face." local) (def-kom-var lyskom-format-experimental nil "If non-nil, LysKOM is likely to make a fool out of you." local) (def-kom-var lyskom-count-var 0 "This variable is used for counting things in the client, such as unread texts in list-unread." local) (def-kom-var lyskom-default-conf-string nil "The default string to use for an unknown conference. Set this locally when inserting a conference name using lyskom-format-insert if you want to replace the usual description of an unknown conference.") (def-kom-var lyskom-default-pers-string nil "The default string to use for an unknown person. Set this locally when inserting a conference name using lyskom-format-insert if you want to replace the usual description of an unknown person.") (def-kom-var lyskom-is-administrator nil "This variable is t if the user is in administrator mode and nil otherwise." local minibuffer) (def-kom-var lyskom-last-personal-message-sender nil "Name of sender of last personal message received." local) (def-kom-var lyskom-last-group-message-recipient nil "Name of target for last group message received." local) (def-kom-var lyskom-last-message-recipient nil "Number of last async message recipient sent to." local) (def-kom-var lyskom-is-new-user nil "An internal variable used in kom-start-anew.") (def-kom-var lyskom-apo-timeout-s 1 "Seconds timeout for accept-process-output.") (def-kom-var lyskom-apo-timeout-ms nil "Microseconds timeout for accept-process-output.") (def-kom-var lyskom-collate-table nil "Table mapping characters to an equivalence class." inherited) (def-kom-var lyskom-char-classes nil "An assoc list from character to a list of equivalent strings. See lyskom-compute-char-classes." inherited) (def-kom-var lyskom-dont-read-user-area nil "If non-nil the user area will not be read on login." local) (def-kom-var lyskom-allow-missing-subject nil "If non-nil allow texts without subjects.") (def-kom-var kom-w3-simplify-body t "**Control stripping of color information from HTML. When this variable is set to `t', strip color information from body tags in HTML passed to w3. This is generally a good idea. When `nil', don't strip color information from body tags. This is generally a bad idea. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-format-show-images t "**Controls in-line display of images. When set to `t', attempt to display images in-line. When set to `nil', images are handled as normal texts. Values other than `t' and `nil' are reserved for future use." server) (def-kom-var kom-format-html-authors '((t . t)) "**Determines from which authors we accept HTML. Each element of this list is a pair \(`PERS' . `VAL'), where `PERS' is a person number and `VAL' is `t' or `nil'. If `VAL' is `t', then format HTML written by `PERS'. If `VAL' is `nil', don't. The special value `t' for `PERS' determines the default. Values other than those listed are reserved for future use." server) (def-kom-var lyskom-format-special '(("html" . (lyskom-format-html-w3m lyskom-format-html-w3 lyskom-format-html-plaintext)) ("enriched" . lyskom-format-enriched) ("^image/" . lyskom-format-image) ("^text/html" . (lyskom-format-html-w3m lyskom-format-html-w3 lyskom-format-html-plaintext)) ("^text/enriched" . lyskom-format-enriched) ("^text/" . lyskom-format-plaintext) ("^x-kom/text" . lyskom-format-plaintext) ;Archaic alias for text/x-kom-basic. ("^x-kom/basic" . lyskom-format-plaintext) ;Archaic alias for text/x-kom-basic. ("^x-kom/user-area" . lyskom-format-x-kom/user-area) ("^x-kom/ö\\." . lyskom-format-ö)) "AList of (FORMAT . FUNCTION) specifying functions that format texts of that type. FORMAT is a symbol and FUNCTION is a function taking one argument and returning a formatted string.") (def-kom-var lyskom-send-text-transform-function nil "Function to call to transform text before sending it to the server. The function should accept a single argument and return the transformed texts that is to be sent to the server.") (def-kom-var lyskom-slow-mode nil "Non-nil when in slow mode." local) (def-kom-var lyskom-saved-read-only nil "Saved value of buffer-read-only when in slow mode." local) (def-kom-var lyskom-read-conf-saved-inputs nil "Saved inputs from lyskom-read-conf." local) (defvar lyskom-line-start-chars-string "\"$&'()*+-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]_`abcdefghijklmnopqrstuvwxyz¡£¤¥§©ª«­®±²³µ¶¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ" "Characters that may start a line in a paragraph to be broken.") (def-kom-var lyskom-line-start-chars nil "Computer-friendly version of lyskom-line-start-string.") (def-kom-var lyskom-last-text-format-flags nil "List of flags specifying how the last text was reformatted. This variable should be dynamically bound whenever it needs to be used.") (def-kom-var lyskom-read-faqs nil "List of FAQs that have been read." inherited) (def-kom-var lyskom-rejected-recommendations nil "List of invitations that have been rejected." inherited) (def-kom-var lyskom-last-known-conf-no nil "Last known conference number." server) (def-kom-var lyskom-last-known-pers-no nil "Last known conference number." server) (defvar lyskom-xface-cache (make-vector 29 0)) ;;; ====================================================================== ;;; Event hooks ;;; (def-kom-var lyskom-add-membership-hook nil "Functions to call when a membership is added." local-hook) (def-kom-var lyskom-replace-membership-hook nil "Functions to call when a membership is replaced." local-hook) (def-kom-var lyskom-remove-membership-hook nil "Functions to call when a membership is removed." local-hook) (def-kom-var lyskom-new-membership-list-hook nil "Functions to call when the entire membership list is replaced." local-hook) ;;; ====================================================================== ;;;; lyskom-tell-phrases-validation-keyword-list ;;; This is a list of keywords for kom-tell-phrases. ;;; These are the only keywords that are allowed in kom-tell-phrases. ;;; To coders of the elisp-client: ;;; If you add/delete a reference to any of these keywords make sure ;;; you update these changes. ;;; To everyone: ;;; The kom-tell-phrases list is checked against this list when the ;;; client is loaded, i.e. by lyskom-tell-phrases-validate that causes ;;; an error if any keyword is not present or any non-keyword is ;;; present. (defvar kom-tell-phrases nil "**A list of phrases describing what the client is doing. Each element in the list is a pair \(`KEY' . `PHRASE') where KEY is one of the keywords in `lykom-tell-phrases-validation-keyword-list' and `PHRASE' is the phrase to sent to the server then the client is doing what `KEY' describes. If the value of this variable is `nil', suitable defaults for the currently selected language will be selected.") (defconst lyskom-tell-phrases-validation-keyword-list '( (kom-tell-silence) (kom-tell-send) (kom-tell-login) (kom-tell-read) (kom-tell-1st-pres) (kom-tell-write-comment) (kom-tell-write-footnote) (kom-tell-write-letter) (kom-tell-write-reply) (kom-tell-write-text) (kom-tell-conf-pres) (kom-tell-recover) (kom-tell-wait) (kom-tell-regret) (kom-tell-review) (kom-tell-change-name) (kom-tell-change-supervisor) (kom-tell-next-lyskom) ) "Users must not change this constant, but are encouraged to change the value of kom-tell-phrases for fun.") ;;; ================================================================ ;;; Commands lists that are removed from extended command depending on ;;; administrator status. (defconst lyskom-admin-removed-commands '(kom-enable-adm-caps)) (defconst lyskom-noadmin-removed-commands '(kom-disable-adm-caps kom-remove-motd kom-set-motd kom-shutdown-server kom-sync-database kom-add-server-faq kom-del-server-faq kom-change-server-faq kom-recommend-conference kom-change-privileges)) ;;; ================================================================ ;;; Symbolic error codes (defvar lyskom-error-codes '((no-error . 0) (not-implemented . 2) (obsolete-call . 3) (invalid-password . 4) (string-too-long . 5) (login-first . 6) (login-disallowed . 7) (conference-zero . 8) (undefined-conference . 9) (undefined-person . 10) (access-denied . 11) (permission-denied . 12) (not-member . 13) (no-such-text . 14) (text-zero . 15) (no-such-local-text . 16) (local-text-zero . 17) (bad-name . 18) (index-out-of-range . 19) (conference-exists . 20) (person-exists . 21) (secret-public . 22) (letterbox . 23) (ldb-error . 24) (illegal-misc . 25) (illegal-info-type . 26) (already-recipient . 27) (already-comment . 28) (already-footnote . 29) (not-recipient . 30) (not-comment . 31) (not-footnote . 32) (recipient-limit . 33) (comment-limit . 34) (footnote-limit . 35) (mark-limit . 36) (not-author . 37) (no-connect . 38) (out-of-memory . 39) (server-is-crazy . 40) (client-is-crazy . 41) (undefined-session . 42) (regexp-error . 43) (not-marked . 44) (temporary-failure . 45) (long-array . 46) (anonymous-rejected . 47) (illegal-aux-item . 48) (aux-item-permission . 49) (unknown-async . 50) (internal-error . 51) (feature-disabled . 52) (message-not-sent . 53) (invalid-membership-type . 54) (invalid-range . 55) (invalid-range-list . 56) (undefined-measurement . 57) (priority-denied . 59) (weight-zero . 60) (bad-bool . 61) ) ) ;;; ================================================================ ;;; Externally defined variables (environment) (def-kom-var kom-default-server nil "**Default LysKOM server. Use this server to log in to LysKOM. Can be overridden by the `KOMSERVER' environment variable. The value of this variable must be a string or `nil'." local) (def-kom-var lyskom-default-server nil "**This variable is reserved for internal use. See `kom-default-server' instead." local) (def-kom-var kom-default-user-name nil "**Default LysKOM user name. The value of this variable must be a string, indicating the default user name, an integer indicating the conference number or `nil' to indicate no default. If set to an integer, log in as the user with that conference number. If set to a string, log in as the user with that name. Overrides the environment variable `KOMNAME'." local) (def-kom-var lyskom-default-user-name nil "**This variable is reserved for internal use. See `kom-default-user-name' instead." local) (def-kom-var kom-default-password nil "**Default LysKOM password. The value of this variable must be a string or `nil'. Overrides the environment variable `KOMPASSWORD' \(which should never be used)." local) (def-kom-var lyskom-default-password nil "**This variable is resvered for internal use. See `kom-default-password' instead." local) (def-kom-var mode-line-conf-name nil "Conf name that is present on the mode-line." local) (def-kom-var mode-line-server-name nil "Server name that is present on the mode-line." local) ;;; ============================================================ ;;; History lists ;;; (defvar lyskom-command-history nil) (defvar lyskom-expression-history nil) (defvar lyskom-message-history nil) (defvar lyskom-language-history nil) (defvar lyskom-fast-reply-history nil) (defvar lyskom-help-history nil) ;;; ============================================================ (defconst lyskom-comment-types-list '(COMM-IN FOOTN-IN)) (defconst lyskom-recpt-types-list '(RECPT CC-RECPT BCC-RECPT) "Types of recipients in LysKOM. This variable must be sorted in order of importance, with full recipients first, followed by successively more and more minor recipients. The reason for this is in kom-sub-recipient, which sorts the recipient list using the order of this list.") (defconst lyskom-review-types-list '(REVIEW REVIEW-TREE REVIEW-MARK REVIEW-FAQ REVIEW-FAQ-TREE)) ;;; ============================================================ (eval-and-compile (provide 'lyskom-vars)) ;;; vars.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: macros.el,v 44.40 2004/07/18 14:58:05 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: macros.el ;;;; ;;;; This file contains the macros which must be loaded before lyskom can ;;;; be compiled. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: macros.el,v 44.40 2004/07/18 14:58:05 byers Exp $\n")) ;;; ;;; Require parts of the widget package. We do this to avoid generating ;;; errors later on. This sucks. ;;; (require 'custom) (require 'widget) ;;; ====================================================================== ;;; lyskom-traverse - traverse a sequence. ;;; (defmacro lyskom-traverse (atom sequence &rest body) "Bind ATOM to each element in SEQUENCE and execute BODY. Value returned is always nil." (let ((seq-sym (make-symbol "sequence")) (len-sym (make-symbol "len")) (idx-sym (make-symbol "index"))) `(catch 'lyskom-traverse (let* ((,seq-sym ,sequence) (,idx-sym 0) (,len-sym (or (listp ,seq-sym) (length ,seq-sym))) (,atom nil)) (if (listp ,seq-sym) (while ,seq-sym (setq ,atom (car ,seq-sym)) ,@body (setq ,seq-sym (cdr ,seq-sym))) (while (< ,idx-sym ,len-sym) (setq ,atom (aref ,seq-sym ,idx-sym)) ,@body (setq ,idx-sym (1+ ,idx-sym)))))))) (defmacro lyskom-traverse-membership (var &rest forms) "Traverse the membership list. Variable VAR is bound to each membership, in turn, and FORMS are evaluated." (let ((el-sym (make-symbol "el"))) `(catch 'lyskom-traverse (let ((,el-sym (membership-list->head (lyskom-with-lyskom-buffer (lyskom-mship-cache-data)))) (,var nil)) (while ,el-sym (setq ,var (mship-list-node->data ,el-sym)) ,@forms (setq ,el-sym (mship-list-node->next ,el-sym))))))) (defmacro lyskom-traverse-aux (atom sequence &rest body) "Bind ATOM to each element in SEQUENCE and execute BODY. Value returned is always nil." (let ((seq-sym (make-symbol "aux-items"))) `(catch 'lyskom-traverse (let ((,seq-sym ,sequence) (,atom nil)) (while ,seq-sym (setq ,atom (car ,seq-sym)) (if (not (aux-item-flags->deleted (aux-item->flags ,atom))) (progn ,@body)) (setq ,seq-sym (cdr ,seq-sym))))))) (defmacro lyskom-traverse-break (&optional result) "Break a current lyskom-traverse" `(throw 'lyskom-traverse ,result)) (put 'lyskom-traverse-aux 'edebug-form-spec '(sexp form body)) (put 'lyskom-traverse-aux 'lisp-indent-hook 2) (put 'lyskom-traverse-membership 'edebug-form-spec '(sexp body)) (put 'lyskom-traverse-membership 'lisp-indent-hook 1) (put 'lyskom-traverse 'lisp-indent-hook 2) (put 'lyskom-traverse 'edebug-form-spec '(sexp form body)) ;;; ====================================================================== ;;; lyskom-save-excursion Does not save point and mark. ;;; (defmacro lyskom-save-excursion (&rest forms) "Save-excursion without saving point and mark." (list 'let (list '(__buffer__ (current-buffer))) (list 'unwind-protect (cons 'progn forms) '(set-buffer __buffer__)))) (put 'lyskom-save-excursion 'edebug-form-spec t) (put 'lyskom-save-excursion 'lisp-indent-hook 0) (defmacro lyskom-with-lyskom-buffer (&rest forms) "Evaluate FORMS in the current LysKOM buffer." `(save-excursion (set-buffer lyskom-buffer) ,@forms)) (put 'lyskom-with-lyskom-buffer 'edebug-form-spec t) (put 'lyskom-with-lyskom-buffer 'lisp-indent-hook 0) ;;; ====================================================================== ;;; Some useful macros to make the code more readable. ;;; (defmacro char-in-string (char string) "Return t if the character CHAR is member of STRING. Otherwise return nil." (list 'null (list 'not (list 'string-match (list 'regexp-quote (list 'char-to-string char)) string)))) (defmacro ++ (var) "Increment the variable VAR and return the value." (list 'setq var (list '1+ var))) (defmacro -- (var) "Decrement the variable VAR and return the value." (list 'setq var (list '1- var))) (eval-and-compile (if (fboundp 'when) nil (defmacro when (expr &rest body) "Execute BODY if EXPR evaluates to non-nil" (list 'if expr (cons 'progn body))) (put 'when lisp-indent-function 1) (put 'when 'edebug-form-spec t))) (eval-and-compile (if (fboundp 'unless) nil (defmacro unless (expr &rest body) "Execute BODY if EXPR evaluates to non-nil" (append (list 'if expr nil) body)) (put 'unless lisp-indent-function 1) (put 'unless 'edebug-form-spec t))) ;;; ====================================================================== ;;; Multiple blocking read from server ;;; (defmacro blocking-do-multiple (bind-list &rest body) "Bind variables according to BIND-LIST and then eval BODY. The value of the last form in BODY is returned. Each element in BIND-LIST is a list (SYMBOL FORM) which binds SYMBOL to the result of the server call FORM, which is the same as used in blocking-do. All the forms in BIND-LIST are evaluated before any symbols are bound." (let ((index 0)) `(let ((lyskom-multiple-bind-sym (lyskom-blocking-do-multiple (list ,@(mapcar (lambda (x) `(list ',(car (car (cdr x))) ,@(cdr (car (cdr x))))) bind-list))))) (let (,@(mapcar (lambda (bpat) (prog1 `(,(car bpat) (elt lyskom-multiple-bind-sym ,index)) (setq index (1+ index)))) bind-list)) ,@body)))) (put 'blocking-do-multiple 'edebug-form-spec '(sexp body)) (put 'blocking-do-multiple 'lisp-indent-function 1) ;;; ====================================================================== ;;; Some commands generat async messages we don't really want ;;; (defmacro lyskom-ignoring-async (async &rest body) `(let ((lyskom-ignoring-async-list (cons (list ,@async) lyskom-ignoring-async-list))) ,@body)) (put 'lyskom-ignoring-async 'edebug-form-spec '(sexp body)) (put 'lyskom-ignoring-async 'lisp-indent-function 1) ;;; ====================================================================== ;;; These macros do magic things to the compiler to avoid gratuitous ;;; compiler warnings. ;;; (eval-and-compile (defvar lyskom-expected-unresolved-functions nil)) (eval-and-compile (defvar lyskom-expected-unresolved-functions-temp nil)) (defmacro lyskom-external-function (fn) `(eval-when-compile (setq lyskom-expected-unresolved-functions (cons ',fn lyskom-expected-unresolved-functions)))) (defmacro lyskom-with-external-functions (fns &rest body) "Ignore warnings about unresolved functions FNS when compiling BODY." `(progn (eval-when-compile (and (boundp 'byte-compile-unresolved-functions) (setq lyskom-expected-unresolved-functions-temp (cons (delq nil (mapcar (lambda (fn) (if (assq fn byte-compile-unresolved-functions) nil fn)) ',fns)) lyskom-expected-unresolved-functions-temp)))) ,@body (eval-when-compile (and (boundp 'byte-compile-unresolved-functions) (mapcar (lambda (fn) (and fn (setq byte-compile-unresolved-functions (delq (assq fn byte-compile-unresolved-functions) byte-compile-unresolved-functions)))) (car lyskom-expected-unresolved-functions-temp))) (setq lyskom-expected-unresolved-functions-temp (cdr lyskom-expected-unresolved-functions-temp))))) (defmacro lyskom-end-of-compilation () `(progn (eval-when-compile (progn (if (and (boundp 'byte-compile-unresolved-functions) (consp (car-safe byte-compile-unresolved-functions)) (symbolp (car-safe (car-safe byte-compile-unresolved-functions)))) (progn (mapcar (function (lambda (x) (setq byte-compile-unresolved-functions (delq (assq x byte-compile-unresolved-functions) byte-compile-unresolved-functions)))) lyskom-expected-unresolved-functions) )) (if lyskom-compatibility-definitions (message "Compatibility definitions: %s" (mapconcat '(lambda (sym) (symbol-name sym)) lyskom-compatibility-definitions ", "))))))) ;;; ============================================================ ;;; Keymap handling ;;; (defmacro lyskom-use-local-map (keymap) "Use keymap KEYMAP as local map in this buffer. KEYMAP is made local in the current buffer, and its value is copied from the LysKOM buffer." (` (progn (make-local-variable (quote (, keymap))) (setq (, keymap) (lyskom-default-value (quote (, keymap)))) (use-local-map (, keymap))))) (defmacro lyskom-try-define-key (map seq fn) `(condition-case nil (define-key ,map ,seq ,fn) (error nil))) ;;; ============================================================ ;;; Widget gunk ;;; (defmacro lyskom-widget-wrapper (fn file) `(eval-and-compile (if (not (fboundp ',fn)) (autoload ',fn ,file)))) (lyskom-widget-wrapper define-widget "widget") (lyskom-widget-wrapper widget-at "wid-edit") (lyskom-widget-wrapper widget-value "wid-edit") (lyskom-widget-wrapper widget-button-click "wid-edit") (lyskom-widget-wrapper widget-setup "wid-edit") (lyskom-widget-wrapper widget-value-set "wid-edit") (lyskom-widget-wrapper widget-insert "wid-edit") (lyskom-widget-wrapper widget-create "wid-edit") (lyskom-widget-wrapper widget-get "wid-edit") (lyskom-widget-wrapper widget-put "wid-edit") ;;; ============================================================ ;;; Signal gunk ;;; (defmacro lyskom-ignore-errors (&rest forms) (` (condition-case nil (progn (,@ forms)) (error nil)))) (put 'ignore-errors 'edebug-form-spec '(sexp form body)) (defun lyskom-assert-error (&rest args) (save-excursion (save-match-data (if (not (and (boundp 'lyskom-buffer) (bufferp lyskom-buffer))) (let ((debug-on-error t)) (apply 'error args)) (set-buffer lyskom-buffer) (lyskom-save-backtrace) (apply 'message args) (lyskom-insert-before-prompt (concat (apply 'format args) "\n")) (lyskom-insert-before-prompt (format "%s\n" (car (car lyskom-backtrace-list)))) (lyskom-insert-before-prompt (format "%s\n" (elt (car lyskom-backtrace-list) 1))))))) (eval-and-compile (if lyskom-debug-compile (defsubst lyskom-assert (check &rest args) (or check (if args (apply 'lyskom-assert-error args) (lyskom-assert-error "Assertion failed")))) (defsubst lyskom-assert (check &rest args) nil))) (eval-and-compile (if lyskom-debug-compile (defmacro lyskom-debug-forms (&rest forms) `(progn ,@forms)) (defmacro lyskom-debug-forms (&rest forms)))) ;;; ============================================================ ;;; Local variables ;;; (defmacro lyskom-setq-default (name value) (` (lyskom-set-default (quote (, name)) (, value)))) (defmacro lyskom-ref-no () `(prog1 lyskom-ref-no (setq lyskom-ref-no (1+ lyskom-ref-no)) (when (< lyskom-ref-no 0) (setq lyskom-ref-no 1)))) (defsubst lyskom-mime-content-type (ct) (car ct)) (defsubst lyskom-mime-content-type-get (ct param) (cdr (assq param (cdr ct)))) (eval-and-compile (provide 'lyskom-macros)) ;;; Local Variables: ;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2) ;;; eval: (put 'lyskom-save-excursion 'lisp-indent-hook 0) ;;; eval: (put 'lyskom-ignore-errors 'lisp-indent-hook 2) ;;; eval: (put 'lyskom-with-external-functions 'lisp-indent-hook 1) ;;; end: ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: compatibility.el,v 44.74 2004/10/29 10:41:09 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; Copyright (C) 2001 Free Software Foundation, Inc. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: compatibility.el ;;;; ;;;; This file contains functions that may not exist in all supported ;;;; versions of Gnu Emacs. XEmacs-specific and Emacs 18-specific code ;;;; should go in some other file. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: compatibility.el,v 44.74 2004/10/29 10:41:09 _cvs_pont_lyskomelisp Exp $\n")) ;;; ============================================================ ;;; Utility macros (eval-and-compile (defvar lyskom-compatibility-definitions nil "Functions defined or redefined because they are incompatible with LysKOM") (defmacro lyskom-provide-function (name &rest rest) "If NAME is not already defined, define it as a function." `(eval-and-compile (or (fboundp ',name) (progn (setq lyskom-compatibility-definitions (cons ',name lyskom-compatibility-definitions)) (defun ,name ,@rest))))) (defmacro lyskom-provide-macro (name &rest rest) "If NAME is not already defined, define it as a macro." `(eval-and-compile (or (fboundp ',name) (progn (setq lyskom-compatibility-definitions (cons ',name lyskom-compatibility-definitions)) (defmacro ,name ,@rest))))) (defmacro lyskom-macro-alias (name args &rest body) "Create a LysKOM name alias. If NAME is defined, then lyskom-NAME will be an alias to it. Otherwise, lyskom-NAME will be defined to be a macro with ARGS and BODY." (let ((alias-name (intern (concat "lyskom-" (symbol-name name))))) `(eval-and-compile (if (fboundp ',name) (defalias ',alias-name ',name) (setq lyskom-compatibility-definitions (cons ',name lyskom-compatibility-definitions)) (defmacro ,alias-name ,args ,@body))))) (defmacro lyskom-function-alias (name args &rest body) "Create a LysKOM name alias. If NAME is defined, then lyskom-NAME will be an alias to it. Otherwise, lyskom-NAME will be defined to be a function with ARGS and BODY." (let ((alias-name (intern (concat "lyskom-" (symbol-name name))))) `(eval-and-compile (if (fboundp ',name) (defalias ',alias-name ',name) (setq lyskom-compatibility-definitions (cons ',name lyskom-compatibility-definitions)) (defun ,alias-name ,args ,@body))))) (defmacro lyskom-xemacs-or-gnu (xemacs-form gnu-form) "Eval XEMACS-FORM in XEmacs and GNU-FORM in Gnu Emacs." (if (string-match "XEmacs" (emacs-version)) xemacs-form gnu-form)) ) ;;; ====================================================================== ;;; Various definitions ;; Lots of Emacsen have buggy definitions of kbd (or no definition at ;; all) Although it's crufty to redefine a function from subr.el, I ;; will do so if it appears to be misbehaving. Don't like it? Tough! (eval-and-compile (and (condition-case nil (or (equal (kbd (identity "")) [down-mouse-2]) (error "Bad definition of kbd")) (error t)) (progn (fmakunbound 'kbd) (lyskom-provide-macro kbd (keys) "Convert KEYS to the internal Emacs key representation. KEYS should be a string in the format used for saving keyboard macros \(see `insert-kbd-macro')." (if (or (stringp keys) (vectorp keys)) (read-kbd-macro keys) `(read-kbd-macro ,keys)))))) ;; Functions mostly from XEmacs that we use (lyskom-macro-alias compiled-function-p (arg) `(byte-code-function-p ,arg)) (lyskom-function-alias characterp (obj) (integerp obj)) (lyskom-function-alias int-to-char (obj) obj) (lyskom-function-alias char-to-int (c) c) (lyskom-function-alias signum (num) (cond ((< num 0) -1) ((> num 0) 1) (t 0))) ;; If we use lyskom-function-alias here we'll get an obsolecense ;; warning about screen-width. This way the compiler won't notice :-) (if (fboundp 'frame-width) (defalias 'lyskom-frame-width 'frame-width) (fset 'lyskom-frame-width 'screen-width)) ;; Some minibuffer compatibility stuff (lyskom-with-external-functions (temp-minibuffer-message) (lyskom-function-alias minibuffer-contents () (buffer-string)) (lyskom-function-alias minibuffer-message (message) (temp-minibuffer-message message))) ;; Definition of map-keymap that hopefully works like the one in XEmacs ;; except that the sort-first argument is ignored. (lyskom-function-alias map-keymap (fn keymap &optional sort-first) "Map FN over all bindings in KEYMAP." (let ((r 0)) (when (keymapp keymap) (when (symbolp keymap) (setq keymap (symbol-value keymap))) (let ((keymap (cdr keymap)) (el nil)) (while (and keymap (not (keymapp keymap))) (setq el (car keymap) keymap (cdr keymap)) (cond ((vectorp el) (while (< r (length el)) (if (aref el r) (funcall fn r (aref el r))) (setq r (1+ r)))) ((char-table-p el) (map-char-table fn el)) (t (funcall fn (car el) (cdr el))))))))) ;; set-keymap-parent also comes from XEmacs (lyskom-function-alias set-keymap-parent (keymap new-parent) (let ((tail keymap)) (while (and tail (cdr tail) (not (eq (car (cdr tail)) 'keymap))) (setq tail (cdr tail))) (if tail (setcdr tail new-parent)))) ;; XEmacs and Gnu Emacs don't use the same names for mouse events ;; and such. This is to help us deal with that. (defconst lyskom-gnu-keysym '((button1 . "") (button2 . "") (button3 . "") (button1up . "") (button2up . "") (button3up . ""))) (defconst lyskom-xemacs-keysym '((button1 . "") (button2 . "") (button3 . "") (button1up . "") (button2up . "") (button3up . ""))) (defun lyskom-keys (sym) "Look up the key description for key SYM." (cdr (assq sym (lyskom-xemacs-or-gnu lyskom-xemacs-keysym lyskom-gnu-keysym)))) ;;; ============================================================ ;;; MULE stuff ;;; ;;; We used to define dummy versions of basic MULE functions so ;;; we could code using the standard names. We don't do that any ;;; more. Instead, we define aliases in our own namespace. (defvar enable-multibyte-characters nil) (lyskom-function-alias set-buffer-multibyte (arg) (put 'enable-multibyte-characters 'permanent-local t) (make-local-variable 'enable-multibyte-characters) (setq enable-multibyte-characters arg)) (lyskom-function-alias set-process-coding-system (proc &optional encoding decoding)) (lyskom-function-alias encode-coding-string (str coding-system) (copy-sequence str)) (lyskom-function-alias decode-coding-string (str coding-system) (copy-sequence str)) (lyskom-function-alias string-bytes (str) (length str)) (lyskom-function-alias check-coding-system (name) (error "No such coding system")) (lyskom-function-alias find-coding-systems-for-charsets (cs) nil) (lyskom-function-alias coding-system-get (cs prop) nil) (lyskom-function-alias char-width (c) 1) (lyskom-function-alias find-charset-string (str) '(ascii)) (lyskom-function-alias string-as-unibyte (str) str) (lyskom-function-alias string-make-unibyte (str) str) (lyskom-function-alias string-make-multibyte (str) str) (lyskom-function-alias multibyte-string-p (str) nil) (lyskom-function-alias charsetp (arg) nil) (lyskom-function-alias coding-system-type (arg) nil) (lyskom-function-alias coding-system-property (arg sym) (lyskom-coding-system-get arg sym)) (lyskom-function-alias split-string (string &optional separators) (string-split (or separators "[ \f\t\n\r\v]+") string)) ;; Detect buggy versions of encode-coding-string and ;; decode-coding-string such as those provided by APEL (part of TM and ;; often included in XEmacs) (defun lyskom-buggy-encode-coding-string (str coding-system) str) (eval-and-compile (if (let ((test "TEM")) (eq (lyskom-encode-coding-string test 'raw-text) test)) (progn (fset 'lyskom-buggy-encode-coding-string (symbol-function 'lyskom-encode-coding-string)) (defun lyskom-encode-coding-string (str coding-system) (copy-sequence (lyskom-buggy-encode-coding-string str coding-system)))))) (defun lyskom-buggy-decode-coding-string (str coding-system) str) (eval-and-compile (if (let ((test "TEM")) (eq (lyskom-decode-coding-string test 'raw-text) test)) (progn (fset 'lyskom-buggy-decode-coding-string (symbol-function 'lyskom-decode-coding-string)) (defun lyskom-decode-coding-string (str coding-system) (copy-sequence (lyskom-buggy-decode-coding-string str coding-system)))))) ;; defmacro lyskom-encode-coding-char in XEmacs so the compiled code ;; is quicker. In Gnu Emacs define it as a function. ;; ;; The definition is made at compile-time to avoid getting warnings ;; about encode-coding-char. (eval-and-compile (cond ((eval-when-compile (string-match "XEmacs" (emacs-version))) (defmacro lyskom-encode-coding-char (c system) c)) ((eval-when-compile (fboundp 'encode-coding-char)) (defun lyskom-encode-coding-char (c system) (let ((s (encode-coding-char c system))) (if (and s (= (length s) 1)) (elt s 0))))) (t (defmacro lyskom-encode-coding-char (c system) c)))) ;; It seems that string-width is buggy with respect to handling ;; unibyte strings in multibyte environments or vice versa. Or ;; something like that. There has got to be a good explanation ;; for the mess below. (eval-and-compile (if (fboundp 'string-width) (defalias 'lyskom-original-string-width 'string-width) (defmacro lyskom-original-string-width (s) `(length ,s))) (lyskom-xemacs-or-gnu (defalias 'lyskom-string-width 'string-width) (defun lyskom-string-width (str) (cond ((and (lyskom-multibyte-string-p str) (null enable-multibyte-characters)) (lyskom-original-string-width (lyskom-string-make-unibyte str))) ((and (null (lyskom-multibyte-string-p str)) enable-multibyte-characters) (lyskom-original-string-width (lyskom-string-make-multibyte str))) (t (lyskom-original-string-width str)))))) ;;; ================================================================ ;;; Faces and windows and stuff (lyskom-function-alias frame-property (frame property &optional default) (or (cdr (assq property (frame-parameters frame))) default)) (lyskom-function-alias face-background (face) nil) (lyskom-function-alias face-foreground (face) nil) (lyskom-function-alias find-face (face) (and (facep face) face)) (defun lyskom-make-face (name temporary) "Like make-face in XEmacs" (lyskom-xemacs-or-gnu (make-face name nil temporary) (make-face name))) (if (not (lyskom-find-face 'strikethrough)) (progn (make-face 'strikethrough) (if (eval-when-compile (fboundp 'set-face-strikethrough-p)) (set-face-strikethru-p 'strikethrough t) (set-face-underline-p 'strikethrough t)))) (defun lyskom-get-buffer-window-list (buffer &optional minibuf frame) "Return windows currently displaying BUFFER, or nil if none. See `walk-windows' for the meaning of MINIBUF and FRAME." (let ((buffer (if (bufferp buffer) buffer (get-buffer buffer))) windows) (walk-windows (function (lambda (window) (if (eq (window-buffer window) buffer) (setq windows (cons window windows))))) minibuf frame) windows)) ; ================================================================== ; Image display (lyskom-function-alias display-images-p () nil) (lyskom-function-alias put-image (what where) nil) (lyskom-function-alias create-image (file-or-data) nil) ;;; ================================================================ ;;; Color stuff (lyskom-function-alias color-specifier-p (obj) nil) (lyskom-function-alias color-name (obj) nil) (lyskom-with-external-functions (color-rgb-components make-specifier set-specifier) (eval-and-compile (cond ((and (fboundp 'color-rgb-components) (fboundp 'make-specifier) (fboundp 'set-specifier)) (defun lyskom-color-values (color) (when (stringp color) (let ((spec nil)) (set-specifier (setq spec (make-specifier 'color)) color) (setq color spec))) (color-rgb-components color))) ((fboundp 'color-values) (fset 'lyskom-color-values 'color-values)) ((fboundp 'x-color-values) (fset 'lyskom-color-values 'x-color-values))))) ;;; ====================================================================== ;;; Event stuff (lyskom-with-external-functions (event-start) (lyskom-function-alias event-glyph (e)) (lyskom-function-alias event-point (e) "Return the character position of the given mouse event. If the event did not occur over a window, or did not occur over text, then this returns nil. Otherwise, it returns an index into the buffer visible in the event's window." (car (cdr (event-start e)))) (lyskom-function-alias event-closest-point (e) "Return the character position closest to the mouse event EVENT." (car (cdr (event-start e))))) ;;; ====================================================================== ;;; Platform-specific stuff (lyskom-provide-function w32-shell-execute (&rest args) "Dummy function that raises an error." (error "w32-shell-execute undefined")) ;;; ================================================================ ;;; We provide these functions in the default namespace since there is ;;; no reason to beleive that (a) the definitions suck (they're taken ;;; from either XEmacs or Gnu Emacs) and (b) no package should be ;;; using them to figure out what environment it is running in ;;; (unlike, say, the MULE functions). ;;; ;;; There are also a few functions (regexpp and functionp) that may ;;; appear in some version of Emacs, and if they do we accept those ;;; definitions. ;;; (lyskom-provide-function last (x &optional n) "Returns the last link in the list LIST. With optional argument N, returns the Nth-to-last link (default 1)." "Returns the last link in the list LIST. With optional argument N, returns Nth-to-last link (default 1)." (if n (let ((m 0) (p x)) (while (consp p) (setq m (1+ m)) (setq p (cdr p))) (if (<= n 0) p (if (< n m) (nthcdr (- m n) x) x))) (while (consp (cdr x)) (setq x (cdr x))) x)) (lyskom-provide-function plist-member (plist prop) "Return non-nil if PLIST has the property PROP. PLIST is a property list, which is a list of the form \(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol. Unlike `plist-get', this allows you to distinguish between a missing property and a property with the value nil." (while (and plist (not (eq (car plist) prop))) (setq plist (cdr (cdr plist)))) (and plist t)) ;; The make-temp-file function below is taken verbatim from Emacs 21.2. (lyskom-provide-function make-temp-file (prefix &optional dir-flag) "Create a temporary file. The returned file name (created by appending some random characters at the end of PREFIX, and expanding against `temporary-file-directory' if necessary, is guaranteed to point to a newly created empty file. You can then use `write-region' to write new data into the file. If DIR-FLAG is non-nil, create a new empty directory instead of a file." (let (file) (while (condition-case () (progn (setq file (make-temp-name (expand-file-name prefix (lyskom-xemacs-or-gnu (temp-directory) temporary-file-directory)))) (if dir-flag (make-directory file) (write-region "" nil file nil 'silent nil)) nil) (file-already-exists t)) ;; the file was somehow created by someone else between ;; `make-temp-name' and `write-region', let's try again. nil) file)) (lyskom-provide-function replace-in-string (str regexp newtext &optional literal) "Replaces all matches in STR for REGEXP with NEWTEXT string. Optional LITERAL non-nil means do a literal replacement. Otherwise treat \\ in NEWTEXT string as special: \\& means substitute original matched text, \\N means substitute match for \(...\) number N, \\\\ means insert one \\." (if (not (stringp str)) (error "(replace-in-string): First argument must be a string: %s" str)) (if (stringp newtext) nil (error "(replace-in-string): 3rd arg must be a string: %s" newtext)) (let ((rtn-str "") (start 0) (special) match prev-start) (while (setq match (string-match regexp str start)) (setq prev-start start start (match-end 0) rtn-str (concat rtn-str (substring str prev-start match) (cond (literal newtext) (t (mapconcat (function (lambda (c) (if special (progn (setq special nil) (cond ((eq c ?\\) "\\") ((eq c ?&) (substring str (match-beginning 0) (match-end 0))) ((and (>= c ?0) (<= c ?9)) (if (> c (+ ?0 (length (match-data)))) ;; Invalid match num (error "(replace-in-string) Invalid match num: %c" c) (setq c (- c ?0)) (substring str (match-beginning c) (match-end c)))) (t (char-to-string c)))) (if (eq c ?\\) (progn (setq special t) nil) (char-to-string c))))) newtext "")))))) (concat rtn-str (substring str start)))) (lyskom-provide-function buffer-live-p (object) "T of OBJECT is an editor buffer that has not been deleted." (and (bufferp object) (buffer-name object))) (lyskom-provide-function string-to-vector (string) "Return a vector of characters in STRING." (let ((len (length string)) (i 0) val) (setq val (make-vector len 0)) (while (< i len) (aset val i (aref string i)) (setq i (1+ i))) val)) (lyskom-provide-function copy-tree (l) "Recursively copy the list L" (cond ((atom l) l) (t (cons (copy-tree (car l)) (copy-tree (cdr l)))))) (lyskom-provide-function functionp (obj) "Returns t if OBJ is a function, nil otherwise." (cond ((symbolp obj) (fboundp obj)) ((subrp obj)) ((lyskom-compiled-function-p obj)) ((consp obj) (and (eq (car obj) 'lambda) (listp (car (cdr obj))))) (t nil))) (lyskom-provide-function regexpp (re) "Return non-nil if RE looks like a valid regexp." (let ((result t)) (save-match-data (condition-case nil (string-match re "") (error (setq result nil)))) result)) (lyskom-macro-alias char-before (&optional pos buffer) `(save-excursion (save-restriction (widen) ,@(if buffer `((set-buffer ,buffer))) ,(if pos `(if (or (> ,pos (point-max)) (<= ,pos (point-min))) nil (goto-char ,pos) (preceding-char)) `(if (<= (point) (point-min)) nil (preceding-char)))))) (lyskom-function-alias make-hash-table (&rest args) "Create and return a new hash table. This is a limited emulation of the make-hash-table function available in some Emacsen. It ignores all arguments. The only test supported is `eq'." (let ((test (car (cdr (memq ':test args))))) (or (eq test 'eq) (lyskom-error "internal error: invalid hash function")) (cons 'HASH nil))) (lyskom-function-alias gethash (key table) "Look up KEY in TABLE and return its associated value. This is a limited emulation of the gethash function available in some Emacsen. It does not support the default argument." (cdr (assq key (cdr table)))) (lyskom-function-alias puthash (key value table) "Associate KEY with VALUE in hash table TABLE. If KEY is already present in table, replace its current value with VALUE. This is a limited emulation of the puthash function available in some Emacsen." (let ((tmp (assq key (cdr table)))) (if tmp (setcdr tmp value) (setcdr table (cons (cons key value) (cdr table)))))) (lyskom-function-alias remhash (key table) "Remove KEY from TABLE. This is a limited emulation of the remhash function available in some Emacsen." (let ((tmp (assq key (cdr table)))) (when tmp (setcdr table (delq tmp (cdr table)))))) ;;; ================================================================ ;;; Some symbols are self-evaluating. They're not in all versions ;;; of Emacs that we would like to support. So we make them ;;; self-evaluating here. ;; This code looks the way it does in order to avoid warnings in ;; Emacs 21. (eval-when-compile (if (boundp ':lyskom-is-this-self-evaluating) (defmacro lyskom-make-self-evaluating (var)) (defmacro lyskom-make-self-evaluating (var) `(eval-and-compile (set ',var ',var))))) (lyskom-make-self-evaluating :default) (lyskom-make-self-evaluating :mime-charset) (lyskom-make-self-evaluating :default-help-echo) (lyskom-make-self-evaluating :group) (lyskom-make-self-evaluating :automatic) (lyskom-make-self-evaluating :read-only) (lyskom-make-self-evaluating :filter) (lyskom-make-self-evaluating :filter-args) (lyskom-make-self-evaluating :constraint) (lyskom-make-self-evaluating :save) (lyskom-make-self-evaluating :refer) (lyskom-make-self-evaluating :width) (lyskom-make-self-evaluating :prompt) (lyskom-make-self-evaluating :align) (lyskom-make-self-evaluating :format) (lyskom-make-self-evaluating :output) (lyskom-make-self-evaluating :subject-mode) (lyskom-make-self-evaluating :subject-indent) (lyskom-make-self-evaluating :text) (lyskom-make-self-evaluating :text-stat) (lyskom-make-self-evaluating :text-no) (lyskom-make-self-evaluating :subjects) (lyskom-make-self-evaluating :subject-last) (lyskom-make-self-evaluating :comment-order) (lyskom-make-self-evaluating :unique) (lyskom-make-self-evaluating :weight) (lyskom-make-self-evaluating :prompt-format) (lyskom-make-self-evaluating :dead-ok) (lyskom-make-self-evaluating :mark) (lyskom-make-self-evaluating :test) (lyskom-make-self-evaluating :size) (lyskom-make-self-evaluating :may-interrupt) ;;; ================================================================ ;;; Emacs 21.4 stuff (lyskom-function-alias function-obsolete-p (function) "Return non-nil if FUNCTION is obsolete" (get function 'byte-obsolete-info)) (eval-and-compile (if (and (lyskom-function-obsolete-p 'process-kill-without-query) (fboundp 'set-process-query-on-exit-flag)) (fset 'lyskom-set-process-query-on-exit-flag 'set-process-query-on-exit-flag) (fset 'lyskom-set-process-query-on-exit-flag 'process-kill-without-query))) (eval-and-compile (if (lyskom-function-obsolete-p 'make-local-hook) (defun lyskom-make-local-hook (hook)) (fset 'lyskom-make-local-hook 'make-local-hook))) ;;; ================================================================ ;;; ================================================================ ;;; ================================================================ ;;; Set up edebug-form-spec and friends. We do this here because ;;; we have to have the eval block at the end, and this at least ;;; keeps everything together (it would have been nicer to put ;;; an eval block with each definition, but I don't think that ;;; would look good, and it might not always work). (put 'lyskom-provide-function 'lisp-indent-hook 2) (put 'lyskom-function-alias 'lisp-indent-hook 2) (put 'lyskom-macro-alias 'lisp-indent-hook 2) (put 'lyskom-xemacs-or-gnu 'edebug-form-spec '(form form)) ;;; Local Variables: ;;; eval: (put 'lyskom-provide-function 'lisp-indent-hook 2) ;;; eval: (put 'lyskom-function-alias 'lisp-indent-hook 2) ;;; eval: (put 'lyskom-macro-alias 'lisp-indent-hook 2) ;;; eval: (put 'lyskom-xemacs-or-gnu 'edebug-form-spec '(form form)) ;;; end: ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: language.el,v 44.32 2004/01/01 22:01:39 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: language.el ;;;; Author: Niels Möller ;;;; ;;;; (require 'lyskom-vars "vars") ;;; Variables ;;(defvar lyskom-language-symbols nil ;; "Symbols with language data bound to them") (defvar lyskom-languages nil "An alist of defined languages. Each entry is a pair (SYMBOL . (NAME NAME ...)) where symbol is the symbol used for identification, and the NAMEs are names of the language.") (defvar lyskom-language-categories nil "Categories of language-specific variables. Each element is a cons cell (NAME . SCOPE), where NAME is the name of the category and SCOPE is its scope (global or local).") (defvar lyskom-language-vars nil "A list of all language-dependent variables. Each element is a cons cell (NAME . SCOPE), where NAME is the name of the category and SCOPE is its scope (global or local).") (defun lyskom-language-var-internal (scope var language val) "Defines a language-local variable value." (or (assq var lyskom-language-vars) (setq lyskom-language-vars (cons (cons var scope) lyskom-language-vars))) (let* ((alist (get var 'lyskom-language-var)) (entry (assq language alist))) (if entry (setcdr entry val) (put var 'lyskom-language-var (cons (cons language val) alist))))) (defmacro lyskom-language-var (scope var language val) `(lyskom-language-var-internal ',scope ',var ',language ',val)) (put 'lyskom-language-var 'lisp-indent-function 2) (defun lyskom-set-language-vars (language scope) "Set language-specific variables to values for LANGUAGE. SCOPE must be one of global or local, and specifies the scope of the change. If SCOPE is global, change all variables, even those that affect multiple sessions." (mapcar (lambda (spec) (let ((var (car spec)) (var-scope (cdr spec))) (when (or (eq scope 'global) (eq var-scope 'local)) (when (eq scope 'global) (set-default var (eval (cdr (assq language (get var 'lyskom-language-var)))))) (when (or (not (symbol-value var)) (get var 'lyskom-language-force)) (set var (eval (cdr (assq language (get var 'lyskom-language-var))))))))) lyskom-language-vars)) ;;; Keymaps (defvar lyskom-language-keymaps nil "A list of all language-dependent keymaps.") (defun lyskom-language-keymap-internal (keymap language langmap) "Defines a language-local keymap." ;; If the "real" keymap has no value, set it to an empty keymap (if (eval keymap) nil (set keymap (make-sparse-keymap))) ;; Add it to the list of keymaps (or (memq keymap lyskom-language-keymaps) (setq lyskom-language-keymaps (cons keymap lyskom-language-keymaps))) ;; Modify the property list (let* ((alist (get keymap 'lyskom-language-keymap)) (entry (assq language alist))) (if entry (setcdr entry langmap) (put keymap 'lyskom-language-keymap (cons (cons language langmap) alist))))) (defmacro lyskom-language-keymap (keymap language langmap) `(lyskom-language-keymap-internal ',keymap ',language ',langmap)) (put 'lyskom-language-keymap 'lisp-indent-function 2) (defun lyskom-set-language-keymaps (language) (mapcar (lambda (map) (lyskom-set-keymap-parent (symbol-value map) (eval (cdr (assq language (get map 'lyskom-language-keymap)))))) lyskom-language-keymaps)) ;;; String catalogs (defun lyskom-language-strings-internal (scope category language alist) "Associates names to symbols. See documentation of lyskom-language-strings for information on the parameters to this function." ;; Record category (or (assq category lyskom-language-categories) (setq lyskom-language-categories (cons (cons category scope) lyskom-language-categories))) (let ((record (get category 'lyskom-language-symbols))) (mapcar (lambda (pair) (let* ((symbol (car pair)) (string (cdr pair)) (llist (get symbol category)) (entry (assq language llist))) ;; Record symbol (or (memq symbol record) (setq record (cons symbol record))) (if entry (setcdr entry string) (put symbol category (cons (cons language string) llist))))) alist) (put category 'lyskom-language-symbols record))) (defmacro lyskom-language-strings (scope category language alist) "Define a category of strings. SCOPE is the scope of language-specificity. If it is global, then these strings apply globally and will not be altered by changing the session language. CATEGORY is the name of the category. LANGUAGE is the language, a symbol denoting the ISO639 language code. ALIST is the list of strings." `(lyskom-language-strings-internal ',scope ',category ',language ,alist)) (defun lyskom-language-missing-string-internal (category string languages) (let ((old-missing (assq 'lyskom-missing-languages (get string category)))) (if old-missing (setcdr old-missing (append languages (cdr old-missing))) (put string category (cons (cons 'lyskom-missing-languages languages) (get string category)))))) (defun lyskom-language-ending-mismatch-internal (category string l1 l2) (let ((old-mismatch (assq 'lyskom-ending-mismatch (get string category)))) (if old-mismatch (setcdr old-mismatch (append (list (cons l1 l2) (cons l2 l1)) (cdr old-mismatch))) (put string category (cons (cons 'lyskom-ending-mismatch (list (cons l1 l2) (cons l2 l1))) (get string category)))))) (defmacro lyskom-language-missing-string (category string &rest languages) `(lyskom-language-missing-string-internal ',category ',string ',languages)) (defmacro lyskom-language-ending-mismatch (category string l1 l2) `(lyskom-language-ending-mismatch-internal ',category ',string ',l1 ',l2)) (put 'lyskom-language-strings 'lisp-indent-function 2) (defsubst lyskom-tell-string (key) "Retrieve the phrase indexed by the key from the kom-tell-phrases assoc list." (condition-case nil (lyskom-get-string key 'kom-tell-phrases) (lyskom-internal-error (message "Bad kom-tell-phrases: missing %s" key) ""))) (defsubst lyskom-try-get-string (symbol category &optional language) (cdr (assq (if (eq (cdr (assq category lyskom-language-categories)) 'local) (or language lyskom-language) (or language lyskom-global-language)) (get symbol category)))) (defsubst lyskom-get-string-error (function symbol category) (signal 'lyskom-internal-error (list function (list symbol category ": string not found")))) (defun lyskom-get-string (symbol &optional category language) "Returns string associated with SYMBOL" (or (lyskom-try-get-string symbol (or category 'lyskom-message) language) (lyskom-get-string-error 'lyskom-get-string symbol (or category 'lyskom-message)))) (defun lyskom-get-string-sol (symbol &optional category) "Returns string associated with SYMBOL If kom-long-lines is set, return the long form of the string, if it exists." (or (and kom-long-lines (lyskom-try-get-string (intern (concat (symbol-name symbol) "-long")) (or category 'lyskom-message))) (lyskom-try-get-string symbol (or category 'lyskom-message)) (lyskom-get-string-error 'lyskom-get-string symbol (or category 'lyskom-message)))) (defun lyskom-get-strings (symbols &optional category) "Returns an alist of (symbol . string) pairs according to CATEGORY and lyskom-language. Kind of inverse to lyskom-define-language." (mapcar (lambda (symbol) (cons symbol (lyskom-get-string symbol category))) symbols)) (defun lyskom-get-menu-string (symbol) "Returns the name of a menu(item) Looks for the 'lyskom-menu category, or 'lyskom-command if 'lyskom-menu is not found." (lyskom-encode-coding-string (or (lyskom-try-get-string symbol 'lyskom-menu) (lyskom-try-get-string symbol 'lyskom-command) (lyskom-get-string-error 'lyskom-get-menu-string symbol 'lyskom-menu)) 'iso-8859-1)) (defun lyskom-define-language (language coding &rest names) (let ((match (assq language lyskom-languages))) (if match (setcdr match names) (setq lyskom-languages (cons (cons language names) lyskom-languages)))) (put language 'lyskom-language-coding coding)) (defun lyskom-language-coding (language) (or (get language 'lyskom-language-coding) 'raw-text)) (defun lyskom-language-name (language) "Return the name of language code LANGUAGE in the current language." (save-excursion (when lyskom-buffer (set-buffer lyskom-buffer)) (or (cdr (assq language lyskom-language-codes)) (lyskom-format (cdr (assq '-- lyskom-language-codes)) (symbol-name language))))) (defun lyskom-set-language (language scope) "Set the current language to LANGUAGE. Returns non-nil on success and nil on failure." (when (listp language) (setq language (lyskom-first-available-language language))) (cond ((not (assq language lyskom-languages)) (lyskom-format-insert-before-prompt 'language-not-loaded (lyskom-language-name language)) nil) (t (cond ((eq scope 'local) (setq lyskom-language language)) ((eq scope 'global) (setq lyskom-global-language language) (lyskom-set-language-keymaps language))) (lyskom-set-language-vars language scope) (when (eq scope 'global) (lyskom-update-menus)) (lyskom-update-prompt t) (lyskom-update-command-completion) t))) (defun lyskom-first-available-language (langs) "Return the first language in LANGS that is supported." (or (lyskom-traverse el (if (listp langs) langs (list langs)) (when (assq el lyskom-languages) (lyskom-traverse-break el))) (car (car lyskom-languages)))) (defun lyskom-language-from-environment (var) "Return language name from value of environment variable VAR." (let ((tmp (getenv var))) (and tmp (string-match "^\\([a-z]+\\)" tmp) (intern (match-string 1 tmp))))) (defun lyskom-default-language () "Return the default language for LysKOM" (let ((languages (append (if (listp kom-default-language) kom-default-language (list kom-default-language)) (list (lyskom-language-from-environment "KOMLANGUAGE") (lyskom-language-from-environment "LC_ALL") (lyskom-language-from-environment "LC_MESSAGES") (lyskom-language-from-environment "LANG"))))) (or (lyskom-traverse lang languages (when (assq lang lyskom-languages) (lyskom-traverse-break lang))) (car (car (last lyskom-languages)))))) (eval-and-compile (provide 'lyskom-language)) ;;; language.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: help.el,v 44.7 2003/01/05 21:37:06 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: help.el ;;;; ;;;; Functions for formatting help strings in the client ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: help.el,v 44.7 2003/01/05 21:37:06 byers Exp $\n")) (defgroup lyskom-faces nil "Faces for use in the LysKOM elisp client." :group 'lyskom) (defgroup lyskom nil "Faces for use in the LysKOM elisp client." :group 'default) (defface lyskom-help-h1-face '((t (:weight bold :underline t :height 2.0 :family "helvetica"))) "First level header in LysKOM help." :group 'lyskom-faces) (defface lyskom-help-h2-face '((t (:weight bold :underline t :height 1.5 :family "helvetica"))) "Second level header in LysKOM help." :group 'lyskom-faces) (defface lyskom-help-h3-face '((t (:weight bold :family "helvetica"))) "Third level header in LysKOM help." :group 'lyskom-faces) ;;; Note that these are duplicated in help-compile.el. Change one and change both! ;;UNUSED: lyskom-help-create-data (defsubst lyskom-help-create-data (tag attr data) (list tag attr data)) (defsubst lyskom-help-data-get-tag (data) (elt data 0)) (defsubst lyskom-help-data-get-attr (attr data) (cdr (assq attr (elt data 1)))) ;;UNUSED: lyskom-help-data-get-attrs (defsubst lyskom-help-data-get-attrs (data) (elt data 1)) (defsubst lyskom-help-data-get-data (data) (elt data 2)) (defvar lyskom-help-format-handlers '((h1 . lyskom-help-format-h1) (h2 . lyskom-help-format-h2) (h3 . lyskom-help-format-h3) (p . lyskom-help-format-p) (b . lyskom-help-format-b) (i . lyskom-help-format-i) (list . lyskom-help-format-list) (item . lyskom-help-format-item) (inline . lyskom-help-format-inline) (refer . lyskom-help-format-refer) (cref . lyskom-help-format-cref) (section . lyskom-help-format-section) (TEXT . lyskom-help-format-TEXT)) ) (defun lyskom-help-get-section (section) (elt (assq section lyskom-help-data) 2)) (defun lyskom-help-show-section (section) "Format and insert section SECTION." (lyskom-do-help-format (lyskom-help-get-section section))) (defun lyskom-do-help-format (data) "Format ant insert help data DATA." (let ((inhibit-read-only t)) (cond ((symbolp (car data)) (funcall (cdr (assq (car data) lyskom-help-format-handlers)) data)) (t (lyskom-traverse el data (let ((tag (lyskom-help-data-get-tag el))) (funcall (cdr (assq tag lyskom-help-format-handlers)) el))))))) (defun lyskom-help-format-text-properties (data props) (let ((start (point-max-marker))) (set-marker-insertion-type start nil) (lyskom-traverse el (lyskom-help-data-get-data data) (lyskom-do-help-format el)) (add-text-properties start (point-max) props) (set-marker start nil))) (defun lyskom-help-format-section (section) "Format and insert section SECTION." (lyskom-do-help-format (lyskom-help-data-get-data section))) (defun lyskom-help-format-h1 (data) (lyskom-insert "\n\n") (lyskom-help-format-text-properties data '(face lyskom-help-h1-face)) (lyskom-insert "\n\n")) (defun lyskom-help-format-h2 (data) (lyskom-insert "\n") (lyskom-help-format-text-properties data '(face lyskom-help-h2-face)) (lyskom-insert "\n\n")) (defun lyskom-help-format-h3 (data) (lyskom-help-format-text-properties data '(face lyskom-help-h3-face)) (lyskom-insert "\n")) (defun lyskom-help-format-i (data) (lyskom-help-format-text-properties data '(face italic))) (defun lyskom-help-format-b (data) (lyskom-help-format-text-properties data '(face bold))) (defun lyskom-help-format-TEXT (data) (lyskom-insert (cdr data))) (defun lyskom-help-format-list (data) (lyskom-insert "\n") (when (lyskom-help-data-get-attr 'header data) (lyskom-insert (lyskom-help-data-get-attr 'header data)) (lyskom-insert "\n")) (lyskom-do-help-format (lyskom-help-data-get-data data)) (lyskom-insert "\n")) (defun lyskom-help-format-item (data) (lyskom-insert " * ") (lyskom-do-help-format (lyskom-help-data-get-data data)) (lyskom-insert "\n")) (defun lyskom-help-format-refer (data) (let* ((id (intern (lyskom-help-data-get-attr 'id data))) (section (lyskom-help-get-section id)) (string (or (lyskom-help-data-get-attr 'prompt section) (format "%s" id)))) (lyskom-format-insert "%#2@%#1s" string `(face underline mouse-face highlight lyskom-button t lyskom-button-text "" lyskom-button-type func lyskom-buffer ,(current-buffer) lyskom-button-arg (kom-help (,string . ,id))))) ) (defun lyskom-help-format-cref (data) (let* ((command (intern (lyskom-help-data-get-attr 'id data))) (command-name (lyskom-get-string command 'lyskom-command)) (keys (delq nil (mapcar (lambda (x) (if (and (arrayp x) (eq (elt x 0) 'menu-bar)) nil x)) (where-is-internal command)))) (heading (lyskom-format "%#1@%[%#2s%]%#3?b%[ (%#3s)%]%[%]" '(face italic) command-name (and keys (mapconcat 'key-description keys "; "))))) (lyskom-insert heading))) (defun lyskom-help-format-inline (data) (let* ((id (intern (lyskom-help-data-get-attr 'id data))) (section (lyskom-help-get-section id))) (cond (section (lyskom-do-help-format section)) (t (lyskom-insert (format "[%S]" id)))))) (defun lyskom-help-format-p (data) (let ((start (point-max-marker))) (set-marker-insertion-type start nil) (lyskom-traverse el (lyskom-help-data-get-data data) (lyskom-do-help-format el)) (save-excursion (save-restriction (narrow-to-region start (point-max)) (goto-char (point-min)) (while (re-search-forward "^\\s-+" nil t) (replace-match "" nil nil)) (lyskom-fill-region (point-min) (point-max)))) (lyskom-insert "\n\n"))) ;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: swedish-strings.el,v 44.396 2005/01/18 07:46:51 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: swedish-strings.el ;;;; ;;;; This file contains all strings in the LysKOM elisp client. ;;;; Language: Swedish. ;;;; ;;;; ================================================================ ;;;; (require 'lyskom-vars "vars") (require 'lyskom-language "language") (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: swedish-strings.el,v 44.396 2005/01/18 07:46:51 _cvs_pont_lyskomelisp Exp $\n")) ;;; ================================================================ ;;; The language definition (lyskom-define-language 'sv 'iso-8859-1 "Svenska" ) ;;; ================================================================ ;;; lyskom-edit-mode-map (defvar lyskom-sv-edit-mode-map nil) (lyskom-language-keymap lyskom-edit-mode-map sv lyskom-sv-edit-mode-map) ;;; Set the keymap for lyskom-edit-mode (defvar lyskom-sv-edit-prefix) (defvar lyskom-sv-edit-review-prefix) (defvar lyskom-sv-edit-insert-prefix) (defvar lyskom-sv-edit-aux-prefix) (defvar lyskom-sv-edit-add-prefix) (if lyskom-sv-edit-mode-map nil (setq lyskom-sv-edit-mode-map (make-sparse-keymap)) (define-prefix-command 'lyskom-sv-edit-prefix) (define-prefix-command 'lyskom-sv-edit-review-prefix) (define-prefix-command 'lyskom-sv-edit-insert-prefix) (define-prefix-command 'lyskom-sv-edit-aux-prefix) (define-prefix-command 'lyskom-sv-edit-add-prefix) (define-key lyskom-sv-edit-mode-map (kbd "*") 'kom-button-press-or-self-insert-command) (define-key lyskom-sv-edit-mode-map (kbd "=") 'kom-menu-button-press-or-self-insert-command) (define-key lyskom-sv-edit-mode-map (kbd "TAB") 'kom-edit-next-button-or-self-insert) (define-key lyskom-sv-edit-mode-map (kbd "M-TAB") 'kom-edit-prev-button) (define-key lyskom-sv-edit-mode-map (kbd "") 'kom-edit-prev-button) (define-key lyskom-sv-edit-mode-map (kbd "C-c") 'lyskom-sv-edit-prefix) (define-key lyskom-sv-edit-mode-map (kbd (lyskom-keys (lyskom-xemacs-or-gnu 'button2 'button2up))) 'kom-button-click-or-yank) (define-key lyskom-sv-edit-mode-map (kbd (lyskom-keys (lyskom-xemacs-or-gnu 'button2up 'button2))) 'kom-mouse-null) (define-key lyskom-sv-edit-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-sv-edit-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-sv-edit-prefix (kbd "C-x") 'lyskom-sv-edit-aux-prefix) (define-key lyskom-sv-edit-prefix (kbd "C-a") 'lyskom-sv-edit-add-prefix) (define-key lyskom-sv-edit-prefix (kbd "C-i") 'lyskom-sv-edit-insert-prefix) (define-key lyskom-sv-edit-prefix (kbd "TAB") 'lyskom-sv-edit-insert-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "C-]") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "C-}") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "C-å") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "C-Å") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [(control aring)] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [(control Aring)] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix "\205" 'lyskom-sv-edit-review-prefix) ; For windows and Emacs 19 (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "å") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "}") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix (kbd "]") 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [aring] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [Aring] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [å] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [Å] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [229] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [197] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [2277] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [2245] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [3909] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [3941] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [195 165] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [195 165] 'lyskom-sv-edit-review-prefix) (lyskom-try-define-key lyskom-sv-edit-prefix [(Ã)] (let ((k (make-sparse-keymap))) (define-key k (vector (intern "\205")) 'lyskom-sv-edit-review-prefix) (define-key k [¥] 'lyskom-sv-edit-review-prefix) k)) (define-key lyskom-sv-edit-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-edit-prefix (kbd "*") 'kom-button-press) (define-key lyskom-sv-edit-prefix (kbd "=") 'kom-menu-button-press) (define-key lyskom-sv-edit-prefix (kbd "C-c") 'kom-edit-send) (define-key lyskom-sv-edit-prefix (kbd "C-s") 'kom-edit-ispell-message) (define-key lyskom-sv-edit-prefix (kbd "C-k") 'kom-edit-quit) (define-key lyskom-sv-edit-prefix (kbd "C-y") 'kom-edit-insert-commented) (define-key lyskom-sv-edit-prefix (kbd "C-b") 'kom-edit-insert-buglist) (define-key lyskom-sv-edit-insert-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-edit-insert-prefix (kbd "C-k") 'kom-edit-insert-commented) (define-key lyskom-sv-edit-insert-prefix (kbd "C-y") 'kom-edit-insert-commented) (define-key lyskom-sv-edit-insert-prefix (kbd "1") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "2") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "3") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "4") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "5") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "6") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "7") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "8") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "9") 'kom-edit-insert-digit-text) (define-key lyskom-sv-edit-insert-prefix (kbd "SPC") 'kom-edit-insert-text) (define-key lyskom-sv-edit-insert-prefix (kbd "C-l") 'kom-edit-insert-link) (define-key lyskom-sv-edit-insert-prefix (kbd "C-i") 'kom-edit-insert-last-info-nodename) (define-key lyskom-sv-edit-add-prefix (kbd "C-m") 'kom-edit-add-recipient) (define-key lyskom-sv-edit-add-prefix (kbd "") 'kom-edit-add-recipient) (define-key lyskom-sv-edit-add-prefix (kbd "C-e") 'kom-edit-add-copy) (define-key lyskom-sv-edit-add-prefix (kbd "C-b") 'kom-edit-add-bcc) (define-key lyskom-sv-edit-add-prefix (kbd "C-f") 'kom-edit-move-text) (define-key lyskom-sv-edit-add-prefix (kbd "C-j") 'kom-edit-add-recipient) (define-key lyskom-sv-edit-add-prefix (kbd "") 'kom-edit-add-recipient) (define-key lyskom-sv-edit-add-prefix (kbd "C-k") 'kom-edit-add-comment) (define-key lyskom-sv-edit-add-prefix (kbd "C-x") 'kom-edit-add-cross-reference) (define-key lyskom-sv-edit-add-prefix (kbd "?") 'lyskom-help)) (define-key lyskom-sv-edit-aux-prefix (kbd "C-p") 'kom-edit-add-personal-comments) (define-key lyskom-sv-edit-aux-prefix (kbd "C-n") 'kom-edit-add-no-comments) (define-key lyskom-sv-edit-aux-prefix (kbd "C-l") 'kom-edit-add-world-readable) (define-key lyskom-sv-edit-aux-prefix (kbd "C-b") 'kom-edit-add-read-confirm-request) (define-key lyskom-sv-edit-review-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-edit-review-prefix (kbd "C-k") 'kom-edit-show-commented) (define-key lyskom-sv-edit-review-prefix (kbd "k") 'kom-edit-show-commented) (defconst lyskom-strings-missing '()) ;;; The alist formely known as lyskom-strings (lyskom-language-strings local lyskom-message sv '( ;; From vars.el: ;; From komtypes.el: nil ;; From clienttypes.el: nil ;; From startup.el: (server-q . "LysKOM-server? (%#1s) ") (try-connect . "LysKOM elisp-klient version %#1s.\nFörsöker koppla upp mot %#2s.\n") (too-old-server . "Servern är för gammal för den här versionen av klienten.") (connection-done . "Uppkopplingen klar. Serverns versionsnummer är %#1s.\n\n") (what-is-your-name . "Vad heter du? ") (password . "Lösenord? ") (wrong-password . "Fel lösen.\n") (wrong-password-help . " Du kan skicka e-mail till någon av nedanstående adresser för att få ett nytt lösenord eller för att få din gamla person raderad så att du kan skapa en ny:\n") (wrong-password-email . "* %#1t\n") (are-logged-in . "Du är nu inloggad. Vänta ett tag.\n") (you-have-motd . "\nDu har en lapp på dörren:\n\n") (server-has-motd . "Servern har ett loginmeddelande:\n") (lyskom-motd-was-garbed . "\nLoginmeddelandet finns inte! Det meddelande som ska visas efter inloggning har försvunnit. Kontakta LysKOM-administratören.\n") (first-greeting . "%#1s Det tycks vara första gången du använder LysKOM. Välkommen! Kontrollera att du stavat ditt namn rätt. Använd gärna ditt fullständiga namn och organisation, t ex \"Eskil Block, FOA\". Om du stavat ditt namn fel, eller vill ändra ditt namn, svara nej på frågan nedan. Observera att all information än så länge sparas så att vem som helst kan läsa den. Dock är lösenordet krypterat. Om du är osäker på hur man använder LysKOM kan du hämta en manual via anonym ftp från ftp.lysator.liu.se. Fråga din systemadministratör om du är osäker. Du kan även skriva \"?\" för kommandot \"Hjälp\". ") (is-name-correct . "Är namnet %#1s korrekt? ") (personal-password . "Ange ett personligt lösen: ") (repeat-password . "Repetera för kontroll: ") (repeat-failure . "Du angav inte samma lösenord bägge gångerna.\n") (could-not-create-you . "Det gick inte att skapa personen.\n") (presentation-subject . "%#1s") (presentation-form . "\ Namn: Adress: Stad: Telefon: E-post: WWW: Annat: ") (presentation-help . "Du skriver just nu din presentation.\n") (not-present-anywhere . "Ej närvarande i något möte.") (in-secret-conference . "Hemligt möte (%#1d).") (start-new-session-same-server . "Du kör redan mot den servern. Vill du starta en ny session? ") (new-session-in-buffer . "\n\n---- Ny session startad %s ----\n\n") (warning-about-uncompiled-client . " OBS: LysKOM-klienten är inte kompilerad. För att öka prestanda bör du köra en kompilerad version av klienten. Läs i den medföljande README-filen hur man gör det. ") ;; From internal.el: (shaky-tcp . "Nu når jag inte servern. TCP/IP-förbindelsen är skakig%#1s") (retrying-tcp . "Jag försöker igen.") ;; From parse.el: (protocol-error . "protokollfel: %s") ;; From services.el: (interrupted . "Kommandot avbrutet\n") ;; From cache.el: ;; No entries. ;; From commands1.el: (appreciation . "Du är mycket vacker och mycket klok. Många älskar dig både till kropp och till själ. Du kommer att överösas med rikedom och få stor lycka i ditt liv. Var glad att just du är du. Det har du all anledning att vara. Fantomen önskar dig en bra dag.\n\n") (abuse . "Du är mycket ful och mycket dum. Många hatar dig både till kropp och till själ. Du kommer att överösas med sjukdomar och inte få någon som helst lycka i ditt liv. Du borde verkligen ta dig samman och göra något av ditt liv även om det inte är mycket att starta med. Guran vill helst sätta en giftpil i dig.\n\n") (what-conf-to-delete . "Vilket möte/person vill du utplåna: ") (what-conf-to-change . "Vilket möte vill du ändra: ") (confirm-delete-pers-or-conf . "Ta bort %#1s %#2s? ") (the-pers . "personen") (the-conf . "mötet") (deletion-not-confirmed . "Utplåningen avbruten\n") (somebody-else-deleted-that-conf . "Någon annan tog precis bort mötet.\n") (conf-is-deleted . "Ok, nu är %#1s utplånad.\n") (you-could-not-delete . "%#1M kunde inte utplånas av dig.\n") (you-have-deleted-yourself . "Du har utplånat dig själv.\n") (what-text-to-delete . "Vilket inlägg skall tas bort? ") (delete-marked-text . "Inlägget är %#1s. Ta bort ändå? ") (delete-marked-by-you . "markerat av dig") (delete-marked-by-you-and-others . "markerad av dig och %#1?d%[någon annan%]%[%#1d andra%]") (delete-marked-by-several . "markerat av %#1d person%#1?d%[%]%[er%]") (delete-commented-text-help . "\ Inlägget du håller på att radera har kommentarer. Om du tar bort inlägget så kommer dessa kommentarer att förlora sitt sammanhang. Detta irriterar många läsare. Överväg att flytta inlägget till ett annat möte istället för att radera det.") (delete-commented-text . "Inlägget har kommentarer. Radera ändå? ") (really-delete-commented-text . "Att radera kommenterade inlägg irriterar många läsare. Radera ändå?") (deleting-text . "Radering av text %#1:n...") (presentation-for-whom . "Se presentation för vilket möte/person? ") (unread-presentation-for-whom . "Oläsmarkera presentation för vilket möte/person? ") (text-to-see-author-of . "Se presentation för vilket inläggs författare? ") (text-to-unread-author-of . "Oläsmarkera presentation för vilket inläggs författare? ") (somebody-deleted-that-conf . "Någon tog precis bort mötet.\n") (review-presentation-of . "Återse presentation av %#1M.\n") (has-no-presentation . "%#1:M har ingen presentation.\n") (have-to-read . "Du måste läsa ett inlägg först.\n") (no-comment-to . "Det finns inget kommenterat inlägg att titta på.\n") (no-text-at-point . "Det finns inget inlägg vid markören.\n") (what-ancestor . "Vilken av de kommenterade texterna önskas? ") (who-letter-to . "Vem vill du skicka brev till? ") (who-send-text-to . "Vart vill du skicka inlägget? ") (has-motd . "%#1P har en lapp på dörren:\n\n") (motd-persist-q . "Vill du fortfarande skriva texten? ") (who-to-add . "Vem vill du addera? ") (where-to-add . "Vilket möte skall han/hon adderas till? ") (where-to-add-self . "Vilket möte vill du bli medlem i? ") (priority-q . "Prioritet på ditt medlemskap i mötet? (0 (låg) - 255 (hög)) ") (other-priority-q . "Prioritet på den adderades medlemskap i mötet? (0 (låg) - 255 (hög)) ") (done . "klart.\n") (cancelled . "avbrutet.\n") (nope . "det gick inte.\n") (add-already-member . "%#2P är redan medlem i %#1M.\n") (you-already-member . "Du är redan medlem i %#1M.\n") (cant-find-supervisor . "Hittar inte organisatören för %#1M.\n") (is-read-protected-contact-supervisor . "%#1M är slutet. Skicka ett brev till %#2P för medlemskap.\n") (conf-does-not-exist . "\nMötet finns inte.\n") (who-to-exclude . "Vem vill du utesluta? ") (where-from-exclude . "Vilket möte skall han/hon uteslutas ifrån? ") (leave-what-conf . "Vilket möte vill du gå ur? ") (error-fetching-person . "Fel i personhämtningen.\n") (error-fetching-conf . "Fel i möteshämtningen.\n") (name-of-conf . "Vad ska mötet heta? ") (anyone-member . "Får vem som helst bli medlem? ") (secret-conf . "Hemligt möte? ") (comments-allowed . "Får man skriva kommentarer? ") (anonymous-allowed . "Får man skriva anonyma texter? ") (secret-members-allowed . "Får man gå med som hemlig medlem? ") (what-comment-no . "Kommentera text nummer: ") (what-footnote-no . "Fotnotera text nummer: ") (what-private-no . "Personligt svar till text nummer: ") (quit-in-spite-of-unsent . "Vill du avsluta sessionen trots oinskickat inlägg? ") (really-quit . "Vill du verkligen avsluta sessionen? ") (session-ended . " ***************************** LysKOM-sessionen är avslutad. *****************************\n") (session-auto-ended . " =========================================================== Kopplar ned från LysKOM eftersom LysKOM är fullt och du har läst klart allting. Kom tillbaks senare. ===========================================================\n\n") (session-ended-long . " ******************************************************************************* LysKOM-sessionen är avslutad. ******************************************************************************* ") (session-auto-ended-long . " =============================================================================== Kopplar ned från LysKOM eftersom LysKOM är fullt och du har läst klart allting. Kom tillbaks senare. =============================================================================== \n") (what-to-change-pres-you . "Vilket möte/person vill du ändra presentationen för: ") (what-to-change-faq-you . "Vilket möte vill du ändra FAQ för: ") (who-to-put-motd-for . "Vilket möte/person vill du sätta lapp på dörr för: ") (what-to-set-pres-you . "Vilket möte/person vill du sätta presentationen för: ") (what-text-to-set-as-pres-no . "Vilket inlägg vill du ska vara den nya presentationen: ") (what-to-set-motd-you . "Vilket möte/person vill du sätta lapp på dörr för: ") (what-text-to-set-as-motd-no . "Vilket inlägg vill du ska vara den nya lappen: ") (conf-already-has-pres . "Mötet/personen har redan en presentation. Fortsätt ändå? ") (conf-already-has-motd . "Mötet/personen har redan en lapp på dörren. Fortsätt ändå? ") (setting-conf-pres . "Sätter presentation för %#1M till text %#2n...") (setting-conf-motd . "Sätter lapp på dörren för %#1M till text %#2n...") (who-to-remove-pres-for . "Vilket möte/person vill du ta bort presentationen från: ") (removing-pres-for-conf . "Tar bort presentation (text %#2n) från %#1M...") (cant-get-conf-stat . "Kan ej hämta mötesstatus för mötet.\n") (go-to-conf-p . "Gå till möte: ") (want-become-member . "Vill du bli medlem? ") (no-ok . "Nehej.\n") (who-to-remove-motd-for . "Vilket möte/person vill du ta bort lapp på dörr för: ") (conf-all-read . "inga olästa") (no-in-conf . "Du är inte närvarande i något möte.\n") (search-for-pers . "Ange sökvillkor (RETURN för alla personer): ") (search-for-conf . "Ange sökvillkor (RETURN för alla möten): ") (search-re . "Ange sökuttryck (reguljärt uttryck): ") (search-re-for-what . "Vad vill du söka? ") (search-re-persons . "pSök personer") (search-re-confs . "mSök möten") (search-re-all . "bSök alla") (no-matching-confs . "Inga möten uppfyller sökvillkoret \"%#1s\".\n") (no-matching-perss . "Inga personer uppfyller sökvillkoret \"%#1s\".\n") (no-matching-anys . "Inga personer eller möten uppfyller uttrycket \"%#1s\".\n") (no-confs-exist . "Det finns inga möten i databasen.\n") (no-pers-confs-exist . "Det finns inga möten eller personer i databasen.\n") (list-confs-created-by . "Lista ägda möten för: ") (listing-confs-created-by . "Ägda möten för %#1P\n\ S=Skapat, O=Organisatör, M=Brevlåda som supermöte; S=Slutet, H=Hemligt\n") (list-pers-confs-created-by . "Lista ägda möten (med brevlådor) för: ") (getting-all-confs . "Hämtar en lista av alla möten från servern...") (getting-all-pers-confs . "Hämtar en lista av alla personer och möten från servern...") (getting-all-confs-done . "Hämtar en lista av alla möten från servern...klart") (getting-all-pers-confs-done . "Hämtar en lista av alla personer och möten från servern...klart") (finding-created-confs . "Söker ägda möten (%#1d av %#2d klart)") (finding-created-pers-confs . "Söker ägda möten (med brevlådor) (%#1d av %#2d klart)") (no-created-confs . "%#1P är inte skapare, organisatör eller supermöte för något möte.\n") (name-to-be-changed . "Ange det namn som skall ändras: ") (no-such-conf-or-pers . "Mötet eller personen finns ej.\n") (new-name . "Nytt namn: ") (new-paren . "Ny parentes: ") (too-many-parens-in-name . "Namnet innehåller mer än en parentes. Använd \"Ändra namn\" istället.\n") (no-paren-in-name . "Namnet innehåller ingen parentes.\n") (who-to-change-supervisor-for . "Vem vill du ändra organisatör för? ") (new-supervisor . "Ny organisatör: ") (text-to-mark . "Vilket inlägg vill du markera? ") (text-to-unmark . "Vilket inlägg vill du avmarkera? ") (what-mark . "Vilken typ av markering vill du sätta (namn eller 0-255)? ") (erroneous-mark . "Felaktig markeringstyp.\n") (want-to-create-symbolic-mark . "Markeringstypen \"%#1s\" finns inte. Vill du skapa den? ") (creating-symbolic-mark-type . "Skapar markeringstypen \"%#1s\" (%#2d).\n") (no-mark-types-left . "Ledsen, det finns inga lediga markeringstyper. Rensa bland de gamla först.") (unmarking-textno . "Avmarkering av text %#1n...") (marking-textno . "Markering av text %#1n med markering %#2?b%[\"%#2s\" (%#3d)%]%[%#3d%]...") (list-which-mark . "Lista vilken markeringstyp (namn eller 0-255, RET för alla)? ") (new-passwd-again . "Mata in det nya lösenordet igen för kontroll: ") (what-mark-to-unread . "Oläsmarkera vilken markeringstyp (namn eller 0-255, RET för alla)? ") (what-mark-to-view . "Återse vilken markeringstyp (namn eller 0-255, RET för alla)? ") (whos-passwd . "Vem vill du ändra lösenord för? ") (old-passwd . "Mata in ditt nuvarande lösenord: ") (new-passwd . "Mata in det nya lösenordet: ") (changing-passwd . "Ändrar lösenordet...") (retype-dont-match . "Lösenorden är inte samma. Gör om.\n") (palindrome . " (en palindrom!)") (lyskom-name . "Användare") (is-in-conf . "Närvarande i möte") (from-machine . "Kör från") (is-doing . "Gör") (connection-time . "Loggade in") (active-last . "Aktiv senast") (active . "Aktiv") (lyskom-client . "Klient") (text-to-add-recipient . "Vilket inlägg vill du addera mottagare till:") (text-to-add-copy . "Vilket inlägg vill du addera en extra kopia till:") (text-to-add-bcc . "Vilket inlägg vill du skicka som dold kopia:") (text-to-delete-recipient . "Vilket inlägg vill du subtrahera mottagare från:") (text-to-move . "Vilket inlägg vill du flytta:") (text-tree-to-move . "Vilket inlägg är rot till trädet du vill flytta:") (text-to-add-comment-to . "Vilket inlägg vill du addera en kommentar till:") (text-to-delete-comment-from . "Vilket inlägg vill du subtrahera en kommentar från:") (text-to-add-footnote-to . "Vilket inlägg vill du addera en fotnot till:") (text-to-delete-footnote-from . "Vilket inlägg vill du subtrahera en fotnot från:") (text-to-add-cross-reference-to . "Vilket inlägg vill du addera en referens till:") (text-has-no-recipients-r . "Inlägg %#1n har inga mottagare\n") (cant-move-from-to-same . "Mötet du flyttar till kan inte vara samma som du flyttar från.\n") (where-on-list-q . "Placering på listan? (0-%#1d) ") (accepting-invitation . "Accepterar inbjudan till %#2M%#3?b%[ %#3s%]%[%]...") (member-in-conf . "Bli medlem i %#2M%#3?b%[ %#3s%]%[%]...") (member-in-conf-with-low-priority . "%#1M har lägre prioritet än din läsnivå och kommer därför inte att visas.\n") (member-in-conf-with-unread-date . "med olästa från %#3d %#2s %#1d") (member-in-conf-with-unread . "med %#1d olästa") (add-member-in . "Addera %#1P som medlem i %#2M...") (change-priority-for-q . "Ändra prioritet för möte: ") (cant-change-priority-of-passive . "Kan inte ändra prioritet på passiva medlemskap.\n") (change-priority-for . "Ändra prioritet på %#2M...") (unsubscribe-to . "Utträda ur %#1M...") (unsubscribe-to-2 . "Utträda ur %#1M%#2s...") (confirm-each-join . "Vill du bekräfta medlemskap i enskila möten? ") (confirm-each-msg . "Vill du bekräfta mottagande av gruppmeddelande i enskila möten? ") (receive-each-msg . "Vill du ta emot gruppmeddelande i alla möten? ") (no-confirm-each-sure . "Är du helt säker på att du vill gå med i %#1d möten automatiskt? ") (confirm-join . "Gå med i %#1M? ") (getting-all-confs . "Hämtar en lista med alla möten...") (getting-all-confs-progress . "Hämtar en lista med alla möten (%#1d/%#2d)...") (getting-all-confs-done . "Hämtar en lista med alla möten...klart") (unsub-all-skipping-letterbox . "nix\nMötet är din brevlåda.\n") (unsub-all-skipping-supervised . "nix\nDu är organisatör för mötet.\n") (unsub-secret-conf-q . "%#1M är hemligt. Vill du gå ur mötet ändå? ") (unsub-all-secret . "aGå ur alla hemliga möten") (unsub-closed-conf-q . "%#1M är slutet. Vill du gå ur mötet ändå? ") (unsub-all-closed . "aGå ur alla slutna möten") (unsub-open-conf-q . "Vill du gå ur %#1M? ") (unsub-all-open . "aGå ur alla öppna möten") (abc-yes . "jJa") (abc-no . "nNej") (abc-yes-all . "aJa till alla") (abc-no-all . "xNej till alla") (move-tree-move . "fFlytta") (move-tree-sub . "sSubtrahera") (move-tree-add . "aAddera") (move-tree-ign . "iIngenting") (move-tree-jump . "hHoppa") (move-tree-quit . "qAvbryt") (move-tree-add-rcpt-type . "Addera som: ") (move-tree-rcpt . "mMottagare") (move-tree-cc . "eExtra kopia") (move-tree-bcc . "dDold kopia") (move-tree-leave-cc-q . "Lämna ursprungsmottagare som extrakopiemottagare? ") (exclude-from . "Utesluta %#1P från %#2M...") (unsubscribe-failed . "\nDet gick inte. %#1P var kanske aldrig medlem i %#2M?\n") (activate-mship . "Bli aktiv medlem i %#1M...") (activate-mship-done . "Du är nu åter aktiv medlem i %#1M.\n") (passivate-done . "Du är nu passiv medlem i %#1M. Utträd ur mötet en gång till för gå ur helt.\n") (You . "Du") (could-not-create-conf . "Mötet \"%#1s\" kunde ej skapas.\n") (created-conf-no-name . "Möte nummer %[%#3@%#1:m %#2:M%], skapat.\n") (cant-read-textno . "Du får inte läsa text %#1:n.\n") (not-supervisor-for . "Du är inte organisatör för %#1M.\n") (not-supervisor-for-server . "Du är inte administratör för LysKOM-servern.\n") (go-to-conf . "Gå till %#1M.\n") (cant-go-to-his-mailbox . "Du får inte gå till %#1Ms brevlåda.\n") (not-member-of-conf . "Du är inte medlem i %#1M.\n") (about-to-change-name-from . "%#1M\n") (change-name-done . "Klart. Nytt namn: %[%#2@%#1:M%].\n") (change-name-nope . "Det gick inte bra att ändra till %#1s.\nFelkod %#3d. %#2s.\n") (change-supervisor-from-to . "Ändra organisatör för %#1M till %#2P...") (change-supervisor-nope . "\nDet gick inte. Kanske du inte får ändra organisatör för %#1M?\n") (no-marked-texts . "Du har inga markerade inlägg.\n") (no-marked-texts-mark . "Du har inga markerade inlägg med markeringstypen \"%#1s\".\n") ;;; For later ; (northward . "norrut") ; (southward . "söderut") ; (permanent-sundown . "Solen kommer inte att gå upp. Flytta %#1s!") ; (permanent-sunup . "Solen kommer inte att gå ned. Flytta %#1s!") ; (sunup-soon . "Solen går snart upp") ; (sundown-recently . "Solen gick nyligen ned") ; (after-sunset . "Solen har gått ned") ; (before-sunup . "Solen har inte gått upp ännu") ; (sun-is-up . "Solen är uppe") ;;; (weekdays . ["söndag" "måndag" "tisdag" "onsdag" "torsdag" "fredag" "lördag" "söndag"]) (weekdays-short . ["sön" "mån" "tis" "ons" "tor" "fre" "lör" "sön"]) (time-is . "Det är %#1s%#2s (enligt servern).") (time-is-week . "Det är %#1s%#2s, vecka %#3d (enligt servern).") (xmaseve . "\nJulafton! Har du öppnat dina julklappar än?") (xmasday . "Juldagen.\nDu har väl varit i julottan?") (newyearday . "Nyårsdagen. Gott nytt %#1d!") (newyearevelate . "Mindre än en timme kvar av %#1d...") (newyeareve . "Nyårsafton.") (cgdag . "Valborgsmässoafton.\nKonungens födelsedag.") (sixjune . "Sveriges nationaldag och svenska flaggans dag.") (holdnose . "Håll för näsan...") (lysbday . " På denna dag, år 1973, grundades Lysator, och det var en stor dag i svensk datorhistoria. Läs mer på http://www.lysator.liu.se/history/") (13dayxmas . "Trettondedag jul (\"Trettondagen\").") (20dayxmas . "Tjugondedag jul (\"Tjugondag Knut\").") (kyndeldag . "Kyndelsmässodagen.") (skottdag . "Skottdagen.") (intwomday . "Internationella kvinnodagen.") (mariebdag . "Marie bebådelsedag.\nFram med våffeljärnet!") (johannesddag . "Johannes Döparens dag.") (fnday . "FN-dagen.") (allhelgonadag . "Allhelgonadagen.") (varnlosdag . "Värnlösa barns dag.") (luciaday . "\nLuciadagen! Glöm inte att lussa för dina kollegor.") (total-users . " Sammanlagt %#1d användare (%#2s).\n") (total-users-sans-date . " Sammanlagt %#1d användare\n") (total-visible-users . " Sammanlagt %#1d synlig%#1?d%[%]%[a%] användare (%#2s).\n") (total-active-users . " Sammanlagt %#1d aktiv%#1?d%[%]%[a%] användare (%#2s).\n") (total-visible-active-users . " Sammanlagt %#1d synlig%#1?d%[%]%[a%] aktiv%#1?d%[%]%[a%] användare (%#2s).\n") (client-statistics . " Klienternas fördelning:\n") (client-statistics-line . " %4#2d %#1s%#3?d%[%]%[ [%#3d varianter]%]") (who-to-add-q . "Vilket möte/person vill du addera som mottagare? ") (who-to-add-copy-q . "Vilket möte/person vill du addera som kopiemottagare? ") (who-to-add-bcc-q . "Vilket möte/person vill du addera som mottagare av en dold kopia? ") (add-footnotes-too-q . "Försök addera mottagare till fotnoter också? ") (add-attachments-too-q . "Försök addera mottagare till bilagor också? ") (really-add-as-recpt-q . "Skall framtida kommentarer till inlägget också skickas till %#1M? ") (who-to-sub-q . "Vilket möte/person vill du subtrahera som mottagare? ") (sub-footnotes-too-q . "Försök subtrahera mottagare från fotnoter också? ") (sub-attachments-too-q . "Försök subtrahera mottagare från bilagor också? ") (who-to-move-from-q . "Från vilket möte vill du flytta texten? ") (who-to-move-to-q . "Vart vill du flytta texten? ") (who-to-move-to-or-sub-q . "Vart vill du flytta texten (tomt för att bara subtrahera)? ") (move-footnotes-too-q . "Försök flytta fotnoter också? ") (move-attachments-too-q . "Försök flytta bilagor också? ") (move-text-not-recipient . "har ej rätt mottagare.\n") (adding-name-as-recipient . "Adderar %#1M som mottagare till text %#2n...") (adding-name-as-copy . "Adderar %#1M som kopiemottagare till text %#2n...") (adding-name-as-bcc . "Adderar %#1M som dold kopiemottagare till text %#2n...") (remove-name-as-recipient . "Subtraherar %#1M som mottagare från text %#2n...") (adding-cross-reference . "Adderar referens...") (error-recipient-limit . "Text %#1n har för många mottagare.\n") (error-already-recipient . "%#2M är redan mottagare till inlägg %#1n.\n") (error-permission-denied-add-recpt . "Bara författaren till %#1n eller organisatören för %#2M kan ändra mottagartyp.\n") (error-permission-denied-sub-recpt . "Bara författaren till %#1n eller organisatören för %#2M kan subtrahera mottagare.\n") (error-access-denied-add-recpt . "Du får inte addera inlägg till %#2M.\n") (error-not-recipient . "%#2M är inte mottagare till inlägg %#1n.\n") (moving-tree-what-action-q . "Vad vill du göra? ") (moving-cant-read . "Det gick inte att inte flytta text %#1n (kan inte läsa texten).\n") (moving-name . "Flyttar text %#3n från %#1M till %#2M...") (moving-already-moved . "Inlägg %#1n har inte %#2M som mottagare.\nFlyttar inte inlägget eller dess kommentarsträd.\n") (text-to-add-q . "Vilket inlägg vill du addera som kommentar till %#1n? ") (text-to-remove-q . "Vilket inlägg vill du subtrahera som kommentar från %#1n? ") (text-to-add-footn-q . "Vilket inlägg vill du addera som fotnot till %#1n? ") (text-to-remove-footn-q . "Vilket inlägg vill du subtrahera som fotnot från %#1n? ") (add-comment-to . "Adderar text %#1n som kommentar till text %#2n...") ; (sub-comment-to . "Subtraherar text %#1n som kommentar till text %#2n...") (add-footnote-to . "Adderar text %#1n som fotnot till text %#2n...") ; (sub-footnote-to . "Subtraherar text %#1n som fotnot till text %#2n...") (comment-keep-recpt-p ."Ska %#1s vara mottagare? ") (comment-all-relevant-p . "Inlägget har flera mottagare. Är alla relevanta? ") (please-edit-recipients . "Ändra mottagarlistan och skicka in inlägget igen.") (checking-rcpt . "Kontrollerar mottagare...") (checking-rcpt-done . "Kontrollerar mottagare...klart") (checking-comments . "Kontrollerar kommenterade texter...") (checking-comments-done . "Kontrollerar kommenterade texter...klart") (please-check-commented-texts . "Återse de kommenterade texterna och deras kommentarer.") (have-unread-comment . "Skicka in trots olästa kommentarer till text %#1n? ") (duplicate-recipients . "Kan inte skicka in texten. En mottagare förekommer flera gånger (%#1M)") (no-recipients . "Kan inte skicka in texten. Inga mottagare har angivits.") (add-recipient-p . "Addera mottagare %#2?b%[ %#2M för att nå%]%[%] %#1P? ") (matching-regexp . "Möten/personer som matchar '%#1s'\n") (matching-regexp-perss . "Personer som matchar '%#1s'\n") (matching-regexp-confs . "Möten som matchar '%#1s'\n") (who-is-active-all . "Visar alla sessioner.\n") (who-is-active-last-minutes . "Visar alla sessioner som har varit aktiva de senaste %#1d minuterna.\n") (showing-invisibles . "Visar osynliga sessioner.\n") (null-who-info . "Det finns inga (aktiva) inloggade.\n") (no-other-lyskom-r . "Det finns inga fler aktiva LysKOM-sessioner.\n") (no-lyskom-session . "Det finns ingen aktiv LysKOM-session.") (no-other-unread-lyskom-r . "Hittar ingen annan LysKOM-session med olästa.\n") (no-unread-lyskom-r . "Hittar ingen aktiv LysKOM-session med olästa.\n") (no-unread-lyskom . "Hittar ingen aktiv LysKOM-session med olästa.") (who-is-on-in-what-conference . "Vilka i vilket möte: ") (who-is-present-in-what-conference . "Vilka närvarande i vilket möte: ") (who-is-friend . "Visar endast vänner.\n") (who-is-active-and-member . "Visar endast medlemmar i %#1M.\n") (who-is-active-and-present . "Visar endast medlemmar närvarande i %#1M.\n") (personal-comment-to-anonymous . "Det går inte att skriva ett personligt svar på ett anonymt inlägg.\n") ;; From commands2.el: (your-memberships . "Ditt medlemskap i olika KOM-möten:\n") (memberships-header . "Senast inne Prio Olästa Mötesnamn\n") (memberships-line . "%16#1s %#2d\t%#3d\t%#4M\n") (conf-for-status . "Vilket möte vill du se statusen för? ") (no-such-conf . "Mötet finns ej.\n") (status-record . "Status för möte %#1M (%#1m)%#2s\n\n") (change-type-prompt . "Ändra mötestyp för möte %#1M (%#1m) (%#2s)...") (Mailbox . "Brevlåda") (Protected . "Hemligt") (no-comments . "original") (closed . "slutet") (allow-anon . "anonymt ok") (allow-secret . "hemliga medl") (created-by . "Skapat av person %25#1p %#3s(%#2P)\n") (created-at . "Skapad:%35#1s\n") (members . "Antal medlemmar: %25#1d\n") (conf-allows-secret-members . "Hemliga medlemmar: %#1s\n") (conf-allows-anon-texts . "Anonyma inlägg: %#1s\n") (anon-texts-permitted . "Anonyma inlägg är tillåtna") (anon-texts-not-permitted . "Anonyma inlägg är inte tillåtna") (secret-members-permitted . "Hemliga medlemmar är tillåtna") (secret-members-not-permitted . "Hemliga medlemmar är inte tillåtna") (garb-nice . "Livslängd på inlägg: %14#1d dag%#1?d%[%]%[ar%]\n") (keep-commented . "Minsta livslängd för kommenterade inlägg: %#1d dag%#1?d%[%]%[ar%]\n") (lowest-local-no ."Lägsta existerande lokala nummer: %8#1d\n") (highest-local-no . "Högsta existerande lokala nummer: %8#1d\n") (last-text-time . "Tid för senaste inlägg: %18#1s (står det i din cache)\n") (no-of-motd . "Lapp på dörren i text nummer: %12#1n\n") (pers-has-privileges . "Rättigheter: %#1s\n") (pers-has-privileges-2 . "%28#1s") (superconf-is-no-name . "Supermöte: %25#1m %#3s(%#2M)\n") (permitted-submitters-no-name . "Tillåtna författare:%22#1m %#3s(%#2M)\n") (supervisor-is-no-name . "Organisatör: %25#1p %#3s(%#2P)\n") (presentation-no . "Presentation: %25#1n\n") (conf-mship-priority . "Prioritet: %25#1n%#2?b%[ %#2s%]%[%]\n") (conf-has-motd . "\n%#1M har en lapp på dörren:\n") (status-conf-generic . "%-40#1s %#2s\n") (status-aux-item . "Okänd tilläggsinformation: %15#1s%#3s (skapad av %#2M)\n") (conf-mx-list-name . "Importerad mailinglista: %#1s %#2s\n") (conf-mx-refuse-import . "Vägra import av: %#1s %#2s\n") (recommended-conf-aux . "Rekommenderat möte: %#1M <%#1m> %#2s\n") (bad-recommended-conf-aux . "Rekommenderat möte: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s\n") (status-read-faq-aux-item . "Läst FAQ: %15#2n för %#1?z%[%#1M <%#1m>%]%[servern%] %#3s\n") (bad-status-read-faq-aux-item . "Läst FAQ: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s\n") (status-rejected-recommendation-aux-item . "Avvisad mötesrekommendation: %#1M %#2s\n") (bad-status-rejected-recommendation-aux-item . "Avvisad mötesrekommendation: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s\n") (status-send-comments-to . "Dirigera om kommentarer till: %#1M <%#1m> %#2s\n") (bad-status-send-comments-to . "Dirigera om kommentarer till: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s\n") (Everybody . "Alla") (show-members-list-also-q . "Vill du se medlemslistan också? ") (show-membership-info-q . "Visa medlemskapsinformation och antalet olästa? ") (conf-has-these-members . "\n%#1M har följande medlemmar:\n") (conf-has-no-members . "\n%#1M har inga medlemmar.\n") (member-list-header . "\nSenast inne Osett Namn\n") (secret-membership . "*** Hemlig rad ***\n") (conf-membership-line . "%#4@%#1s%#2M %#3s\n") (conf-membership-line-2 . " Adderad %#1s av %#2P\n") (pers-for-status . "Vem vill du se statusen för? ") (text-to-see-author-status-of . "Vilken texts författare vill du statusen för? ") (no-such-pers . "Det finns ingen sådan person.\n") (pers-status-record . "Status för person %#1P (%#1p)\n") (created-time . "Skapad:%34#1s\n\n") (created-confs . "Skapade möten:%27#1d\n") (created-persons . "Skapade personer:%24#1d\n") (created-texts . "Skapade texter:%26#1d\n") (created-lines . "Skapade rader:%27#1d\n") (created-chars . "Antal skapade tecken:%20#1d\n") (no-of-sessions . "Antal sessioner:%25#1d\n") (present-time-d-h-m-s . "Närvarotid:%19#1d d %02#2d:%02#3d:%02#4d\n") (last-log-in . "Senaste in-/utloggning:%18#1s\n") (user-name . "Användare: %30#1s\n") (read-texts . "Lästa texter:%28#1d\n") (marked-texts . "Markerade texter:%24#1d\n") (time-for-last-letter . "Tid för senaste brev:%20#1s (står det i din cache)\n") (superconf . "Supermöte:%31#1m %#3s(%#2M)\n") (supervisor . "Organisatör:%29#1p %#3s(%#2P)\n") (member-of-confs . "Medlem i (antal möten):%18#1d\n") (presentation . "Presentation: %24#1n\n") (show-membership-list-also-q . "Vill du se vilka möten personen är medlem i också? ") (not-allowed-see-confs . "%#1P är inte medlem i några möten.\n") (is-member-of . "\n%#1P är medlem i följande möten:\n") (membership-list-header . "\nSenast inne Osett Namn\n") (pers-membership-line . "%#5@%#1s%#2s%#3M %#4s\n") (pers-membership-line-2 . " Adderad %#1s av %#2P\n") (is-supervisor-mark . "O ") (who-to-send-message-to . "Vem vill du skicka meddelandet till? (%#1s) ") (send-empty-message-p . "Meddelandet är tomt. Vill du ändå skicka det? ") (his-total-unread . "\n%#1M har totalt %#2d olästa (plus %#3d i passiva medlemskap).\n") (message-prompt . "Meddelande%#1?z%[%]%[ (till alla inloggade)%]: ") (message-sent-to-user . "\ %[%#3$\ ================================================================ %]%[%#4$\ Ditt meddelande till %#2M: %#1t %]%[%#3$\ ---------------------------------------------------------------- %]") (message-sent-to-all . "\ %[%#3$\ ================================================================ %]%[%#4$\ Ditt alarmmeddelande löd: %#1t %]%[%#3$\ ---------------------------------------------------------------- %]") (message-sent-to-user-long . "\ %[%#3$\ =============================================================================== %]%[%#4$\ Ditt meddelande till %#2M: %#1t %]%[%#3$\ ------------------------------------------------------------------------------- %]") (message-sent-to-all-long . "\ %[%#3$\ =============================================================================== %]%[%#4$\ Ditt alarmmeddelande löd: %#1t %]%[%#3$\ ------------------------------------------------------------------------------- %]") (message-use-alarm-instead . "Använd kommandot %#1s för att skicka alarmmeddelanden.\n") (message-all-info . "\ %#1@Sänd alarmmeddelande till alla inloggade. %[%#3FÖverväg att använda \"%#2C\" för att skicka meddelandet till ett specifikt möte eller en enskild användare.%] ") (message-recipient-info . "Sänd meddelande till %#1M\n") (message-nope . "Det gick inte. %#3s\ Meddelandet du försökte sända till %#1M var: %#2t\n") (only-last . "Endast läsa senaste i %#1s: ") (initial-unread . "Initialt antal olästa (tomt för alla): ") (only-error . "Något gick galet. Ledsen.\n") (lp--only-last . "Antal texter att läsa: ") (session-list-unreads-in-confs . "Du har %#2?z%[%#2d oläst%#2?d%[%]%[a%] brev och totalt %]%[%]%#3d oläst%#3?d%[%]%[a%] i %#4d möte%#4?d%[%]%[n%] i %#1s.\n") (session-list-no-unread-in . "Du har läst ut %#1s.\n") (you-have-unreads . "Du har %#1d oläst%#1?d%[%]%[a%] inlägg i %#2M\n") (you-have-unreads-special . "Du har %#1d okommentera%#1?d%[t%]%[de%] inlägg i %#2M\n") (you-have-no-unreads . "Du har inget oläst i %#1M\n") (you-have-read-everything . "Du har sett alla nyheter.\n") (no-unreads-shown . "Hittade inga möten som matchade det kriteriet.\n") (total-unreads . "Du har totalt %#1d oläst%#1?d%[%]%[a%] inlägg i %#2d möte%#2?d%[%]%[n%].\n") (shown-unreads . "Visade %#1d oläst%#1?d%[%]%[a%] inlägg i %#2d möte%#2?d%[%]%[n%].\n") (list-unread-with-n-unread . "Visar endast möten med minst %#1d olästa.\n") (list-unread-with-at-most-n-unread . "Visar endast möten med som mest %#1d olästa.\n") (waiting-for-anything . "Du väntar på ett inlägg i vilket möte som helst.\n") (waiting-higher-than . "Du väntar på ett inlägg i ett möte med högre prioritet än %#1d.\n") (have-to-be-in-conf-with-unread . "Du måste gå till ett icketomt möte först.\n") (Texts . "Inlägg") (Written . "Skrivet") (Lines . "Rader") (Author . "Författare") (Subject . "Ärende") (Comments . "Ko") (Num-marks . "Mk") (mark-type . "Markering") (mark-no . "Mrk") (could-not-read . "Du fick inte läsa denna text (%#1n).\n") (multiple-choice . "Flera alternativ finns.") (does-not-exist . "Detta kommando finns inte.") (summary-line . "%=-8#1n%#2s%4#3d %[%#4@%#5:P%] %[%#6@%#7r%]\n") (diff-what-text-old . "Gammal text att jämföra: ") (diff-what-text-new . "Ny text att jämföra: ") ;; Only people fixing bugs or receiving bug reports should ;; change these: (buggreport-compilestart . "Skapar buggrapporten...") (buggreport-compileend . "Skapar buggrapporten...klart") (buggreport-description . "Detta gjorde jag: \(Fyll i dina kommentarer nedan\)\n================\n\n ================ Bland informationen nedan finns också en lista på de 100 sist tryckta tangenterna i din emacs. Om du nyligen loggat in kan den innehålla ditt lyskomlösenord. Titta igenom den och ändra det som är ditt lösenord till * * * eller m i t t l ö s e n eller något annat lämpligt. När du skrivit klart skall du skicka in din buggrapport till LysKOMs elispklientutvecklare. Det sker antingen: * med email till bug-lyskom@lysator.liu.se * med vanligt brev till: \tLysator \tc/o ISY \tLinköping University \tS-581 83 Linkoping \tSWEDEN. Märk kuvertet \"LysKOM buggrapport för elispklienten\".\n\n") (buggreport-internals . "LysKOMs interna information:\n\n") (buggreport-version . "lyskom-version:") (buggreport-emacs-version . "emacs-version:") (buggreport-system-id . "system-id:") (buggreport-ctl-arrow-doc . "ctrl-doc:") (buggreport-unparsed . "\nlyskom-unparsed-buffer:") (buggreport-command-keys . "Nyss tryckta tangenter:") (buggreport-backtrace . "\n*Backtrace*:\n%#1s\n") (buggreport-communications . "\nlyskom-debug-communications-to-buffer-buffer:") (buggreport-all-kom-variables . "\n\nAndra variabler:\n***** *********") (buggreport-instead-of-byte-comp . "byte-code(\"byte-string\"") (buggreport-subject . "Bugg-rapport elisp-klienten version %#1s") (not-logged-in . "Du är inte inloggad. ") ;; Used for kom-is-person-member-of-conference: (pers-to-check-mship-for . "Vems medlemskap vill du undersöka? ") ;-) (conf-to-check-mship-of . "...i vilket möte? ") (conf-is-empty . "Mötet %#1M är tomt.\n") (pers-is-member-of-conf . "Ja, %#1P är medlem i mötet %#2M.\n") (pers-is-passive-member-of-conf . "Nja, %#1P är bara passiv medlem i mötet %#2M.\n") (pers-is-not-member-of-conf . "Nej, %#1P är inte medlem i mötet %#2M.\n") (pers-is-member-of-conf-2 . "Antal olästa: %#2D (senast inne %#1s)\n") (pers-will-receive-async . "Tar %#1?b%[%]%[inte %]emot gruppmeddelanden till mötet\n") (pers-mship-priority . "Medlemskapets prioritet: %#1d\n") (Unknown-number . "Okänt antal") (text-to-check-will-read-for . "...för medlemskap i mottagare till inlägg: ") (pers-to-check-will-read-for . "Vilken person vill du kontrollera: ") (pers-is-member-of-rcpt . "Ja, %#1P är medlem i minst en mottagare till inlägg %#2n.\n") (pers-is-passive-member-of-rcpt . "Nja, %#1P är bara passiv medlem någon mottagare till %#2n.\n") (pers-is-not-member-of-rcpt . "Nej, %#1P är inte medlem i någon mottagare till %#2n.\n") ;; +++ cant seem to find where these are used: (name-is-not-in-conf . "%#1s är inte närvarande i något möte.\n") (name-is-in-conf . "%#1s är närvarande i\n%#2s\n") (connected-during . "Uppkopplingstid: %#1d sekunder.\n") ;; +++ (conf-to-set-permitted-submitters-q . "Vilket möte vill du sätta tillåtna författare för? ") (conf-to-set-super-conf-q . "Vilket möte vill du sätta supermöte för? ") (new-super-conf-q . "Vilket möte vill du ha som supermöte? ") (new-permitted-submitters-q . "Möte med tillåtna författare till %#1s? (alla) ") (super-conf-for-is . "Ändra supermöte för %#1M till %#2M...") (permitted-submitters-removed-for-conf . "Tillåt alla författare i möte %#1M...") (submitters-conf-for-is . "Ändra tillåtna författare för möte %#1M till\nmedlemmarna i %#2M...") (conf-to-set-garb-nice-q . "Vilket möte vill du sätta livslängd för? ") (new-garb-nice-q . "Efter hur många dagar ska inlägg utplånas? ") (new-keep-commented-q . "Hur många dagar ska nya kommentarer skydda det kommenterade? ") (garb-nice-for-is . "Ändrar livslängden för %#1M till %#2d dag%#2?d%[%]%[ar%]...") (keep-commented-for-is . "Ändrar så kommentarer skyddar från utplåning i %#2d dag%#2?d%[%]%[ar%] för %#1M...") (really-shutdown . "Är du säker på att du vill stänga av servern? ") (closing-server . "Stänga av servern...") (really-sync . "Är du säker på att du vill spara databasen? ") (syncing-server . "Spara databasen...") (administrator . "administratör") (no-longer-administrator . "en normal användare igen") (you-are-now . "Ok, du kör nu som %#1s.\n") (setting-motd . "Sätter loginmeddelandet till text %#1n.\n") (set-motd-success . "Du har satt ett nytt loginmeddelande.\n") (set-motd-failed . "Det gick inte. Du var kanske inte administratör.\n") (removing-motd . "Tar bort loginmeddelandet.\n") (removed-motd . "Du har tagit bort loginmeddelandet.\n") (who-to-throw-out . "Vems session vill du kasta ut? ") (throwing-out . "Kastar nu ut session %#1d... ") (postpone-prompt . "Hur lite vill du läsa nu? ") (set-session-priority . "Sätt läsnivå: ") ;; From review.el: (no-unread-done . "Du måste markera inlägg olästa innan du kan markera fler olästa.\n") (no-review-done . "Du måste återse innan du kan återse mer.\n") (not-reviewing . "Du håller inte på att återse något nu.\n") (unread-how-many . "Oläsmarkera hur många?") (review-how-many . "Återse hur många?") (unread-how-many-more . "Oläsmarkera ytterligare hur många?") (review-how-many-more . "Återse ytterligare hur många?") (latest-n . "senaste %#1d") (first-n . "första %#1d") (review-by-whom . "Återse %#1s av vem: ") (review-to-conf . "Återse %#1s till möte: ") (unread-by-whom . "Oläsmarkera %#1s av vem: ") (unread-to-conf . "Oläsmarkera %#1s till möte: ") (all-confs . "alla möten") (unread-info-by-to . "Oläsmarkera %#1s av %#2P till %#3M.\n") (unread-more-info-by-to . "Oläsmarkera %#1s av %#2P till %#3M.\n") (unread-rest . "resten") (unread-more . "nästa %#1d") (review-info-by-to . "Återse %#1s av %#2P till %#3M framåt.\n") (review-more-info-by-to . "Återse %#1s av %#2P till %#3M framåt.\n") (review-rest . "resten") (review-more . "nästa %#1d") (you-review . "Du återser nu %#1s.\n") (read-text-first . "Du måste läsa en text först.\n") (cannot-read-last-text . "Du kan inte läsa den senast lästa texten.\n") (review-n-texts . "Återse %#1d inlägg.\n") (review-marked . "Återse %#1d markerade.\n") (review-text-no . "Återse text nummer %#1n\n") (review-many-comments . "Återse %#2?d%[en%]%[%#2d%] kommentar%#2?d%[%]%[er%] till inlägg %#1n.\n") (view-many-comments . "Läs %#2?d%[en%]%[%#2d%] kommentar%#2?d%[%]%[er%] till %#1n.\n") (view-texts-in-conf . "Totalt %#1d inlägg att läsa i %#2M.\n") (not-reading-anywhere . "Du läser inte i något möte.\n") (read-normally-read . "Hur många vill du se igen? ") (review-conf-gone . "Mötet finns inte.\n") (review-pers-gone . "Personen finns inte.\n") (review-cant-read-conf . "Du kan inte återse inlägg till ett slutet möte du inte är med i.\n") (review-cant-read-letterbox . "Du kan inte återse inlägg till någon annans brevlåda.\n") (review-cant-read-empty . "Mötet är tomt.\n") (cant-review-everything . "Du kan inte återse alla texter i LysKOM.\n") (cant-unread-everything . "Du kan inte oläsmarkera alla texter i LysKOM.\n") (more-than-one-root . "Inlägg %#1n har mer än ett urinlägg.\n") (more-than-one-root-review . "Inlägg %#1n har mer än ett urinlägg, men endast ett träd kommer att visas.\n") ;; From edit-text.el: (press-C-c-C-c . "Tryck C-c C-c för att skicka in texten.") (recipient . "Mottagare") (carbon-copy . "Extra kopia") (blank-carbon-copy . "Dold kopia") (recipient-prefix . "\\([Mm]\\)") (carbon-copy-prefix . "\\([Ee]\\)") (blank-carbon-copy-prefix . "\\([Dd]\\)") (add-recipient . "Addera mottagare") (add-recipient-or-xref . "Addera...") (secret-aux-flag . "hemlig") (anonymous-aux-flag . "anonym") (inherit-aux-flag . "ärvd") (aux-item-prefix . "[*]") (aux-item-prefix-regexp . "\\[\\*\\]\\s-*") (comment-item-prefix . "#\\s-*") (text-no-comment . "%#1d %#2s /%#3d rad%#3?d%[%]%[er%]/ %#4P %#5?b%[ [anonymt]%]%[%]\n") (cant-fcc-text-file-error . "Kan inte spara inlägg %#1n till \"%#2s\" (%#3s: %#4s).\n") (cant-fcc-text . "Kan inte spara inlägg %#1n till \"%#2s\" (%#3s).\n") (header-subject . "Ärende: ") (header-separator . "\\\ --- Skriv nedan. \ Skicka in=\\[kom-edit-send], \ Avbryt=\\[kom-edit-quit], \ Annat se \\[describe-mode] ---") (text-mass . "%#4s%#1s%[%#6@\n%]%[%#5@%#2s%]%[%#7@\n%]%#3s") (comment-to-by . "%#1s till text %#2n%#3s.\n") (already-sent . "Du har redan skickat denna text en gång. Sänd ändå? ") (subject . "Ärende: ") (subject-prefix . "[Ää\\{\\[]") (enter-subject-idi . "Skriv ett ärende.") (which-text-include . "Vilken text skall vi inkludera? ") (added-recipient . "Mottagare som skall adderas: ") (added-carbon-copy . "Extra kopia till möte: ") (added-blank-carbon-copy . "Dold kopia till: ") (text-to-comment-q . "Vilket inlägg vill du kommentera? ") (conf-has-motd-no . "Mötet har en lapp på dörren. (%#1d)\n\n%#2s") (still-want-to-add . "Vill du fortfarande addera mötet? ") (could-not-create-text . "\nTexten kunde ej skapas. %#2s.\n") (no-get-text . "Du fick inte hämta texten.") (unknown-header . "Okänd information på raden") (transform-error . "Skicka in oformatterat (%#1s)? ") (cant-find-info-node . "Hittar inte info-bufferten") (link-type . "Vad vill du länka till? ") (which-text-to-link . "Lägg in länk till text nummer: ") (which-text-to-link-err . "Hittar inte texten. Lägg in länk till text nummer: ") (which-pers-to-link . "Lägg in länk till person: ") (which-conf-to-link . "Lägg in länk till möte: ") ;; From view-text.el: (view-text-first-line . "%#7$%#2@%#1n %#3s /%#4d rad%#4?d%[%]%[er%]/ %#5P%#6?b%[%#6s%]%[%]\n") (marked-by-you . "Markerad av dig (typ: %#1s).\n") (marked-by-you-and-others . "Markerad av dig (typ: %#2s) och %#1?d%[någon annan%]%[%#1d andra%].\n") (marked-by-several . "Markerad av %#1d person%#1?d%[%]%[er%].\n") (timeformat-day-yyyy-mm-dd-hh-mm-ss . "%#7s %4#1d-%02#2d-%02#3d %02#4d:%02#5d:%02#6d") (timeformat-yyyy-mm-dd-hh-mm-ss . "%4#1d-%02#2d-%02#3d %02#4d:%02#5d:%02#6d") (timeformat-yyyy-mm-dd-hh-mm . "%4#1d-%02#2d-%02#3d %02#4d:%02#5d") (timeformat-yyyy-mm-dd . "%4#1d-%02#2d-%02#3d") (timeformat-hh-mm-ss . "%02#4d:%02#5d:%02#6d") (timeformat-hh-mm . "%02#4d:%02#5d") (format-time-date-and-time . "%#1s %#2s") (format-time-just-date . "%#1s") (format-time-just-time . "%#2s") (today . "idag") (yesterday . "igår") (no-such-text-no . "Det finns inget sådant inlägg. (%#1:n)\n") (text-created-at . "Skapad: %#1s\n") (text-imported-at . "Importerad: %#1s\n") (text-imported-at-by . "Importerad: %#1s av %#2P\n") (head-Subject . "Ärende: ") (Recipient . "Mottagare") (Extra-recipient . "Extra kopia") (Hidden-recipient . "Dold kopia") (mx-Recipient . "Extern mottagare") (mx-Extra-recipient . "Extern kopiemottagare") (mx-Extern-reply-to . "Externa svar till") (Strange-recipient . "Underlig mottagare") (send-at . " Sänt: %#1s\n") (sent-by . " Sänt av %#1P\n") (received-at . " Mottaget: %#1s\n") (comment-to-text . "Kommentar till text %#1n") (footnote-to-text . "Fotnot till text %#1n") (comment-in-text . "Kommentar i text %#1n") (footnote-in-text . "Fotnot i text %#1n") (comment-to-text-by . "Kommentar till text %#1n av %#2P") (footnote-to-text-by . "Fotnot till text %#1n av %#2P") (comment-in-text-by . "Kommentar i text %#1n av %#2P") (footnote-in-text-by . "Fotnot i text %#1n av %#2P") (attachment-to-text . "Bilaga %#3still text %#1n") (attachment-in-text . "Bilaga %#3si text %#1n") (envelope-sender . "Sänt av: %#1s\n") (attachment-filename . "Bilagans filnamn: \"%#1s\"\n") (message-id . "Meddelande-ID: %#1s\n") (written-by . " av %#1P\n") ;; From async.el: (name-has-changed-to-name . "%#1:P har nu bytt namn till %#2:P") (name-has-changed-to-name-r . "%[%#3@%#1:P%] har nu bytt namn till %[%#3@%#2:P%]\n") (you-changed-name-to . "Nu har du bytt namn till %[%#2@%#1:P%].\n") (database-sync . "Databasen synkas.") (lyskom-is-full . "\ =========================================================== Meddelande från LysKOM-systemet: Någon försökte koppla upp, men misslyckades eftersom alla tillgängliga förbindelser är upptagna. Logga ut och kom tillbaks senare om du väntar nu. ===========================================================\n") (lyskom-is-full-long . "\ =============================================================================== Meddelande från LysKOM-systemet: Någon försökte koppla upp, men misslyckades eftersom alla tillgängliga förbindelser är upptagna. Logga ut och kom tillbaks senare om du väntar nu. =============================================================================== ") (has-entered . "Nu har %#1:P gått in i %#2s.") (has-entered-r . "%#2@Nu har %#1P gått in i %#3s.\n") (has-left . "Nu har %#1:P gått ur %#2s.") (has-left-r . "%#2@Nu har %#1P gått ur %#3s.\n") (Unknown . "Okänd") (unknown . "okänd") (Unknown2 . "Okänt") (unknown-person . "Okänd person") (no-longer-member . "Du är inte längre medlem i %#1M.\n") (no-longer-member-n . "Du är inte längre medlem i möte %#1m (finns inte).\n") (have-become-member . "Du har blivit medlem i %#1M.\n") (have-become-invited-member . "Du har bjudits in till %#1M. Gå till mötet för att acceptera eller tacka nej till inbjudan. Du kan även använda kommandot 'Bli medlem i möte' för att acceptera inbjudan.\n") (have-become-passive-member . "Du har blivit passiv medlem i %#1M.\n") (message-broadcast . "\ %[%#4$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$\ Alarmmeddelande från %#1P (%#3s): %#2t %]%[%#4$\ ---------------------------------------------------------------- %]") (message-broadcast-long . "\ %[%#4$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$\ Alarmmeddelande från %#1P (%#3s): %#2t %]%[%#4$\ ------------------------------------------------------------------------------- %]") (message-from . "\ %[%#4$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$\ Personligt meddelande från %#1P (%#3s): %#2t %]%[%#4$\ ---------------------------------------------------------------- %]") (message-from-long . "\ %[%#4$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$\ Personligt meddelande från %#1P (%#3s): %#2t %]%[%#4$\ ------------------------------------------------------------------------------- %]") (message-from-to . "\ %[%#5$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#6$\ Gruppmeddelande till %#3M\nfrån %#2P (%#4s): %#1t %]%[%#5$\ ---------------------------------------------------------------- %]") (message-from-to-long . "\ %[%#5$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#6$\ Gruppmeddelande till %#3M\nfrån %#2P (%#4s): %#1t %]%[%#5$\ ------------------------------------------------------------------------------- %]") (text-is-created . "Text %#1n är skapad!") ;; Used in mode-line-process (mode-line-waiting . ": väntar") (mode-line-working . ": arbetar") (mode-line-saving . ": sparar") (mode-line-down . ": nerkopplad") ;; From completing-read.el: (person-or-conf-no-regexp . "\\`[ \t]*[mpMP]\\w*[ \t]+\\([0-9]+\\)\\'") (session-no-regexp . "\\`[ \t]*[sS]\\w*[ \t]+\\([0-9]+\\)\\'") (conf-prompt . "Vilket möte/person? ") ;; From flags.el: (saving-settings . "Sparar inställningarna...") (saving-settings-done . "Sparar inställningarna...klart") (save-options-failed-internal . "\ Det gick inte att spara inställningarna på grund av ett internt fel. Globala inställningar: %#1?b%[Kodningen misslyckades%]%[OK%] Elispklientens inställningar: %#2?b%[Kodningen misslyckades%]%[OK%] Andra klienters inställningar: %#3?b%[Kodningen misslyckades%]%[OK%] Rapportera gärna detta fel till elispklientens utvecklare. ") (hang-on . "Vänta ett tag...\n") (no-changes . "Ingenting behövde sparas eftersom inga variabler hade ändrats.\n") (could-not-save-options . "Kunde ej spara inställningarna.\n") (could-not-create-area . "Kunde ej skapa texten.\n") (could-not-set-user-area . "Kunde ej ställa om user-arean. Servern säger felmeddelande: %#1d\n") (you-dont-exist . "Du finns inte.\n") (error-in-options . "Det fanns ett fel i en av dina variabler (%#1s) Det stod \"%#2s\" i user-arean. Den sätts till nil istället. Skicka en bugrapport.\n") (error-in-options-short . "Det fanns ett fel i dina inställningar. Vissa inställningar har inte lästs in.") (reading-settings-from-server . "Dina sparade inställningar har ändrats på servern. Läser om inställningarna.\n") ;; From elib-string.el: ;; No entries. ;; From lyskom-rest.el: (mode-line-unread . " Olästa ") (mode-line-letters . "brev ") (frame-title-unread . "Olästa") (frame-title-letters . " brev") (sessions-with-unreads . "Sessioner med olästa") (unread-letters . "olästa brev") (bad-text-no-prefix . "Kan inte översätta prefix `%s' till inläggsnummer") (prefix-arg-try-again . "Ange en annan text eller tryck control-g för att avbryta.\n") (error-code . "%#2?+%[Felkod %#2d/%#3S: %]%[%]%#1s.\n") (error-in-kom-do-when-done . "Variabeln kom-do-when-done har ett felaktigt värde. Du bör sätta den till ett bättre värde.\n") (extended-command . "LysKOM: ") (wait-for-server . "LysKOM väntar på svar från servern. Vänta tills du får en prompt.\n") (review-text-q . "Återse text nummer: ") (completely-read-conf . "Du har sett alla texter i detta möte.\n") (not-in-any-conf . "Du läser inte något möte just nu.\n") (all-conf-unread-r . "Du har läst ut alla möten.\n") (all-conf-unread-s . "Du har läst ut alla möten. ") (enter-conf-unread . "%#1d oläst%#1?d%[%]%[a%]") (enter-conf-unread-faq . "%#1d oläst%#1?d%[%]%[a%] FAQ") (save-one-on-file-q . "Arkivera inlägg %#1n till fil: ") (save-many-on-file-q . "Arkivera %#1d inlägg till fil: ") (saving-one-on-file . "Arkiverar inlägg %#1n i %#2s.\n") (saving-many-on-file . "Arkivera %#1d inlägg i %#2s.\n") (save-text-to-file-q . "Spara inläggstext %#1n på fil: ") (save-text-confirm . "Filen %#1s finns redan. Vill du skriva över den? ") (saving-text . "Sparar inlägg %#1n som %#2s...") (what-save-no . "Vilket inlägg vill du spara? ") (wait-for-prompt . "Vänta på prompten.") (conference-no . "") (person-no . "") (prompt-several-messages . "(%d meddelanden)") (prompt-single-message . "(%d meddelande)") (text-buffer-missing . "Inläggsbufferten existerar inte längre.\n") (re-edit-text-prompt . "Redigera texten som inte kunde skapas") (go-to-pri-conf-prompt . "Gå till nästa prioriterade möte") (go-to-pri-mailbox-prompt . "Gå till din brevlåda (prioriterad)") (read-pri-text-conf . "Läsa nästa prioriterade text") (read-pri-letter-prompt . "Läsa nästa brev (prioriterat)") (review-next-text-prompt . "Återse nästa text") (review-next-comment-prompt . "Återse nästa kommentar") (review-next-marked-prompt . "Återse nästa markerade") (review-next-faq-prompt . "Återse nästa FAQ") (read-next-letter-prompt . "Läsa nästa brev") (read-next-footnote-prompt . "Läsa nästa fotnot") (read-next-comment-prompt . "Läsa nästa kommentar") (read-next-text-prompt . "Läsa nästa text") (read-next-attachment-prompt . "Läsa nästa bilaga") (go-to-conf-of-marked-prompt . "Återuppta återse markerade") (go-to-conf-of-review-tree-prompt . "Återuppta återse kommentarer") (go-to-conf-of-review-prompt . "Återuppta återse") (go-to-conf-of-review-faq-prompt . "Återuppta återse FAQ") (go-to-next-conf-prompt . "Gå till nästa möte") (go-to-your-mailbox-prompt . "Gå till din brevlåda") (next-pri-session-prompt . "Gå till prioriterat LysKOM \"%#1s\"") (next-unread-session-prompt . "Gå till LysKOM \"%#1s\"") (no-such-kom-session . "Det finns ingen sådan session med olästa.\n") (the-command . "Kommandot: %#1C") (error-in-login-hook . "Det fanns ett fel i din kom-login-hook: %#1s\n") (give-a-number . "Mata in ett tal: ") (yes-regexp . "\\`[jJ][aA]\\'") (no-regexp . "\\`[nN][eE][jJ]\\'") (yes-string . "Ja") (no-string . "Nej") (yes-or-no-nag . "Svara bara ja eller nej.") (yes-or-no . "(ja eller nej) ") (y-or-n-instring . "jJnN ") (j-or-n-nag . "Svara bara j eller n. ") (j-or-n . "(j eller n) ") (y-instring . "jJ ") (a-or-b-or-c-nag . "Ge ett giltigt alternativ. ") (person-does-not-exist . "Person %#1d (finns inte).") (conference-does-not-exist . "Möte %#1d (finns inte).") (conf-no-does-not-exist-r . "Möte %#1d finns inte.") (person-is-anonymous . "Anonym person") (process-signal . "Signal från processen.") (closed-connection . " ************************************************** %#2s LysKOM-sessionen onormalt stängd. Felmeddelande: %#1s**************************************************") (dead-session . "LysKOM-sessionen är inte aktiv.") (resurrect-session . "LysKOM-sessionen har kopplats ner, vill du ansluta igen? ") (not-lyskom-buffer . "Detta är inte en aktiv LysKOM-session.") (error-not-found . "Fel nummer %#1d. Ingen klartextförklaring finns.") ;; Useful in more place than one: (illegal-command . "Otillåtet kommando.\n") (no-such-text . "Det finns inget sådant inlägg.\n") (no-such-text-m . "Det finns inget sådant inlägg.") (nobody . "ingen") (everybody . "alla") (everything . "allt") (anybody . "vem som helst") (forward . "framåt") (backward . "bakåt") (wait . "Vänta ett tag...\n") (comment . "Kommentar") (comment-prefix . "\\([Kk]\\)") (footnote . "Fotnot") (footnote-prefix . "\\([Ff]\\)") (by . " av %#1P") (text-created . "Text nummer %#1n är skapad.\n") (text-created-anonymous . "\ Text nummer %#1n är skapad (anonymt). För att göra det svårare för andra att ta reda på att du skapade inlägget bör du vänta ett tag med att läsa det.\n") (resolve-session . "Ange vilken session: ") (starting-program . "Startar %#1s...") (super-jump . "Filtrerar ärende \"%#1r\" i möte \"%#2M\"\n") (no-recipient . "Inlägget har ingen mottagare.\n") (filtered . "[Filtrerad]") (filter-error-specification . "Fel i filterspecifikationen") (filter-error-bad-not . "Fel i filterspecifikation efter 'not'") (filter-error-unknown-key . "Filternyckeln '%S' är okänd.") (filter-error-key-arg . "Fel filterdata (%S %S)") (filter-tree . "Hoppar över text %#1n \"%#2r\" av %#3P och dess kommentarsträd.\n") (filter-text . "Hoppar över text %#1n \"%#2r\" av %#3P.\n") (filter-permanent . "Permanent? ") (filter-action . "Hur vill du filtrera? ") (filter-in-conf . "I vilket möte? (alla) ") (filter-subject . "Filtrera vilket ärende? ") (filter-which-text . "Filtrera inlägg som innehåller: ") (filter-author . "Filtrera vilken författare? ") (filter-recipient . "Vilken mottagare vill du filtrera? ") (permanent . "(permanent)") (temporary . "(tillfällig)") (filter-edit-buffer-name . "*LysKOM Filter Edit*") (filter-edit-empty-list . "Listan är tom") (filter-edit-start-of-list . "Listans början") (filter-edit-end-of-list . "Listans slut") (filter-edit-filter-how . "Hur vill du filtrera? ") (filter-edit-filter-what . "Vad vill du filtrera? ") (filter-edit-bad-argument . "Felaktig inmatning: %s") (filter-edit-outside-entry . "Kan inte utföra kommandot utanför ett filter") (filter-edit-outside-list . "Kan inte utföra operationen utanför listan") (filter-edit-end-of-pattern . "Filtrets slut") (filter-edit-save-p . "Spara förändringar? ") (filter-edit-remove-empty . "Tomma filter gör att alla texter filtreras. Vill du ta bort dessa? ") (filter-edit-restart-p . "Du har gjort ändringar. Vill du verkligen börja om? ") (filter-edit-help . "p,n Upp/ned, i/M-i Ny rad/filter, d/M-d Radera rad/filter, C-h m Mer hjälp") (filter-edit-header . "Ändra filter för \"%s\"\n") (filter-edit-saving . "Sparar ändringarna...") (filter-edit-saving-done . "Sparar ändringarna...klart") (filter-edit-saving-error . "Kunde inte spara ändringarna!") (filter-edit-insert-pred . "%#1s (=,!=): ") (filter-edit-insert-arg . "%#1s %#2s (vad): ") (no-filters . "Inga filter har definierats.\n") (view-filters-header . "\nAktiva filter:\n\n") (view-filters-footer . "") (ansaphone-new-message . "Nytt automatsvar: ") (ansaphone-message . "Svarsmeddelande: ---------------------------------------------------------------------- %#1t ---------------------------------------------------------------------- ") (ansaphone-message-long . "Svarsmeddelande: ------------------------------------------------------------------------------- %#1t ------------------------------------------------------------------------------- ") (ansaphone-state . "Automatsvar är nu %#1s.") (ansaphone-state-r . "Automatsvar är nu %#1s.\n") (ansaphone-messages-gone . "Sparade meddelanden raderade.") (ansaphone-no-messages . "Inga meddelanden.\n") (ansaphone-message-list-start . "Sparade meddelanden:\n\n") (ansaphone-message-list-end . "\n\n") (ansaphone-message-header . "Automatiskt svar (satt %#1s):\n") (remote-erase-messages . "Fjärrstyrning (%#1P %#2s): Sparade meddelanden raderade\n") (remote-set-message . "Fjärrstyrning (%#1P %#2s): Svarsmeddelande: ---------------------------------------------------------------------- %#3t ---------------------------------------------------------------------- ") (remote-set-message-long . "Fjärrstyrning (%#1P %#2s): Svarsmeddelande: ------------------------------------------------------------------------------- %#3t ------------------------------------------------------------------------------- ") (remote-set-ansaphone . "Fjärrstyrning (%#1P %#2s): Automatsvar är nu %#3s\n") (remote-list-messages . "Fjärrstyrning (%#1P %#2s): Meddelanden listade\n") (remote-quit . "Fjärrstyrning(%#1P %#2s): Avsluta\n") (illegal-remote . "Otillåten fjärrstyrning: Tid: %#1s Från: %#2P <%#2p> Till: %#3P <%#3p> Text: %#4t") (illegal-remote-reply . "Fjärrstyrning inte accepterad: %#1s") (remote-not-in-list . "Otillåten person") (remote-bad-command . "Felaktigt kommando") (remote-unknown-error . "Okänt fel") (remote-control-who . "Kontrollera vilken session? ") (remote-control-autoreply . "Automatsvar på eller av? ") (state-on . "påslaget") (state-off . "avslaget") (text-popup-title . "Inlägg %#1s") (conf-popup-title . "Möte %#1s") (pers-popup-title . "Person %#1s") (url-popup-title . "URL %#1s") (aux-popup-title . "Tilläggsinformation") (timestamp-popup-title . "Tidsstämpel %#1s") (recpt-type-popup-title . "Mottagartyp: %#1s") (add-recpt-button-text . "[Addera...]") (add-recpt-button-text-regex . "\\[Addera\\.\\.\\.\\]") (generic-popup-title . "%#1s") (who-i-am-not-present . "%#1P är inte närvarande i något möte\n") (who-i-am-present . "%#1P är närvarande i %#2M\n") (who-i-am-client . "Programmet heter lyskom.el, version %#1s%#2?b%[ (MULE)%]%[%].\n") (who-i-am-server . "Detta är %#1s, version %#2s.\n") (who-i-am-emacs . "Det körs under %#1s%#2?b%[ (MULE)%]%[%].\n") (no-such-session-r . "Det finns ingen sådan session. Personen kanske inte är inloggad.\n") (person-not-logged-in-r . "%#1P %#2?b%[har inte varit inloggad sedan %#2s%]%[är inte inloggad%].\n") (session-status . "Session %#1d är %#2P <%#2p> %#5s %#7s %#4M Kör %#6D från %#3s\n") (session-status-9 . "Session %#1d är %#2P <%#2p> %#5s %#7s %#4M Kör %#6D från %#3s Uppkopplad sedan %#8s%#9s") (session-status-inactive . "\nHar inte varit aktiv på %#1s\n") (one-day . "en dag") (one-hour . "en timme") (one-minute . "en minut") (years . "år") (year . "år") (months . "månader") (month . "månad") (days . "dagar") (day . "dag") (hours . "timmar") (minutes . "minuter") (and . "och") (session-is-active . " och är aktiv.\n") (session-is-invisible . "Denna session är osynlig.\n") (status-for-session . "Sessionsstatus för vilken person? ") (unknown-doing-what . "Existerar") (doing-where-conn . "i") (doing-nowhere-conn . "men är") (waiting-for-membership . "Väntar på att medlemskapslistan ska läsas in...%d/%d") ;; From slow.el (no-such-command . "Det finns inget sådant kommando.\n") (command-completions . "Du kan mena någon av följande:\n %#1s\n") (which-language . "Ändra språk till (change language to): ") (send-formatted . "Skicka in som formatterad text? ") (changing-language-to . "Byter till %#1_s.\n") (language-set-to . "Språket är %#1_s%#2?b%[ %#3@[%#2s]%]%[%].\n") (language-not-loaded . "%#1s finns inte tillgängligt.\n") (reformat-html . "HTML") (reformat-enriched . "enriched") (reformat-filled . "ombruten") (reformat-image . "bild") (image-no-show . "< Bilden kan inte visas. >") (reformat-truncated . "nedkortad") (reformat-signature . "avsignerad") (reformat-deswascii . "var swascii") (reformat-rot13 . "rot13") (need-library . "Paketet \"%#1s\" behövs för att utföra detta kommando.\n") (calc-expression . "Uttryck: ") (do-send-anonymous . "Skicka in texten anonymt? ") (remove-self-sending-anonymous . "Vill du ta bort dig själv som mottagare från inlägget? ") (anonymous . "anonym") (Anonymous . "Anonym") (secret-conf-letter . "H") (protected-conf-letter . "S") (created-conf-letter . "S") (superconf-conf-letter . "M") (supervisor-conf-letter . "O") ;; Some Help (where-is-doesnt-exist . "Kommandot %#1s finns inte") (where-is-on-no-key . "%#1s finns inte på någon tangent") (where-is-on-key . "%#1s finns på %#2s") ;; From aux-items.el (content-type-aux . "Innehållstyp: %#1s") (content-type-regexp . "Innehållstyp: \\(\\S-+\\)") (agreeing . "Håller med om inlägg %#1n...") (fast-replying . "Anmärkning till inlägg %#1n...") (author-fast-replies . "Anmärkningar av författaren:") (author-fast-reply-aux . " \"%#1t\"") (other-fast-replies . "Anmärkningar:") (other-fast-reply-aux . " \"%#1t\" /%#2P/") (fast-reply-too-long . "Kan inte skapa anmärkningar som består av mer än en rad.\n") (conf-to-list-faqs . "Lista FAQ för vilket möte: ") (faq-for-conf-aux . "Texten är FAQ för %#1M <%#1m>") (bad-faq-for-conf-aux . "Texten är FAQ: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s") (faq-for-server-aux . "Texten är FAQ för LysKOM-servern") (faq-in-text-aux . "FAQ i inlägg: %10#1n %#2D") (bad-faq-in-text-aux . "FAQ i inlägg: \"%<20...#1s\" %[%#2@[ogiltigt]%] %#3s") (conf-to-add-faq . "Vilket möte vill du lägga till en FAQ för? ") (text-to-add-as-faq . "Vilken text vill du lägga till som FAQ? ") (text-to-change-as-faq . "Vilken FAQ vill du ändra? ") (adding-faq . "Lägger till inlägg %#1n som FAQ för %#2?b%[%#2M%]%[servern%]...") (conf-to-del-faq . "Vilket möte vill du ta bort en FAQ från? ") (text-to-del-as-faq . "Vilken text vill du ta bort som FAQ? ") (deleting-faq . "Tar bort inlägg %#1n som FAQ för %#2?b%[%#2M%]%[servern%]...") (conf-has-no-faq . "%#1?b%[%#1M%]%[Servern%] har ingen FAQ\n") (unread-which-faq . "Oläsmarkera FAQ för vilket möte? ") (view-which-faq . "Återse FAQ för vilket möte? ") (review-faq-for-r . "Återse FAQ för %#1?b%[%#1M%]%[servern%].\n") (set-faq-for-conf-done . "Text %#3n är nu FAQ för %#1?b%[%#1M%]%[servern%].\n") (set-faq-for-conf-failed . "Kunde inte sätta FAQ för %#1?b%[%#1M%]%[servern%] till text %#3n.\n") (changed-faq-for-conf-done . "FAQ i text %#2n för %#1?b%[%#1M%]%[servern%] ändrad till text %#3n.\n") (changed-faq-for-conf-failed . "Kunde inte ändra FAQ för %#1?b%[%#1M%]%[servern%] till text %#3n. %#2?b%[Text %#2n är fortfarande FAQ. %]%[%]%#4s") (faq-in-text . "FAQ i text %#1n %#3s%#4s") (faq-in-text-by . "FAQ i text %#1n %#5s %#3sav %#2P %#4s") (server-has-new-faq . "\nDet finns %#1d ny%#1?d%[%]%[a%] FAQ till servern.\n") (unread-faqs-header . "\nOläst%#1?d%[%]%[a%] FAQ till %#2?b%[%#2M%]%[servern%]:\n") (all-faqs-header . "Alla FAQ till %#1?b%[%#1M%]%[servern%]:\n") (too-many-languages . "För många teckenuppsättningar för att koda. Skicka in okodat? ") (too-many-content-types . "Kan inte avgöra innehållstyp. Förenkla inlägget.") (cross-reference-text-status-aux . "Se även inlägg: %10#1n /%#2P/") (cross-reference-conf-status-aux . "Se även möte: <%#1m> %#1M /%#2P/") (cross-reference-pers-status-aux . "Se även person: <%#1p> %#1P /%#2P/") (strange-cross-reference-status . "Se även: %#1s (vad nu det betyder)") (cross-reference-text-aux . "Se även inlägg %#1n /%#2P/") (cross-reference-conf-aux . "Se även möte <%#1m> %#1M /%#2P/") (cross-reference-pers-aux . "Se även person <%#1p> %#1P /%#2P/") (cross-reference-text-regexp . "Se även inlägg \\([0-9]+\\)") (cross-reference-conf-regexp . "Se även möte <\\([0-9]+\\)>") (cross-reference-pers-regexp . "Se även person <\\([0-9]+\\)>") (strange-cross-reference . "Se även %#1s, vad nu det betyder") (no-comments-aux . "Författaren har begärt att inte få kommentarer") (no-comments-edit-aux . "Begär att inte få kommentarer") (no-comments-regexp . "Begär att inte få kommentarer") (personal-comment-aux . "Författaren har begärt endast personliga svar") (personal-comment-edit-aux . "Begär endast personliga svar") (personal-comment-regexp . "Begär endast personliga svar") (request-confirmation-aux . "%#1P har begärt läsbekräftelse") (request-confirmation-edit-aux . "Begär bekräftelse om läsning") (request-confirmation-regexp . "Begär bekräftelse om läsning") (confirm-read-q . "Bekräfta läsning av inlägg %#1n? ") (read-confirm-aux . "Läst: %#1P %#2s") (redirect-email-aux . "Skicka sladdpost till %#1s") (redirect-lyskom-aux . "Skicka inlägg till möte %#1M") (label-what-kind . "Sätt personligt namn på vad (inlägg, möte, person)? ") (label-what-text . "Sätt personligt namn på inlägg nummer: ") (label-what-conf . "Sätt personligt namn på vilket möte? ") (label-what-pers . "Sätt personligt namn på vilken person? ") (label-what-label . "Personligt namn: ") (label-secret . "Skall andra kunna se namnet? ") (creating-software-aux . "Skapad med %#1s") (world-readable-text-aux . "Inlägget kan läsas utan inloggning") (world-readable-text-edit-aux . "Gör inlägget läsbart utan inloggning") (cant-get-aux-item . "Hittar inte tilläggsinformationen\n") (aux-item-no-info . "Ingen information tillgänglig\n") (aux-item-info . "\ Nummer: %#1d %#6s Typ: %#2d (%#3s) Skapad av: %#4P <%#4p> Skapad: %#5s Flaggor: %#7s Arvsgräns: %#8s Innehåll: \"%#9s\" ") (secret . "Hemlig") (deleted . "Raderad") (hide-creator . "Dold skapare") (inherit . "Ärvs") (unlimited-inherit . "Obegränsat arv") (no-inheritance . "Arv är avslaget") (no-more-inheritance . "Gränsen uppnådd; inget mer arv") (inherit-steps . "%#1d steg") (aux-item-for . "Tilläggsinformation för ") (aux-item-for-conference-no . "möte <%#1m> %#1M") (aux-item-for-text-no . "inlägg %#1n") (aux-item-for-server . "servern") (what-fast-reply-no . "Anmärkning till vilket inlägg? ") (fast-reply-prompt . "Anmärkning: ") (agree-prompt . "Text: ") (default-agree-string . "Håller med") (what-agree-no . "Håll med vilket inlägg? ") (what-kind-to-add-aux-to . "Koppla tilläggsinformation till vad? ") (which-conf-to-add-aux-to . "Vilket möte vill du koppla till? ") (which-text-to-add-aux-to . "Vilket inlägg vill du koppla till? ") (which-aux-item-tag . "Aux-item tag: ") (which-aux-item-inherit . "Sätt inherit-flaggan? ") (which-aux-item-secret . "Sätt secret-flaggan? ") (which-aux-item-anonymous . "Sätt anonymous-flaggan? ") (which-aux-item-rsv1 . "Sätt dont-garb-flaggan? ") (which-aux-item-rsv2 . "Sätt reserved2-flaggan? ") (which-aux-item-rsv3 . "Sätt reserved3-flaggan? ") (which-aux-item-rsv4 . "Sätt reserved4-flaggan? ") (which-aux-item-inherit-limit . "Arvsgräns: ") (which-aux-item-data . "Data: ") ;; Cross-reference stuff (Person . "Person") (person . "person") (persons . "personer") (Conference . "Möte") (conference . "möte") (conferences . "möten") (Text . "Inlägg") (text . "inlägg") (texts . "inlägg") (Server . "Server") (server . "server") (servers . "servrar") (abc-conference . "mMöte") (abc-person . "pPerson") (abc-text . "iInlägg") (xref-type . "Vad vill du referera till? ") (which-text-to-xref . "Lägg till referens till text nummer: ") (which-text-to-xref-err . "Hittar inte texten. Lägg till referens till text nummer: ") (which-pers-to-xref . "Lägg till referens till person: ") (which-conf-to-xref . "Lägg till referens till möte: ") ;; Aux-item stuff from edit-text (no-comments-q . "Författaren vill inte ha kommentarer. Kommentera ändå? ") (private-answer-q . "Författaren har bett om personliga svar. Skriv personligt svar? ") (your-invited . "%#2P har bjudit in dig till %#1M. Genom att acceptera inbjudan fortsätter du vara medlem i %#1M. Du kan även tacka nej, och då kommer du automatiskt att gå ur mötet. ") (accept-invitation . "Vill du acceptera inbjudan och fortsätta vara medlem? ") (enter-passive . "Du är passiv medlem i %#1M. Du måste bli aktiv medlem för att gå till mötet.\n") (convert-passive . "Vill du bli aktiv medlem i %#1M? ") (bug-secret-mship . "Du är hemlig medlem i %#1M\n") (invitation-mt-type . "inbjuden") (passive-mt-type . "passiv") (secret-mt-type . "hemlig") (message-flag-off-mt-type . "ej gruppmeddelanden") (message-flag-on-mt-type . "gruppmeddelanden") (Invitation-mt-type . "Inbjuden") (Passive-mt-type . "Passiv") (Secret-mt-type . "Hemlig") (Message-flag-mt-type . "Gruppmeddelanden") (not-author . "Du är inte författare till text %#1n.") (not-author-try-anyway-p . "Du är inte författare till inlägget. Vill du försöka ändå? ") (what-no-comments-no . "Vilken text vill du inte ha kommentarer till: ") (adding-no-comments . "Begär att inte få kommentarer till inlägg %#1n...") (already-no-comments . "Inlägg %#1n har redan begäran om inga kommentarer.\n") (what-private-answer-no . "Vilken text vill du ha personligt svar till: ") (adding-private-answer . "Begär att endast få personligt svar till inlägg %#1n...") (already-private-answer . "Inlägg %#1n har redan begäran om enbart personliga svar.\n") (what-request-confirm-no . "Vilken text vill du ha läsbekräftelse till: ") (adding-request-confirm . "Begär läsbekräftelse till inlägg %#1n...") (already-request-confirm . "Inlägg %#1n har redan begäran om läsbekräftelse.\n") (review-mail-headers-to-what . "Vilken texts brevhuvud vill du se? ") (no-mail-headers . "Inlägg %#1n har inget brevhuvud\n") (mail-headers-for . "Brevhuvud för inlägg %#1n:\n") (email-name-prefix . "") (email-name-suffix . "") (you-are-anonymous . "Du är nu någorlunda anonym.\n") (you-are-nonanonymous . "Du är inte längre anonym.\n") (you-are-already-anonymous . "Du är redan någorlunda anonym.\n") (you-are-already-nonanonymous . "Du är redan icke-anonym.\n") (start-keep-alive . "Sänder data med %#1d sekunders mellanrum för att hålla förbindelsen aktiv.") (stop-keep-alive . "Data sänds inte längre för att hålla förbindelsen aktiv.") (review-converted-q . "Återse vilket inlägg konverterat?") (review-noconversion-q . "Återse vilket inlägg omodifierat?") (review-rot13-q . "Återse vilket inlägg i rot13?") (unread-commented-q . "Oläsmarkera vilket inläggs kommenterade?") (review-commented-q . "Återse vilket inlägg kommenterade?") (unread-tree-q . "Oläsmarkera alla kommentarer rekursivt för vilket inlägg?") (review-tree-q . "Återse alla kommentarer rekursivt för vilket inlägg?") (unread-root-q . "Oläsmarkera urinlägget för vilken text?") (find-root-q . "Återse urinlägget för vilken text?") (unread-root-review-q . "Oläsmarkera träd för vilket inlägg?") (find-root-review-q . "Återse träd för vilket inlägg?") (unread-comments-q . "Oläsmarkera alla kommentarer till vilket inlägg?") (review-comments-q . "Återse alla kommentarer till vilket inlägg?") (review-xrefs-q . "Återse alla korsreferenser från vilket inlägg?") (confusion-who-to-reply-to . "Jag förstår inte vems inlägg du vill skriva ett privat svar till.\n") (confusion-what-to-answer-to . "Jag förstår inte vilken text du vill besvara.\n") (confusion-what-to-view . "Jag förstår inte vilken text du vill återse.\n") (confusion-what-to-reply-to . "Jag förstår inte vilken text du vill skriva en anmärkning till.\n") (confusion-what-to-agree-to . "Jag förstår inte vilken text du vill hålla med om.\n") (confusion-what-to-request-confirmation . "Jag förstår inte vilken text du vill ha läsbekräftelser på.\n") (confusion-what-to-comment . "Jag förstår inte vilken text du vill kommentera.\n") (confusion-what-to-footnote . "Jag förstår inte vilken text du vill skriva en fotnot till.\n") (confusion-what-to-delete . "Jag förstår inte vilken text du vill radera.\n") (confusion-what-to-add-sub-recipient . "Jag förstår inte vilken text du vill %#1s.\n") (add-rcpt-action-name . "addera mottagare till") (add-copy-action-name . "addera extra-kopiemottagare till") (add-bcc-action-name . "addera dold kopia till") (sub-action-name . "subtrahera mottagare från") (move-action-name . "flytta") (confusion-what-to-add-comment-to . "Jag förstår inte vilken text du vill addera en kommentar till.\n") (confusion-what-to-sub-comment-from . "Jag förstår inte vilken text du vill subtrahera en kommentar från.\n") (confusion-what-to-add-footnote-to . "Jag förstår inte vilken text du vill addera en fotnot till.\n") (confusion-what-to-sub-footnote-from . "Jag förstår inte vilken text du vill subtrahera en fotnot från.\n") (confusion-what-to-mark . "Jag förstår inte vilket inlägg du vill markera.\n") (confusion-what-to-unmark . "Jag förstår inte vilket inlägg du vill avmarkera.\n") (confusion-what-to-save . "Jag förstår inte vilket inlägg du vill spara.\n") (confusion-what-to-review-mail-headers . "Jag förstår inte vilket inläggs brevhuvud du vill se.\n") (confusion-what-to-unread-root . "Jag förstår inte vilket inläggs urinlägg du vill markera oläst.\n") (confusion-what-to-find-root . "Jag förstår inte vilket inläggs urinlägg du vill återse.\n") (could-not-find-root . "Kan inte identifiera urinlägget. Kommentarsstrukturen kanske är cirkulär.\n") (confusion-what-to-unread-root-review . "Jag förstår inte vilket inläggsträd du vill markera oläst.\n") (confusion-what-to-find-root-review . "Jag förstår inte vilket inläggsträd du vill återse.\n") ;; Help (help-with-what . "Vad vill du ha hjälp med? ") (help-for . "Hjälp för \"%#1s\"\n") ;; Button actions (lyskom-button-view-text-action . "Återse texten") (lyskom-button-unread-text-action . "Oläsmarkera texten") (lyskom-button-copy-text-no-action . "Kopiera inläggsnumret") (lyskom-button-review-converted-action . "Återse konverterat") (lyskom-button-review-noconversion-action . "Återse omodifierat") (lyskom-button-review-rot13-action . "Återse rot13") (lyskom-button-find-root-review-action . "Återse träd") (lyskom-button-find-root-action . "Återse urinlägget") (lyskom-button-comment-text-action . "Kommentera texten") (lyskom-button-private-comment-text-action . "Personligt svar") (lyskom-button-mark-text-action . "Markera texten") (lyskom-button-unmark-text-action . "Avmarkera texten") (lyskom-button-save-text-action . "Arkivera inlägg") (lyskom-button-save-text-body-action . "Spara inläggstext") (lyskom-button-review-comments-action . "Återse alla kommentarer") (lyskom-button-review-tree-action . "Återse alla kommentarer rekursivt") (lyskom-button-write-footnote-action . "Fotnotera") (lyskom-button-fast-reply-action . "Anmärk") (lyskom-button-view-conf-presentation-action . "Visa presentation") (lyskom-button-view-conf-status-action . "Visa mötesstatus") (lyskom-button-goto-conf-action . "Gå till mötet") (lyskom-button-send-message-action . "Skicka gruppmeddelande") (lyskom-button-add-self-action . "Bli medlem i mötet") (lyskom-button-sub-self-action . "Utträd ur mötet") (lyskom-button-view-pers-presentation-action . "Visa presentation") (lyskom-button-view-pers-status-action . "Visa personstatus") (lyskom-button-view-session-status-action . "Visa sessionsstatus") (lyskom-button-mail-action . "Skicka brev") (lyskom-button-send-message-action . "Sänd meddelande") (lyskom-button-open-url-action . "Öppna") (lyskom-button-copy-url-action . "Kopiera") (lyskom-button-goto-info-node-action . "Öppna") (lyskom-button-open-email-action . "Skicka mail") (lyskom-button-copy-email-action . "Kopiera") (lyskom-button-info-aux-action . "Information") (lyskom-button-delete-aux-action . "Radera") (lyskom-button-copy-timestamp-action . "Kopiera") (lyskom-button-recpt-type-recipient . "Mottagare") (lyskom-button-recpt-type-copy . "Extra kopia") (lyskom-button-recpt-type-bcc . "Dold kopia") (lyskom-button-recpt-type-sub . "Subtrahera") (lyskom-button-recpt-add-recipient . "Mottagare") (lyskom-button-recpt-add-copy . "Extra-kopiemottagare") (lyskom-button-recpt-add-bcc . "Dold-kopiamottagare") (lyskom-button-aux-type-xref . "Referens till möte/person/inlägg") (lyskom-button-aux-type-no-comments . "Begäran om inga kommentarer") (lyskom-button-aux-type-personal-comments . "Begäran om personligt svar") (lyskom-edit-toggle-secret-aux-action . "Växla \"hemlig\"") (lyskom-edit-toggle-anonymous-aux-action . "Växla \"anonym\"") (lyskom-edit-toggle-inherit-aux-action . "Växla \"ärvd\"") (lyskom-edit-delete-aux-action . "Ta bort") (lyskom-prioritize-flag-toggle-action . "Växla") (lyskom-prioritize-flag-set-action . "Sätt på") (lyskom-prioritize-flag-clear-action . "Stäng av") (server-status-header . "Status för LysKOM-server %#1s%#2?b%[ (%#2s:%#3d)%]%[%]\n\n") (server-status-server . "Kanonisk server: %#1s%#2?b%[:%#2s%]%[%]\n") (server-status-version . "Programversion: %#1s %#2s\n") (server-status-protocol . "Protokollversion: %15#1d\n") (server-status-sessions . "\ Antal sessioner: %21#1d (totalt) %21#2d aktiva under de senaste %#7d minuterna %21#3d inaktiva sessioner %21#4d okänd aktivitet %21#5d osynliga sessioner %21#6d ej inloggade/hemliga/zombies\n") (server-status-first-text . "Äldsta befintliga text: %14#1n\n") (server-status-last-text . "Yngsta befintliga text: %14#1n%#2?b%[ (%#2n vid start)%]%[%]\n") (server-status-texts . "Antal existerande inlägg: %14#1d (%#2s just nu, %#3d vid start)\n") (server-status-confs . "Antal existerande möten: %14#1d (%#2s just nu, %#3d vid start)\n") (server-status-pers . "Antal existerande personer: %14#1d (%#2s just nu, %#3d vid start)\n") (server-status-has-motd . "\nServern har en lapp på dörren:\n") (server-status-time . "Serverns tid: %#1s\n") (server-status-boot-time . "Servern startades: %#1s\n") (server-status-save-time . "Initial databas sparades: %#1s%#2?b%[ (%#2s)%]%[%]\n") (mship-type-invitation-q . "Inbjudan till medlemskap? ") (mship-type-passive-q . "Passivt medlemskap? ") (mship-type-secret-q . "Hemligt medlemskap? ") (recommend-which-conf . "Vilket möte vill du rekommendera? ") (recommend-set-priority-q . "Rekommendera prioritet? ") (recommend-set-mship-type-q . "Rekommendera mötestyp? ") (recommending-conf . "Rekommenderar %#1M%#2?b%[ (prioritet %#2d)%]%[%]%#3?b%[ %#3s%]%[%]...") (has-recommended-conf . "%#1P har rekommenderat möte %#2M. Vill du bli medlem?\n") (accept-recommendation . "Gå med i %#1M? ") (accepting-recommendation . "Gå med i rekommenderat möte %#2M...") (redirect-for-whom . "Dirigera om kommentarer för: ") (redirect-to-which-conf . "Dirigera om kommentarer till: ") (redirecting-comments-to . "Dirigerar om kommentarer för %#1P till %#2M%#3?b%[ (förr %#1M)%]%[%]...") (kom-redirect-comments-e49 . "Du har inte rätt att ändra denna omdirigering") (kom-redirect-comments-e48 . "Omdirigering av kommentarer stöds inte av servern") (external-program-missing . "Hittar inte det externa programmet \"%#1s\" som krävs för att genomföra kommandot.") (ignored-user-area-var . "\ Ignorerar följande variabler i dina inställningar: %#1s Variablerna är inte registrerade LysKOM-variabler och kan därför inte läsas från servern. Du kan ta bort variablerna från servern genom att ge kommandot \"Spara inställningar\" med prefixargument. %#2?b%[%#5F\ Okända variabler kan bero på att dina inställningar sparades med version %#3s av elispklienten, medan detta är version %#4s. %]%[%]") (unknown-aux-item . "Okänd tilläggsinformation") (text-header-aux-item . "%#1s: <%#2d> \"%#3s\" %#4s") (aux-content-type-name . "Innehållstyp") (aux-fast-reply-name . "Anmärkning") (aux-cross-reference-name . "Referens") (aux-no-comments-name . "Begäran om inga kommentarer") (aux-personal-comment-name . "Begäran om personliga svar") (aux-request-confirmation-name . "Begäran om läsbekräftelse") (aux-read-confirm-name . "Läsbekräftelse") (aux-redirect-name . "Omdirigering") (aux-x-face-name . "Bild") (aux-alternate-name-name . "Alternativt namn") (aux-pgp-signature-name . "PGP-signatur") (aux-pgp-public-key-name . "Publik PGP-nyckel") (aux-e-mail-address-name . "E-postadress") (aux-faq-text-name . "FAQ i text") (aux-creating-software-name . "Skapande klient") (aux-mx-author-name . "E-mailförfattare") (aux-mx-from-name . "E-mail från") (aux-mx-reply-to-name . "E-mail svar sänds till") (aux-mx-to-name . "E-mail till") (aux-mx-cc-name . "E-mail CC") (aux-mx-date-name . "E-maildatum") (aux-mx-message-id-name . "E-mail-meddelande-ID") (aux-mx-in-reply-to-name . "E-mail svar till") (aux-mx-misc-name . "E-mailheader") (aux-mx-allow-filter-name . "E-mail allow-filter") (aux-mx-reject-forward-name . "E-mail reject-forward") (aux-notify-comments-name . "Meddela kommentarer") (aux-faq-for-conf-name . "FAQ för möte") (aux-recommended-conf-name . "Mötesrekommendation") (aux-allowed-content-type-name . "Tillåten innehållstyp") (aux-canonical-name-name . "Kanoniskt namn") (aux-mx-list-name-name . "E-maillistnamn") (aux-send-comments-to-name . "Sänd kommentarer till") (aux-world-readable-name . "Läsbart utan inloggning") (aux-mx-refuse-import . "Vägra inläggsimport") (aux-elisp-client-read-faq-name . "Läst FAQ") (aux-elisp-client-rejected-invitation-name . "Avvisad inbjudan") (review-marking-as-read . "Återse läsmarkerar") (review-not-marking-as-read . "Återse läsmarkerar inte") (review-using-cache . "Återse använder cache") (review-not-using-cache . "Återse använder inte cache") (using-ssh-connection . "Använder ssh-uppkoppling till %#1s...") (opening-ssh-connection . "Öppnar ssh-uppkoppling till %#1s...") (ssh-cant-connect . "Kan inte göra ssh-uppkopplingen: %s") (ssh-closing . "Stänger ssh-uppkopplingen till %#1s") (ssh-unknown-host . "okänd värd") (keyboard-cancel . "Avbryt") (keyboard-menu-help . "(välj: C-n, C-p; bekräfta: RET)") (customize-help . "Se början av bufferten för mer information") (no-mule-warning . "\ %#1@Du har stödet för multibytetecken (MULE) avslaget i emacs. Detta beror antagligen på att du har ett anrop till standard-display-european eller motsvarande i din .emacs, eller i någon av systemets startfiler. Elispklienten är gjord för att köras med stödet för multibytetecken påslaget. Utan detta stöd kan inlägg visas fel, och du kan få problem med att skapa inlägg. Du bör därför slå på stödet för multibytetecken i emacs. ") (coding-system-mismatch-warning . "\ %#3@Din emacs är inställd på att i första hand koda tecken enligt \"%#1s\", men den LysKOM-server du kör mot rekommenderar \"%#2s\". Det innebär att kommentarer du skriver till andras inlägg, och kommentarer till dina inlägg kan få en blandning av tecken som inte går att visa ordentligt. Du bör byta språkomgivning i emacs till en som använder \"%#2s\" som förstahandsval för teckenkodning. ") (has-nameday-1 . "%#1s har namnsdag i dag%#2?b%[ (%#2s)%]%[%].") (has-nameday-2 . "%#1s och %#2s har namnsdag i dag%#3?b%[ (%#3s)%]%[%].") (no-nameday . "Ingen namnsdag i dag%#2?b%[ (%#2s)%]%[%]") (invalid-date-entry . "Ogiltigt datum") (number-out-of-range . "Otillåtet tal") (or-date . "eller datum") (set-unread-n . "Endast läsa %#1?d%[det senaste inlägget%]%[de senaste %#1d inläggen%].\n") (set-unread-date . "Endast läsa inlägg sedan %#3d %#2s %#1d.\n") (jump-from-text . "Hoppa över kommentarer till vilken text? ") (jumping-from-text . "Hoppar över kommentarer till inlägg %#1n.\n") (jumping-from-text-review . "Hoppar över återsedda kommentarer.\n") (session-to-copy-options-from . "Kopiera inställningar från session: ") (reading-settings-from . "Läser inställningar från %s...") (reading-settings-from-done . "Läser inställningar från %s...klart") (super-jump-q . "Superhoppa vilket inlägg? ") (conf-list-legend . "* Ej medlem; - Passiv medlem\n") (unread-text-q . "Gör vilket inlägg oläst? ") (marking-text-unread . "Markerar inlägg %#1n oläst...") (cant-mark-text-unread . "Kunde inte markera inlägg %#1n som oläst (%#2s)\n") (confusion-what-to-mark-unread . "Jag förstår inte vilken text du vill markera oläst.\n") (no-comment-to-to-unread . "Det finns inget kommenterat inlägg att markera som oläst.\n") (mx-refuse-import-html . "HTML") (mx-refuse-import-spam . "Spam") (mx-refuse-import-all . "Alla texter") (abc-html . "hHTML") (abc-spam . "sSpam") (abc-everything . "aAlla texter") (limit-import-to-conf . "Begränsa import till vilket möte? ") (limit-import-of-what . "Begränsa import av vad? ") (limit-import-not-super . "Du verkar inte vara organisatör för mötet. Försök ändå? ") (limiting-import . "Begränsar import av %#1s i %#2M...") (set-message-flag-for-conf . "Ändra meddelandeflagga för vilket möte? ") (set-message-flag-to-what . "Vill du ta emot gruppmeddelanden till %#1M? ") (setting-message-flag . "%#1?b%[Slår på%]%[Stänger av%] mottagning av gruppmeddelanden till %#2M...") (text-has-no-comments . "Inlägg %#1n har inga kommentarer\n") (text-has-no-footnotes . "Inlägg %#1n har inga fotnoter\n") (set-message-flag-q . "Ta emot gruppmeddelanden till %#1M? ") (why-you-got-no-presentation . "\ %#1@\ ======================================================================== Du har ingen presentation%#2?z%[ men har skrivit %#2d inlägg%]%[%] Använd kommandot \"Ändra presentation\" för att skriva eller ändra din presentation. %[%#4F\ Din presentation låter andra i %#3s veta lite om vem du är, och det bidrar till känslan av samhörighet i %#3s. Det här meddelandet kommer att upprepas då och då tills du har skrivit en presentation.%] ======================================================================== ") (status-server-stats . "Statistik om servern:\n\n") (current-average . "nu") (unit-second . "sekund") (unit-minute . "minut") (unit-hour . "timme") (unit-day . "dag") (unit-mongth . "månad") (unit-year . "år") (db-status-backup . "informationsförlust kan ha förekommit") (no-support-in-server . "Servern saknar nödvändig funktionalitet för detta kommando.\n") (mark-confs-as-known . "Markera dessa %#2d %#1s som kända? ") (no-new-conferences . "Inga nya %#2s%#1?b%[ sedan %#1s%]%[%].\n") (new-conferences-since . "Nya %#2s%#1?b%[ sedan %#1s%]%[%]:\n") (list-confs-from-date . "Lista %#1s skapade sedan vilket datum (tomt för alla)? ") (privs-wheel . "operatör") (privs-admin . "administratör") (privs-statistic . "statistik") (privs-create-conf . "skapa möten") (privs-create-pers . "skapa personer") (privs-change-name . "ändra namn") (privs-flg7 . "okänd (7)") (privs-flg8 . "okänd (8)") (privs-flg9 . "okänd (9)") (privs-flg10 . "okänd (10)") (privs-flg11 . "okänd (11)") (privs-flg12 . "okänd (12)") (privs-flg13 . "okänd (13)") (privs-flg14 . "okänd (14)") (privs-flg15 . "okänd (15)") (privs-flg16 . "okänd (16)") (lyskom-no-privileges . "inga rättigheter") (what-pers-privs-to-change . "Vems rättigheter vill du ändra? ") (change-pers-privs-prompt . "\ Nuvarande rättigheter för %#1P (%#1p): %#2s Ändra rättigheter för %#1P (%#1p)...") (set-wheel-priv-q . "Aktivera operatörsrättigheter? ") (set-admin-priv-q . "Aktivera administratörsrättigheter? ") (set-statistic-priv-q . "Aktivera statistikrättigheter? ") (set-create-conf-priv-q . "Aktivera rätt att skapa möten? ") (set-create-pers-priv-q . "Aktivera rätt att skapa personer? ") (set-change-name-priv-q . "Aktivera rätt att ändra namn? ") (set-flg7-priv-q . "Aktivera okänd rättighet 7? ") (set-flg8-priv-q . "Aktivera okänd rättighet 8? ") (set-flg9-priv-q . "Aktivera okänd rättighet 9? ") (set-flg10-priv-q . "Aktivera okänd rättighet 10? ") (set-flg11-priv-q . "Aktivera okänd rättighet 11? ") (set-flg12-priv-q . "Aktivera okänd rättighet 12? ") (set-flg13-priv-q . "Aktivera okänd rättighet 13? ") (set-flg14-priv-q . "Aktivera okänd rättighet 14? ") (set-flg15-priv-q . "Aktivera okänd rättighet 15? ") (set-flg16-priv-q . "Aktivera okänd rättighet 16? ") (canceling-command . "Abryter kommandot...") (no-selection . "Ingen markerad") (selection . "%#1d markerad%#1?d%[%]%[e%]") (lp-no-hidden . "") (lp-hidden . "(%#1d dold%#1?d%[%]%[a%])") (priority-prompt . "Ny prioritet för %#1M: ") (priority-prompt-marked . "Ny prioritet på markerade möten: ") (lp-no-creation-info . "Ingen information om när medlemskapet skapades") (lp-invited . "Inbjuden") (lp-added . "Adderad") (lp-nope . "Det gick inte: %#1s") (lp-no-entry . "Det finns inget medlemskap här") (lp-no-active-filter . "(inga filter aktiva)") (lp-active-filters . "Aktiva filter: %#1s") (lp-mark-mship-with-prio . "Markera medlemskap med prioritet: ") (lp-unmark-mship-with-prio . "Avmarkera medlemskap med prioritet: ") (lp-no-selection . "Inga medlemskap är markerade") (lp-at-min-prio . "Medlemskapet har redan lägsta möjliga prioritet") (lp-at-max-prio . "Medlemskapet har redan högsta möjliga prioritet") (lp-beginning-of-list . "Listans början") (lp-end-of-list . "Listans slut") (lp-goto-priority . "Gå till prioritet: ") (lp-mode-name . "Medlemskap") (lp-header-main . "Medlemskap för %#1M på %#2s") (lp-list-header . " Prio %#1s Senast inne Oläst IHPM\n") (lp-help-footer . " Markera medlemskap: SPC Markera område: C-w Flytta markerade: C-y Sätt prioritet: p Öka prioritet: + Minska prioritet: - Flytta upp: M-p Flytta ned: M-n Ändra flaggor: I,H,P,M Uppskjuta läsning: u Endast: e Avsluta: C-c C-c Mer hjälp: C-h m ") (lp-hide-read-after . "Dölj medlemskap lästa efter: ") (lp-hide-read-since . "Dölj medlemskap ej lästa sedan: ") (lp-skipping-missing-meeting . "Mötet %#1M finns inte längre, hoppar över.") )) (lyskom-language-var local lyskom-month-names sv '(("januari" . 1) ("jan" . 1) ("februari" . 2) ("feb" . 2) ("mars" . 3) ("mar" . 3) ("april" . 4) ("apr" . 4) ("maj" . 5) ("maj" . 5) ("juni" . 6) ("jun" . 6) ("juli" . 7) ("jul" . 7) ("augusti" . 8) ("aug" . 8) ("september" . 9) ("sep" . 9) ("oktober" . 10) ("okt" . 10) ("november" . 11) ("nov" . 11) ("december" . 12) ("dec" . 12))) ;;; ================================================================ ;;; The commands and their associated functions ;;; The Alist formerly known as lyskom-commands (lyskom-language-strings global lyskom-command sv '( (kom-help . "Hjälp") (kom-slow-mode . "Långsamma kommandon") (kom-quick-mode . "Snabba kommandon") (kom-send-message . "Sända meddelande") (kom-send-alarm . "Skicka alarmmeddelande") (kom-create-conf . "Skapa möte") (kom-delete-conf . "Utplåna (möte/person)") (kom-delete-text . "Radera inlägg") (kom-display-time . "Se tiden") (kom-go-to-conf . "Gå till möte") (kom-go-to-next-conf . "Gå till nästa möte") (kom-jump . "Hoppa över alla kommentarer") (kom-list-created-conferences . "Lista ägda möten") (kom-list-conferences . "Lista möten") (kom-list-persons . "Lista personer") (kom-list-news . "Lista nyheter") (kom-list-sessions . "Lista sessioner") (kom-list-re . "Lista (med) regexpar") (kom-membership . "Lista medlemskap") (kom-postpone . "Uppskjuta läsning") (kom-set-session-priority . "Sätt läsnivå") (kom-prioritize . "Prioritera möten") (kom-status-person . "Status (för) person") (kom-status-conf . "Status (för) möte") (kom-add-self . "Bli medlem i möte") (kom-change-priority . "Ändra prioritet") (kom-list-summary . "Lista ärenden") (kom-sub-self . "Utträda ur möte") (kom-quit . "Sluta") (kom-recover . "Starta om klienten") (kom-start-anew . "Börja med nytt namn") (kom-view . "Återse inlägg") (kom-find-root-review . "Återse träd") (kom-review-comments . "Återse alla kommentarer") (kom-review-tree . "Återse alla kommentarer rekursivt") (kom-review-clear . "Återse hoppa") (kom-review-last-normally-read . "Återse igen") (kom-review-cross-references . "Återse alla korsreferenser") (kom-review-converted . "Återse konverterat") (kom-review-noconversion . "Återse omodifierat") (kom-review-rot13 . "Återse rot13") (kom-review-next . "Återse nästa") (kom-find-root . "Återse urinlägget") (kom-review-by-to . "Återse senaste") (kom-review-more . "Återse fler inlägg") (kom-review-first . "Återse första") (kom-review-all . "Återse alla") (kom-view-commented-text . "Återse det kommenterade") (kom-view-previous-commented-text . "Återse det föregående kommenterade") (kom-review-stack . "Återse lista") (kom-review-presentation . "Återse presentation") (kom-review-backward . "(Återse) Baklänges") (kom-view-next-text . "Läsa nästa inlägg") (kom-who-is-on . "Vilka (är) inloggade") (kom-who-is-on-in-conference . "Vilka (är inloggade i) möte") (kom-who-is-present-in-conference . "Vilka (är) närvarande (i möte)") (kom-who-is-on-and-friend . "Vilka vänner (är inloggade)") (kom-who-am-i . "Var (är) jag") (kom-list-clients . "Lista klienter") (kom-busy-wait . "Vänta på ett inlägg") (kom-write-comment . "Kommentera inlägg") (kom-comment-previous . "Kommentera föregående inlägg") (kom-write-footnote . "Fotnot till inlägg") (kom-private-answer . "Personligt svar") (kom-private-answer-previous . "Personligt svar på föregående inlägg") (kom-set-unread . "Endast läsa senaste") (kom-write-text . "Skriva ett inlägg") (kom-send-letter . "Skicka brev") (kom-change-name . "Ändra namn") (kom-change-parenthesis . "Ändra parentes") (kom-change-password . "Ändra lösenord") (kom-change-supervisor . "Ändra organisatör") (kom-change-presentation . "Ändra presentation") (kom-get-appreciation . "Få uppmuntran") (kom-get-abuse . "Få skäll") (kom-mark-text . "Markera (inlägg)") (kom-unmark-text . "Avmarkera (inlägg)") (kom-review-marked-texts . "Återse markerade") (kom-review-all-marked-texts . "Återse alla markerade") (kom-add-recipient . "Addera mottagare") (kom-add-copy . "Addera extra kopiemottagare") (kom-add-bcc . "Addera dold kopia") (kom-sub-recipient . "Subtrahera mottagare") (kom-move-text . "Flytta inlägg") (kom-add-comment . "Addera kommentar") (kom-sub-comment . "Subtrahera kommentar") (kom-add-cross-reference . "Addera referens") (kom-add-member . "Addera medlem") (kom-sub-member . "Uteslut medlem") (kom-change-conf-motd . "Sätt lapp på dörren") (kom-set-garb-nice . "Ändra livslängd") (kom-set-super-conf . "Ändra supermöte") (kom-set-permitted-submitters . "Ändra tillåtna författare") (kom-unset-conf-motd . "Ta bort lapp på dörren") (kom-save-text . "Arkivera inlägg (till fil)") (kom-save-text-body . "Spara inläggstext (på fil)") (kom-save-options . "Spara inställningar") (kom-shutdown-server . "Stäng av servern") (kom-sync-database . "Spara databasen") (kom-enable-adm-caps . "Övergå till administratörsmod") (kom-disable-adm-caps . "Övergå till normalmod") (kom-set-motd . "Sätt loginmeddelande") (kom-remove-motd . "Ta bort loginmeddelande") (kom-force-logout . "Kasta ut en session") (kom-filter-author . "Filtrera författare") (kom-filter-subject . "Filtrera ärende") (kom-filter-text . "Filtrera innehåll") (kom-filter-recipient . "Filtrera mottagare") (kom-super-jump . "Superhoppa") (kom-filter-edit . "Ändra filter") (kom-list-filters . "Lista filter") (kom-show-user-area . "Visa user-arean") (kom-change-conf-type . "Ändra mötestyp") (kom-change-auto-reply . "Ändra svarsmeddelande") (kom-toggle-auto-reply . "Automatsvar") (kom-list-messages . "Lista meddelanden") (kom-erase-messages . "Radera meddelanden") (kom-remote-autoreply . "Fjärrkontrollera automatsvar") (kom-remote-set-message . "Fjärrkontrollera ändra svarsmeddelande") (kom-remote-list-messages . "Fjärrkontrollera lista meddelanden") (kom-remote-erase-messages . "Fjärrkontrollera radera meddelanden") (kom-remote-quit . "Fjärrkontrollera avsluta") (kom-status-session . "Status (för) session") (kom-customize . "Inställningar (för) LysKOM") (kom-next-kom . "Nästa LysKOM") (kom-previous-kom . "Föregående LysKOM") (kom-next-unread-kom . "Nästa olästa LysKOM") (kom-change-language . "Ändra språk") (kom-calculate . "Beräkna") (kom-list-marks . "Lista markeringar") (kom-where-is . "Var finns kommandot") (kom-fast-reply . "Anmärkning (till inlägg)") (kom-agree . "Hålla med") (kom-add-faq . "Addera FAQ") (kom-del-faq . "Ta bort FAQ") (kom-review-faq . "Återse FAQ") (kom-add-footnote . "Addera fotnot") (kom-sub-footnote . "Subtrahera fotnot") (kom-add-no-comments . "Förhindra kommentarer") (kom-add-private-answer . "Begär personligt svar") (kom-add-request-confirm . "Begär läsbekräftelse") (kom-review-mail-headers . "Återse brevhuvud") (kom-compare-texts . "Jämför två texter") (kom-diff-texts . "Se diff") (kom-become-anonymous . "Bli anonym") (kom-become-nonanonymous . "Bli icke-anonym (träd fram ur skuggorna)") (kom-keep-alive . "Håll förbindelsen aktiv") (kom-stop-keep-alive . "Avbryt håll förbindelsen aktiv") (kom-is-person-member-of-conference . "Kontrollera (om person är) medlem (i möte)") (kom-will-person-read-text . "Kontrollera (om person kommer att) läsa (inlägg)") (kom-change-conf-faq . "Ändra FAQ") (kom-make-review-mark-as-read . "Återse läsmarkerar") (kom-make-review-not-mark-as-read . "Återse läsmarkerar inte") (kom-set-presentation . "Addera presentation") (kom-remove-presentation . "Ta bort presentation") (kom-set-motd-text . "Addera lapp på dörren") (kom-create-aux-item . "Skapa tilläggsinformation") (kom-status-server . "Status (för) servern") (kom-add-server-faq . "Addera server-FAQ") (kom-del-server-faq . "Ta bort server-FAQ") (kom-review-server-faq . "Återse server-FAQ") (kom-change-server-faq . "Ändra server-FAQ") (kom-recommend-conference . "Rekommendera möte") (kom-redirect-comments . "Dirigera om kommentarer") (kom-move-text-tree . "Flytta träd") (kom-copy-options . "Kopiera inställningar") (kom-mark-unread . "Oläsmarkera inlägg") (kom-unread-by-to . "Oläsmarkera senaste") (kom-unread-more . "Oläsmarkera fler inlägg") (kom-unread-commented-text . "Oläsmarkera det kommenterade") (kom-unread-previous-commented-text . "Oläsmarkera det föregående kommenterade") (kom-unread-comments . "Oläsmarkera alla kommentarer") (kom-unread-tree . "Oläsmarkera alla kommentarer rekursivt") (kom-unread-root . "Oläsmarkera urinlägget") (kom-unread-root-review . "Oläsmarkera träd") (kom-unread-last-normally-read . "Oläsmarkera igen") (kom-unread-all . "Oläsmarkera alla") (kom-unread-first . "Oläsmarkera första") (kom-unread-presentation . "Oläsmarkera presentation") (kom-unread-server-faq . "Oläsmarkera server-FAQ") (kom-unread-faq . "Oläsmarkera FAQ") (kom-unread-marked-texts . "Oläsmarkera markerade") (kom-unread-all-marked-texts . "Oläsmarkera alla markerade") (kom-join-all-conferences . "Bli medlem i alla möten") (kom-leave-all-conferences . "Utträd ur (nästan) alla möten") (kom-limit-import . "Begränsa import av texter") (kom-change-message-flag . "Ändra mottagning (av) gruppmeddelanden") (kom-list-faqs . "Lista FAQ") (kom-list-server-faqs . "Lista server-FAQ") (kom-list-new-conferences . "Lista nya möten") (kom-list-new-persons . "Lista nya personer") (kom-change-privileges . "Ändra rättigheter") )) (lyskom-language-var local lyskom-language-codes sv '((aa . "Afar") (ab . "Abkhasianska") (af . "Afrikaans") (am . "Amhariska") (ar . "Arabiska") (as . "Assamesiska") (ay . "Aymara") (az . "Azerbajanska") (ba . "Bashkiriska") (be . "Vitryska") (bg . "Bulgariska") (bh . "Bihariska") (bi . "Bislamska") (bn . "Bengaliska") (bo . "Tibetanska") (br . "Bretangneska") (ca . "Katalanska") (co . "Korsikanska") (cs . "Tjeckiska") (cy . "Walesiska") (da . "Danska") (de . "Tyska") (dz . "Bhutanska") (el . "Grekiska") (en . "Engelska") (eo . "Esperanto") (es . "Spanska") (et . "Estniska") (eu . "Baskiska") (fa . "Persiska") (fi . "Finska") (fj . "Fiji") (fo . "Faröiska") (fr . "Franska") (fy . "Frisiska") (ga . "Irländska") (gd . "Skotsk Gäliska") (gl . "Galiciska") (gn . "Guarani") (gu . "Gujaratiska") (ha . "Hausa") (he . "Hebreiska") (hi . "Hindi") (hr . "Kroatiska") (hu . "Ungerska") (hy . "Armeniska") (ia . "Interlingua") (id . "Indonesiska") (ie . "Interlingue") (ik . "Inupiak") (is . "Isländska") (it . "Italienska") (iu . "Inuktitut") (ja . "Japanska") (jw . "Javanesiska") (ka . "Georgiska") (kk . "Kazakhstanska") (kl . "Grönländska") (km . "Kambodianska") (kn . "Kannada") (ko . "Koreanska") (ks . "Kashmiriska") (ku . "Kurdiska") (ky . "Kirghiz") (la . "Latinska") (ln . "Lingala") (lo . "Laotesiska") (lt . "Litauiska") (lv . "Lettiska") (mg . "Malagasiska") (mi . "Maori") (mk . "Makedonska") (ml . "Malayalam") (mn . "Mongolska") (mo . "Moldaviska") (mr . "Marathi") (ms . "Malaysiska") (mt . "Maltesiska") (my . "Burmesiska") (na . "Nauruiska") (ne . "Nepalska") (nl . "Holländska") (no . "Norska") (oc . "Occitanska") (om . "Oromo") (or . "Oriya") (pa . "Pundjabiska") (pl . "Polska") (ps . "Pashtu") (pt . "Protugisiska") (qu . "Quechua") (rm . "Rhätoromanska") (rn . "Kirundiska") (ro . "Rumänska") (ru . "Ryska") (rw . "Kiyarwanda") (sa . "Sanskrit") (sd . "Sindhi") (sg . "Sangho") (sh . "Serbokroatiska") (si . "Singhalesiska") (sk . "Slovakiska") (sl . "Slovenska") (sm . "Samoanska") (sn . "Shoniska") (so . "Somaliska") (sq . "Albanska") (sr . "Serbiska") (ss . "Siswatiska") (st . "Sesothiska") (su . "Sudanesiska") (sv . "Svenska") (sw . "Swahili") (ta . "Tamilska") (te . "Telugu") (tg . "Tajikiska") (th . "Thailändska") (ti . "Tigrinya") (tk . "Turkmenistanska") (tl . "Tagalog") (tn . "Sichuanska") (to . "Tongiska") (tr . "Turkiska") (ts . "Tsongiska") (tt . "Tatariska") (tw . "Twi") (ug . "Uiguriska") (uk . "Ukrainska") (ur . "Urdu") (uz . "Uzbekistanska") (vi . "Vietnamesiska") (vo . "Volapük") (wo . "Wolof") (xh . "Xhosa") (yi . "Yiddish") (yo . "Yorouba") (za . "Zhuang") (zh . "Kinesiska") (zu . "Zulu") (-- . "Okänt språk (%#1s)"))) (lyskom-language-ending-mismatch lyskom-menu language sv en) (lyskom-language-ending-mismatch lyskom-menu kom-change-language sv en) (lyskom-language-ending-mismatch lyskom-menu kom-change-global-language sv en) (lyskom-language-ending-mismatch lyskom-menu kom-change-local-language sv en) (lyskom-language-strings global lyskom-menu sv '((lyskom . "LysKOM") (read . "Läs") (dont-read . "Hoppa") (write . "Skriv") (conference . "Möte") (person . "Person") (server . "Server") (other . "Annat") (move . "Gå") (info . "Om") (send . "Sänd") (unread . "Markera oläst") (review . "Återse inlägg") (marks . "Markerade inlägg") (filters . "Filter") (receivers . "Mottagare") (commented . "Kommenterar") (aux-items . "Tilläggsinformation") (conf-admin . "Mötesadministration") (server-admin . "Serveradministration") (membership . "Medlemskap") (pers-admin . "Personadministration") (autoreply . "Automatsvar") (remote-control . "Fjärrstyrning") (language . "Ändra språk (Change Language)") (kom-help . "Hjälp (Help)") (kom-change-language . "Ändra språk (Change language)") (kom-change-global-language . "Visning och kommandon (display and commands)") (kom-change-local-language . "Endast visning (display language only)") (kom-edit-send . "Skicka in") (kom-edit-send-anonymous . "Skicka anonymt") (kom-edit-quit . "Kasta bort") (kom-ispell-message . "Stavningskontroll") (kom-edit-add-recipient . "Addera mottagare") (kom-edit-add-copy . "Addera extra kopiemottagare") (kom-edit-show-commented . "Återse det kommenterade") (kom-edit-insert-commented . "Citera det kommenterade") (kom-edit-insert-buglist . "Klistra in kommenterad buglista") (kom-edit-add-bcc . "Addera dold kopia") (kom-edit-add-cross-reference . "Addera korsreferens") (kom-edit-add-no-comments . "Begär inga kommentarer") (kom-edit-add-personal-comments . "Begär personliga svar") (kom-edit-add-read-confirm-request . "Begär läsbekräftelse") (kom-edit-move-text . "Flytta till en ny mottagare") (lp--toggle-membership-selection . "Växla markering på medlemskap") (lp--select-region . "Markera område") (lp--select-priority . "Markera prioritet") (lp--deselect-priority . "Avmarkera prioritet") (lp--deselect-all . "Avmarkera alla") (lp--membership-expansion . "Expandera medlemskap") (lp--toggle-entry-expansion . "Växla expansion") (lp--expand-entry . "Expandera medlemskap") (lp--contract-entry . "Avexpandera medlemskap") (lp--membership-priority . "Prioritet") (lp--set-priority . "Ändra prioritet") (lp--move-up . "Flytta uppåt") (lp--move-down . "Flytta nedåt") (lp--increase-priority . "Öka prioritet") (lp--decrease-priority . "Minska prioritet") (lp--yank . "Flytta markerade") (lp--filter . "Urval") (lp--show-hide-memberships-read-before . "Växla visning av medlemskap lästa före...") (lp--show-hide-memberships-read-after . "Växla visning av medlemskap lästa efter...") (lp--show-hide-read-memberships . "Växla visning av medlemskap utan olästa") (lp--show-hide-passive-memberships . "Växla visning av passiva medlemskap") (lp--show-all . "Visa alla medlemskap") (lp--membership-type . "Medlemskapstyp") (lp--toggle-invitation . "Växla inbjudan") (lp--toggle-passive . "Växla passiv") (lp--toggle-message-flag . "Växla meddelanden") (lp--toggle-secret . "Växla hemlig") (lp--set-unread . "Endast") (lp--quit . "Avsluta") )) (lyskom-language-var local lyskom-onoff-table sv '(("på" . on) ("av" . off))) (lyskom-language-var local lyskom-filter-predicate-list sv '(("=" . nil) ("!=" . t))) (lyskom-language-var local lyskom-filter-what sv '((author . "Författare") (author-no . "Författare (nummer)") (author-re . "Författare (regexp)") (subject . "Ärende") (subject-re . "Ärende (regexp)") (recipient . "Mottagare") (recipient-no . "Mottagare (nummer)") (recipient-re . "Mottagare (regexp)") (text . "Innehåll") (text-re . "Innehåll (regexp)"))) (lyskom-language-var local lyskom-filter-actions sv '((skip-text . "Hoppa över") (dontshow . "Visa inte") (read . "Undanta från filtrering") (skip-tree . "Hoppa över kommentarer") (obliterate . "Utplåna"))) (defconst lyskom-keybindings-missing nil) (defvar lyskom-sv-mode-map nil) (lyskom-language-keymap lyskom-mode-map sv lyskom-sv-mode-map) (defvar lyskom-sv-review-prefix) (defvar lyskom-sv-change-prefix) (defvar lyskom-sv-next-prefix) (defvar lyskom-sv-list-prefix) (defvar lyskom-sv-S-prefix) (defvar lyskom-sv-fast-reply-prefix) (defvar lyskom-sv-filter-get-prefix) (defvar lyskom-sv-who-prefix) (defvar lyskom-sv-A-prefix) (defvar lyskom-sv-unread-prefix) (if lyskom-sv-mode-map nil (setq lyskom-sv-mode-map (make-keymap)) (suppress-keymap lyskom-sv-mode-map) (define-prefix-command 'lyskom-sv-review-prefix) (define-prefix-command 'lyskom-sv-change-prefix) (define-prefix-command 'lyskom-sv-next-prefix) (define-prefix-command 'lyskom-sv-list-prefix) (define-prefix-command 'lyskom-sv-S-prefix) (define-prefix-command 'lyskom-sv-fast-reply-prefix) (define-prefix-command 'lyskom-sv-filter-get-prefix) (define-prefix-command 'lyskom-sv-who-prefix) (define-prefix-command 'lyskom-sv-A-prefix) (define-prefix-command 'lyskom-sv-unread-prefix) (define-key lyskom-sv-mode-map (kbd "f") 'lyskom-sv-filter-get-prefix) (define-key lyskom-sv-mode-map (kbd "n") 'lyskom-sv-next-prefix) (define-key lyskom-sv-mode-map (kbd "l") 'lyskom-sv-list-prefix) (define-key lyskom-sv-mode-map (kbd "s") 'lyskom-sv-S-prefix) (define-key lyskom-sv-mode-map (kbd "r") 'lyskom-sv-fast-reply-prefix) (define-key lyskom-sv-mode-map (kbd "v") 'lyskom-sv-who-prefix) (define-key lyskom-sv-mode-map (kbd "a") 'lyskom-sv-A-prefix) (define-key lyskom-sv-mode-map (kbd "o") 'lyskom-sv-unread-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "ä") 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "{") 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "[") 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [adiaeresis] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [Adiaeresis] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [ä] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [Ä] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [228] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [196] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [2276] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [2244] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [3908] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [3940] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [195 164] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map [195 132] 'lyskom-sv-change-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "å") 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "}") 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map (kbd "]") 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [aring] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [Aring] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [å] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [Å] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [229] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [197] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [2277] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [2245] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [3909] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [3941] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [195 165] 'lyskom-sv-review-prefix) (lyskom-try-define-key lyskom-sv-mode-map [195 133] 'lyskom-sv-review-prefix) ; XEmacs 21.4 UTF-8 on terminal compatibility (lyskom-try-define-key lyskom-sv-mode-map [(Ã)] (let ((k (make-sparse-keymap))) (define-key k (vector (intern "\205")) 'lyskom-sv-review-prefix) (define-key k [¥] 'lyskom-sv-review-prefix) (define-key k (vector (intern "\204")) 'lyskom-sv-change-prefix) (define-key k [(¤)] 'lyskom-sv-change-prefix) k)) (define-key lyskom-sv-mode-map (kbd "M-m") 'kom-toggle-mark-as-read-prefix) (define-key lyskom-sv-mode-map (kbd "M-c") 'kom-toggle-cache-prefix) (define-key lyskom-sv-mode-map (kbd (lyskom-keys 'button2)) 'kom-button-click) (define-key lyskom-sv-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-sv-mode-map (kbd (lyskom-keys 'button2up)) 'kom-mouse-null) (define-key lyskom-sv-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-sv-mode-map (kbd "*") 'kom-button-press) (define-key lyskom-sv-mode-map (kbd "=") 'kom-menu-button-press) (define-key lyskom-sv-mode-map (kbd "TAB") 'kom-next-link) (define-key lyskom-sv-mode-map (kbd "M-TAB") 'kom-previous-link) (define-key lyskom-sv-mode-map (kbd "") 'kom-previous-link) (define-key lyskom-sv-mode-map (kbd "C-i") 'kom-next-link) (define-key lyskom-sv-mode-map (kbd "M-C-i") 'kom-previous-link) ;; These should be first in order to be last in the menu of alternatives. (define-key lyskom-sv-change-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-review-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-unread-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-filter-get-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-next-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-list-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-S-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-who-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-fast-reply-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-A-prefix (kbd "?") 'lyskom-help) (define-key lyskom-sv-mode-map (kbd "e") 'kom-set-unread) ;; (define-key lyskom-sv-mode-map (kbd "a") 'kom-obsolete-extended-command-binding) ;; (define-key lyskom-sv-mode-map (kbd "l v") 'kom-obsolete-who-is-on-in-conference) (define-key lyskom-sv-mode-map (kbd "x") 'kom-extended-command) (define-key lyskom-sv-mode-map (kbd "") 'kom-next-command) (define-key lyskom-sv-mode-map (kbd "") 'kom-line-next-command) (define-key lyskom-sv-mode-map (kbd "") 'kom-page-next-command) (define-key lyskom-sv-mode-map (kbd "C-j") 'kom-page-next-command) (define-key lyskom-sv-mode-map (kbd "j") 'kom-page-next-command) (define-key lyskom-sv-mode-map (kbd "C-m") 'kom-line-next-command) (define-key lyskom-sv-mode-map (kbd "?") 'kom-help) (define-key lyskom-sv-mode-map (kbd "b") 'kom-send-letter) (define-key lyskom-sv-mode-map (kbd "g") 'kom-go-to-conf) (define-key lyskom-sv-mode-map (kbd "i") 'kom-write-text) (define-key lyskom-sv-mode-map (kbd "k") 'kom-write-comment) (define-key lyskom-sv-mode-map (kbd "K") 'kom-comment-previous) (define-key lyskom-sv-mode-map (kbd "F") 'kom-write-footnote) (define-key lyskom-sv-mode-map (kbd "p") 'kom-private-answer) (define-key lyskom-sv-mode-map (kbd "P") 'kom-private-answer-previous) (define-key lyskom-sv-mode-map (kbd "h") 'kom-jump) (define-key lyskom-sv-mode-map (kbd "H") 'kom-super-jump) (define-key lyskom-sv-mode-map (kbd "m") 'kom-add-self) (define-key lyskom-sv-mode-map (kbd "M") 'kom-mark-text) (define-key lyskom-sv-mode-map (kbd "A") 'kom-unmark-text) (define-key lyskom-sv-mode-map (kbd "S") 'kom-quit) (define-key lyskom-sv-mode-map (kbd "q") 'kom-quit) (define-key lyskom-sv-mode-map (kbd "z") 'kom-bury) (define-key lyskom-sv-mode-map (kbd "R") 'kom-recover) (define-key lyskom-sv-mode-map (kbd "t") 'kom-display-time) (define-key lyskom-sv-mode-map (kbd "J") 'kom-who-am-i) (define-key lyskom-sv-mode-map (kbd "V") 'kom-busy-wait) (define-key lyskom-sv-next-prefix (kbd "i") 'kom-view-next-new-text) (define-key lyskom-sv-next-prefix (kbd "m") 'kom-go-to-next-conf) (define-key lyskom-sv-next-prefix (kbd "l") 'kom-next-kom) (define-key lyskom-sv-next-prefix (kbd "o") 'kom-next-unread-kom) (define-key lyskom-sv-list-prefix (kbd "k") 'kom-list-sessions) (define-key lyskom-sv-list-prefix (kbd "M") 'kom-list-marks) (define-key lyskom-sv-list-prefix (kbd "m") 'kom-list-conferences) (define-key lyskom-sv-list-prefix (kbd "n") 'kom-list-news) (define-key lyskom-sv-list-prefix (kbd "p") 'kom-list-persons) (define-key lyskom-sv-list-prefix (kbd "r") 'kom-list-re) (define-key lyskom-sv-list-prefix (kbd "s") 'kom-membership) (define-key lyskom-sv-list-prefix (kbd "f") 'kom-list-filters) (define-key lyskom-sv-list-prefix (kbd "q") 'kom-list-faqs) (define-key lyskom-sv-list-prefix (kbd "Q") 'kom-list-server-faqs) (lyskom-try-define-key lyskom-sv-list-prefix (kbd "ä") 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix (kbd "{") 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix (kbd "[") 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [adiaeresis] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [Adiaeresis] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [ä] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [Ä] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [228] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [196] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [2276] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [2244] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [3908] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [3940] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [195 164] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [195 132] 'kom-list-summary) (lyskom-try-define-key lyskom-sv-list-prefix [(Ã)] (let ((k (make-sparse-keymap))) (define-key k (vector (intern "\204")) 'kom-list-summary) (define-key k [¤] 'kom-list-summary) k)) (define-key lyskom-sv-filter-get-prefix (kbd "u") 'kom-get-appreciation) (define-key lyskom-sv-filter-get-prefix (kbd "s") 'kom-get-abuse) (define-key lyskom-sv-filter-get-prefix (kbd "t") 'kom-move-text) (define-key lyskom-sv-filter-get-prefix (kbd "T") 'kom-move-text-tree) (define-key lyskom-sv-filter-get-prefix (kbd "f") 'kom-filter-author) (define-key lyskom-sv-filter-get-prefix (kbd "i") 'kom-filter-text) (define-key lyskom-sv-filter-get-prefix (kbd "m") 'kom-filter-recipient) (define-key lyskom-sv-filter-get-prefix (kbd "l") 'kom-previous-kom) (lyskom-try-define-key lyskom-sv-filter-get-prefix (kbd "ä") 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix (kbd "{") 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix (kbd "[") 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [adiaeresis] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [Adiaeresis] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [ä] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [Ä] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [228] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [196] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [2276] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [2244] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [3908] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [3940] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [195 164] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [195 132] 'kom-filter-subject) (lyskom-try-define-key lyskom-sv-filter-get-prefix [(Ã)] (let ((k (make-sparse-keymap))) (define-key k (vector (intern "\204")) 'kom-filter-subject) (define-key k [¤] 'kom-filter-subject) k)) (define-key lyskom-sv-who-prefix (kbd "i") 'kom-who-is-on) (define-key lyskom-sv-who-prefix (kbd "m") 'kom-who-is-on-in-conference) (define-key lyskom-sv-who-prefix (kbd "n") 'kom-who-is-present-in-conference) (define-key lyskom-sv-who-prefix (kbd "v") 'kom-who-is-on-and-friend) (define-key lyskom-sv-change-prefix (kbd "p") 'kom-change-presentation) (define-key lyskom-sv-change-prefix (kbd "q") 'kom-change-conf-faq) (define-key lyskom-sv-change-prefix (kbd "f") 'kom-filter-edit) (define-key lyskom-sv-change-prefix (kbd "m") 'kom-change-auto-reply) (define-key lyskom-sv-unread-prefix (kbd "SPC") 'kom-mark-unread) (define-key lyskom-sv-unread-prefix (kbd "0") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "1") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "2") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "3") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "4") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "5") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "6") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "7") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "8") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "9") 'kom-initial-digit-unread) (define-key lyskom-sv-unread-prefix (kbd "k") 'kom-unread-commented-text) (define-key lyskom-sv-unread-prefix (kbd "K") 'kom-unread-previous-commented-text) (define-key lyskom-sv-unread-prefix (kbd "a ?") 'lyskom-help) (define-key lyskom-sv-unread-prefix (kbd "a k") 'kom-unread-comments) (define-key lyskom-sv-unread-prefix (kbd "a r") 'kom-unread-tree) (define-key lyskom-sv-unread-prefix (kbd "i") 'kom-unread-last-normally-read) (define-key lyskom-sv-unread-prefix (kbd "r") 'kom-unread-root) (define-key lyskom-sv-unread-prefix (kbd "u") 'kom-unread-root) (define-key lyskom-sv-unread-prefix (kbd "s") 'kom-unread-by-to) (define-key lyskom-sv-unread-prefix (kbd "y") 'kom-unread-more) (define-key lyskom-sv-unread-prefix (kbd "t") 'kom-unread-root-review) (define-key lyskom-sv-unread-prefix (kbd "A") 'kom-unread-all) (define-key lyskom-sv-unread-prefix (kbd "f") 'kom-unread-first) (define-key lyskom-sv-unread-prefix (kbd "p") 'kom-unread-presentation) (define-key lyskom-sv-unread-prefix (kbd "q") 'kom-unread-faq) (define-key lyskom-sv-unread-prefix (kbd "Q") 'kom-unread-server-faq) (define-key lyskom-sv-unread-prefix (kbd "m") 'kom-unread-marked-texts) (define-key lyskom-sv-unread-prefix (kbd "a m") 'kom-unread-all-marked-texts) (define-key lyskom-sv-unread-prefix (kbd "a SPC") 'kom-unread-all) (define-key lyskom-sv-review-prefix (kbd "SPC") 'kom-view) (define-key lyskom-sv-review-prefix (kbd "0") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "1") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "2") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "3") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "4") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "5") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "6") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "7") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "8") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "9") 'kom-initial-digit-view) (define-key lyskom-sv-review-prefix (kbd "k") 'kom-view-commented-text) (define-key lyskom-sv-review-prefix (kbd "K") 'kom-view-previous-commented-text) (define-key lyskom-sv-review-prefix (kbd "a ?") 'lyskom-help) (define-key lyskom-sv-review-prefix (kbd "a k") 'kom-review-comments) (define-key lyskom-sv-review-prefix (kbd "a r") 'kom-review-tree) (define-key lyskom-sv-review-prefix (kbd "a x") 'kom-review-cross-references) (define-key lyskom-sv-review-prefix (kbd "h") 'kom-review-clear) (define-key lyskom-sv-review-prefix (kbd "i") 'kom-review-last-normally-read) (define-key lyskom-sv-review-prefix (kbd "n") 'kom-review-next) (define-key lyskom-sv-review-prefix (kbd "o") 'kom-review-noconversion) (define-key lyskom-sv-review-prefix (kbd "v") 'kom-review-converted) (define-key lyskom-sv-review-prefix (kbd "3") 'kom-review-rot13) (define-key lyskom-sv-review-prefix (kbd "r") 'kom-find-root) (define-key lyskom-sv-review-prefix (kbd "u") 'kom-find-root) (define-key lyskom-sv-review-prefix (kbd "s") 'kom-review-by-to) (define-key lyskom-sv-review-prefix (kbd "y") 'kom-review-more) (define-key lyskom-sv-review-prefix (kbd "A") 'kom-review-all) (define-key lyskom-sv-review-prefix (kbd "f") 'kom-review-first) (define-key lyskom-sv-review-prefix (kbd "l") 'kom-review-stack) (define-key lyskom-sv-review-prefix (kbd "p") 'kom-review-presentation) (define-key lyskom-sv-review-prefix (kbd "t") 'kom-find-root-review) (define-key lyskom-sv-review-prefix (kbd "m") 'kom-review-marked-texts) (define-key lyskom-sv-review-prefix (kbd "q") 'kom-review-faq) (define-key lyskom-sv-review-prefix (kbd "Q") 'kom-review-server-faq) (define-key lyskom-sv-review-prefix (kbd "a m") 'kom-review-all-marked-texts) (define-key lyskom-sv-review-prefix (kbd "a SPC") 'kom-review-all) (define-key lyskom-sv-review-prefix (kbd "b") 'kom-review-mail-headers) (define-key lyskom-sv-review-prefix (kbd "B") 'kom-review-backward) (define-key lyskom-sv-S-prefix (kbd "m") 'kom-status-conf) (define-key lyskom-sv-S-prefix (kbd "p") 'kom-status-person) (define-key lyskom-sv-S-prefix (kbd "s") 'kom-status-session) (define-key lyskom-sv-S-prefix (kbd "k") 'kom-status-server) (define-key lyskom-sv-S-prefix (kbd "u ?") 'lyskom-help) (define-key lyskom-sv-S-prefix (kbd "u m") 'kom-sub-recipient) (define-key lyskom-sv-S-prefix (kbd "u k") 'kom-sub-comment) (define-key lyskom-sv-S-prefix (kbd "u q") 'kom-del-faq) (define-key lyskom-sv-S-prefix (kbd "u f") 'kom-sub-footnote) (define-key lyskom-sv-S-prefix (kbd "t") 'kom-save-text) (lyskom-try-define-key lyskom-sv-S-prefix (kbd "ä") 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix (kbd "{") 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix (kbd "[") 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [adiaeresis] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [Adiaeresis] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [ä] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [Ä] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [228] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [196] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [2276] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [2244] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [3908] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [3940] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [195 164] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [195 132] 'kom-send-message) (lyskom-try-define-key lyskom-sv-S-prefix [(Ã)] (let ((k (make-sparse-keymap))) (define-key k (vector (intern "\204")) 'kom-send-message) (define-key k [¤] 'kom-send-message) k)) (define-key lyskom-sv-A-prefix (kbd "m") 'kom-add-recipient) (define-key lyskom-sv-A-prefix (kbd "e") 'kom-add-copy) (define-key lyskom-sv-A-prefix (kbd "d") 'kom-add-bcc) (define-key lyskom-sv-A-prefix (kbd "k") 'kom-add-comment) (define-key lyskom-sv-A-prefix (kbd "r") 'kom-add-cross-reference) (define-key lyskom-sv-A-prefix (kbd "q") 'kom-add-faq) (define-key lyskom-sv-A-prefix (kbd "f") 'kom-add-footnote) (define-key lyskom-sv-A-prefix (kbd "Q") 'kom-add-server-faq) (define-key lyskom-sv-fast-reply-prefix (kbd "a") 'kom-fast-reply) (define-key lyskom-sv-fast-reply-prefix (kbd "r") 'kom-fast-reply) (define-key lyskom-sv-fast-reply-prefix (kbd "h") 'kom-agree) ;; Running in buffer (define-key lyskom-sv-mode-map (kbd "M-p") 'backward-text) (define-key lyskom-sv-mode-map (kbd "M-n") 'forward-text) (define-key lyskom-sv-mode-map (kbd "C-M-p") 'kom-prev-prompt) (define-key lyskom-sv-mode-map (kbd "C-M-n") 'kom-next-prompt) (define-key lyskom-sv-mode-map (kbd "C-?") 'scroll-down) (define-key lyskom-sv-mode-map (kbd "") 'scroll-down) (define-key lyskom-sv-mode-map (kbd "") 'scroll-down) (define-key lyskom-sv-mode-map (kbd "") 'scroll-down) (define-key lyskom-sv-mode-map (kbd "<") 'beginning-of-buffer) (define-key lyskom-sv-mode-map (kbd ">") 'end-of-buffer) ) ;;; ================================================================ ;;; Prioritization (defvar lyskom-sv-prioritize-mode-map nil "Keymap used in lyskom-prioritize-mode") (lyskom-language-keymap lyskom-prioritize-mode-map sv lyskom-sv-prioritize-mode-map) (if lyskom-sv-prioritize-mode-map nil (setq lyskom-sv-prioritize-mode-map (make-keymap)) (suppress-keymap lyskom-sv-prioritize-mode-map) (define-key lyskom-sv-prioritize-mode-map (kbd "SPC") 'lp--toggle-membership-selection) (define-key lyskom-sv-prioritize-mode-map (kbd "C-k") 'lp--toggle-membership-selection) (define-key lyskom-sv-prioritize-mode-map (kbd "p") 'lp--set-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "C-w") 'lp--select-region) (define-key lyskom-sv-prioritize-mode-map (kbd "M-w") 'lp--select-region) (define-key lyskom-sv-prioritize-mode-map (kbd "C-y") 'lp--yank) (define-key lyskom-sv-prioritize-mode-map (kbd "#") 'lp--select-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "M-#") 'lp--deselect-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "M-DEL") 'lp--deselect-all) (define-key lyskom-sv-prioritize-mode-map (kbd "C-p") 'lp--previous-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "") 'lp--previous-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "C-n") 'lp--next-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "") 'lp--next-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "") 'lp--first-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "") 'lp--last-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "M-<") 'lp--first-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "M->") 'lp--last-entry) (define-key lyskom-sv-prioritize-mode-map (kbd "g") 'lp--goto-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "RET") 'lp--toggle-entry-expansion) (define-key lyskom-sv-prioritize-mode-map (kbd "+") 'lp--increase-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "-") 'lp--decrease-priority) (define-key lyskom-sv-prioritize-mode-map (kbd "M-p") 'lp--move-up) (define-key lyskom-sv-prioritize-mode-map (kbd "M-n") 'lp--move-down) (define-key lyskom-sv-prioritize-mode-map (kbd "M-") 'lp--move-up) (define-key lyskom-sv-prioritize-mode-map (kbd "M-") 'lp--move-down) (define-key lyskom-sv-prioritize-mode-map (kbd "I") 'lp--toggle-invitation) (define-key lyskom-sv-prioritize-mode-map (kbd "H") 'lp--toggle-secret) (define-key lyskom-sv-prioritize-mode-map (kbd "P") 'lp--toggle-passive) (define-key lyskom-sv-prioritize-mode-map (kbd "M") 'lp--toggle-message-flag) (define-key lyskom-sv-prioritize-mode-map (kbd "e") 'lp--set-unread) (define-key lyskom-sv-prioritize-mode-map (kbd "u") 'lp--postpone) (define-key lyskom-sv-prioritize-mode-map (kbd "C-c C-c") 'lp--quit) (define-key lyskom-sv-prioritize-mode-map (kbd "q") 'lp--quit) (define-key lyskom-sv-prioritize-mode-map (kbd "(") 'lp--expand-entry) (define-key lyskom-sv-prioritize-mode-map (kbd ")") 'lp--contract-entry) (define-key lyskom-sv-prioritize-mode-map (kbd (lyskom-keys 'button2up)) 'kom-button-click) (define-key lyskom-sv-prioritize-mode-map (kbd (lyskom-keys 'button2)) 'kom-mouse-null) (define-key lyskom-sv-prioritize-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-sv-prioritize-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-sv-prioritize-mode-map (kbd "*") 'kom-button-press) (define-key lyskom-sv-prioritize-mode-map (kbd "=") 'kom-menu-button-press) (define-key lyskom-sv-prioritize-mode-map (kbd "TAB") 'kom-next-link) (define-key lyskom-sv-prioritize-mode-map (kbd "M-TAB") 'kom-previous-link) (define-key lyskom-sv-prioritize-mode-map (kbd "C-i") 'kom-next-link) (define-key lyskom-sv-prioritize-mode-map (kbd "M-C-i") 'kom-previous-link) ) ;;; ============================================================== ;;; Keymap for filter editing ;;; (defvar lyskom-sv-filter-edit-map nil) (lyskom-language-keymap lyskom-filter-edit-map sv lyskom-sv-filter-edit-map) (if lyskom-sv-filter-edit-map () (setq lyskom-sv-filter-edit-map (make-keymap)) (suppress-keymap lyskom-sv-filter-edit-map) (define-prefix-command 'lyskom-sv-filter-edit-prefix) (define-key lyskom-sv-filter-edit-map (kbd "C-c") 'lyskom-sv-filter-edit-prefix) (define-key lyskom-sv-filter-edit-map (kbd "p") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-sv-filter-edit-map (kbd "P") 'lyskom-filter-edit-prev-entry) (define-key lyskom-sv-filter-edit-map (kbd "n") 'lyskom-filter-edit-next-pattern) (define-key lyskom-sv-filter-edit-map (kbd "N") 'lyskom-filter-edit-next-entry) (define-key lyskom-sv-filter-edit-map (kbd "C-p") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-sv-filter-edit-map (kbd "C-n") 'lyskom-filter-edit-next-pattern) (define-key lyskom-sv-filter-edit-map (kbd "C-b") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-sv-filter-edit-map (kbd "C-f") 'lyskom-filter-edit-next-pattern) (define-key lyskom-sv-filter-edit-map (kbd "M-p") 'lyskom-filter-edit-prev-entry) (define-key lyskom-sv-filter-edit-map (kbd "M-n") 'lyskom-filter-edit-next-entry) (define-key lyskom-sv-filter-edit-map (kbd "d") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-sv-filter-edit-map (kbd "M-d") 'lyskom-filter-edit-delete-entry) (define-key lyskom-sv-filter-edit-map (kbd "D") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-sv-filter-edit-map (kbd "C-d") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-sv-filter-edit-map (kbd "i") 'lyskom-filter-edit-insert-pattern) (define-key lyskom-sv-filter-edit-map (kbd "I") 'lyskom-filter-edit-insert-pattern) (define-key lyskom-sv-filter-edit-map (kbd "M-i") 'lyskom-filter-edit-insert-entry) (define-key lyskom-sv-filter-edit-map (kbd "<") 'lyskom-filter-edit-beginning-of-list) (define-key lyskom-sv-filter-edit-map (kbd ">") 'lyskom-filter-edit-end-of-list) (define-key lyskom-sv-filter-edit-map (kbd "M-<") 'lyskom-filter-edit-beginning-of-list) (define-key lyskom-sv-filter-edit-map (kbd "M->") 'lyskom-filter-edit-end-of-list) (define-key lyskom-sv-filter-edit-map (kbd "q") 'lyskom-filter-edit-quit) (define-key lyskom-sv-filter-edit-map (kbd "C-c C-c") 'lyskom-filter-edit-quit) (define-key lyskom-sv-filter-edit-map (kbd "x") 'lyskom-filter-edit-expunge) (define-key lyskom-sv-filter-edit-map (kbd "s") 'lyskom-filter-edit-save) (define-key lyskom-sv-filter-edit-map (kbd "g") 'lyskom-filter-edit-revert) (define-key lyskom-sv-filter-edit-map (kbd "t") 'lyskom-filter-edit-toggle-permanent) (define-key lyskom-sv-filter-edit-map (kbd "a") 'lyskom-filter-edit-toggle-action) (define-key lyskom-sv-filter-edit-map (kbd "?") 'lyskom-filter-edit-brief-help) (define-key lyskom-sv-filter-edit-map (kbd "h") 'lyskom-filter-edit-brief-help) ) ;;;; ============================================================ ;;;; Strings and things for the customize mode ;;;; (defvar lyskom-sv-customize-map nil) (lyskom-language-keymap lyskom-customize-map sv lyskom-sv-customize-map) (if lyskom-sv-customize-map nil (setq lyskom-sv-customize-map (make-sparse-keymap)) (define-key lyskom-sv-customize-map (kbd "TAB") 'widget-forward) (define-key lyskom-sv-customize-map (kbd "M-TAB") 'widget-backward) (define-key lyskom-sv-customize-map (kbd "") 'widget-backward) (define-key lyskom-sv-customize-map (kbd "C-i") 'widget-forward) (define-key lyskom-sv-customize-map (kbd "M-C-i") 'widget-backward) (define-key lyskom-sv-customize-map (kbd "C-m") 'widget-button-press) (define-key lyskom-sv-customize-map (kbd "C-j") 'widget-button-press) (define-key lyskom-sv-customize-map (kbd "") 'widget-button-press) (define-key lyskom-sv-customize-map (kbd "") 'widget-button-press) (define-key lyskom-sv-customize-map (kbd (lyskom-keys 'button2)) 'widget-button-click) (define-key lyskom-sv-customize-map (kbd (lyskom-keys 'button3)) 'lyskom-widget-click) (define-key lyskom-sv-customize-map (kbd (lyskom-keys 'button2up)) 'kom-mouse-null) (define-key lyskom-sv-customize-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-sv-customize-map (kbd "C-c C-c") 'lyskom-customize-save-and-quit) (define-key lyskom-sv-customize-map (kbd "C-c C-k") 'lyskom-customize-quit) (define-key lyskom-sv-customize-map (kbd "C-c C-s") 'lyskom-customize-save) (define-key lyskom-sv-customize-map (kbd "C-c C-a") 'lyskom-customize-apply) (define-key lyskom-sv-customize-map (kbd "?") 'lyskom-customize-help) ) (lyskom-language-strings local lyskom-custom-strings sv '( ;; ;; Widget strings ;; (which-person . "Ange en person: ") (which-conf . "Ange ett möte: ") (which-conf-or-person . "Ange en person eller ett möte: ") (which-name . "Ange ett namn: ") (some-person . "Person %#1d") (invalid-value . "Otillåtet värde (%#1S)") (unknown-command . "Okänt kommando (%#1s)") (ding . "Ljudsignal") ;; ;; Help messages ;; (variable-type-help . "Kryssa i för att spara inställningen i servern.") (default-help-echo . "Ändra värdet på %#1s.") (change-this-name . "Ändra namnet på denna rad.") (show-doc . "Visa hjälptexten.") (hide-doc . "Dölj hjälptexten.") (select-command . "Välj kommando.") (select-what-to-execute . "Exekvera kommando eller tangentbordsmakro.") (select-url-viewer . "Välj en WWW-läsare.") (select-number . "Ange hur många gånger.") (select-audio-file . "Ange en ljudfil.") (select-priority . "Ange prioritet.") (select-buffer . "Ange buffert.") (select-buffer-size . "Ange buffertstorlek.") ;; ;; Strings that are used in types and so forth ;; (buffer-name . "%#1s-inställningar") (other-window . "Något annat fönster ") (other-frame . "I en annan frame ") (new-frame . "I en ny frame ") (lyskom-window . "LysKOM-buffertens fönster ") (window-on-buffer . "Ett fönster som visar bufferten") (on . "På") (off . "Av") (yes . "Ja ") (no . "Nej") (to-file . "Till fil:") (max-text-length . "För inlägg kortare än: ") (autowrap-timeout . "Antal sekunder: ") (no-timeout . "Ingen tidsbegränsning") (friends . "Vänner och bekanta") (turned-off . "Avslaget ") (number-of-times . "Några gånger") (specific-spec . "Per mottagare/avsändare") (sound-file . "Ljudfil") (other-persons . "Alla andra") (selected-mark . "Markering") (conf-or-person . "Person eller möte") (ask . "Fråga varje gång") (before . "Före texten") (after . "Efter texten") (first . "Först") (last . "Sist ") (depth-first . "I kommentarsordning") (time-order . "I tidsordning") (limited-number . "Ett begränsat antal") (unlimited-number . "Obegränsat") (ar-message-type . "Meddelandetyp") (ar-personal . "Personligt meddelande") (ar-group . "Gruppmeddelande") (ar-alarm . "Alarmmeddelande") (ar-any-type . "Alla meddelandetyper") (ar-sender . "Avsändare") (ar-any-sender . "Alla avsändare") (ar-specified-sender . "Specifika avsändare") (ar-pers-or-conf . "Person eller möte") (ar-recipient . "Mottagare") (ar-any-recipient . "Alla mottagare") (ar-specified-recipient . "Specifika mottagare") (ar-person . "Person") (ar-message-text . "Meddelandetext") (ar-any-message . "Alla meddelanden") (ar-matching-regexp . "Meddelanden som matchar") (ar-reply . "Automatsvar") (ar-no-reply . "Inget svar") (ar-reply-text . "Svarstext") (express-break . "Omedelbart efter de har skapats") (break . "Efter aktuell kommentarskedja") (no-break . "Efter aktuellt möte") (express-server-break . "Omedelbart") (express-server-letters-break . "Omedelbart om det kommer brev") (server-break . "Efter aktuell kommentarskedja") (letters-server-break . "Efter aktuell kommentarskedja om det kommer brev") (after-conf-server-break . "Efter aktuellt möte") (after-conf-letters-server-break . "Efter aktuellt möte när det kommer brev") (when-done-server-break . "När allt är utläst") (no-server-break . "Aldrig") (command . "Kommando") (command-list . "Kommandolista") (some-persons . "För vissa personer") (name . "Namn") (page-none . "Aldrig ") (page-all . "Före varje kommando ") (page-some . "Före följande kommandon") (ask-every-time . "Fråga varje gång ") (fixed-priority . "Fast prioritet") (messages-in-lyskom-buffer . "I LysKOM-bufferten ") (discard-messages . "Ingenstans ") (in-named-buffer . "I namngiven buffert:") (automatic-session-name . "Automatiskt") (given-session-name . "Använd angivet:") (simple-unread-mode-line . "Enkel") (explicit-unread-mode-line . "Visa alla sessioner med olästa") (everybody-rcpt . "Alla ") (group-rcpt . "Senaste gruppmeddelandes mottagare") (sender-rcpt . "Senaste meddelandes avsändare ") (last-recipient-recpt . "Senaste mottagaren ") (viewer-program . "WWW-läsare") (no-viewer . "(ingenting valt)") (default-viewer . "Browse-URL (alla)") (netscape-viewer . "Netscape/Mozilla (alla)") (windows-viewer . "Windows standard eller Netscape/Mozilla (alla)") (emacs-w3-viewer . "Emacs W3-mode (HTTP, Goper, FTP)") (emacs-general-viewer . "Emacs (FTP, Telnet, Mail)") (emacs-dired-viewer . "Emacs Dired (FTP)") (emacs-mail-viewer . "Emacs Mail-mode (Mail)") (emacs-telnet-viewer . "Emacs Telnet-mode (telnet)") (mosaic-viewer . "NCSA Mosaic (alla)") (lynx-viewer . "Lynx (alla)") (galeon-viewer . "Galeon (alla)") (dont-check . "Ingen bekräftelse") (check-before-open . "Bekräfta innan inlägget skrivs") (check-before-send . "Bekräfta innan inlägget sänds") (no-size-limit . "Ingen begränsning") (max-size-in-bytes . "Begränsning (i bytes)") (execute . "Utför") (kbd-macro . "Tangentbordmakro") (command . "Kommando") (enter-kbd-macro . "Mata in tangentbordsmakro. Avsluta med %#1s") (long-format . "Visa hjälptexter") (short-format . "Göm hjälptexter ") (truncate-threshold-lines . "Max rader") (first . "Först") (last . "Sist") (specific-placement . "Specifik plats") (priority . "Prioritet") (same-as-conf . "Samma som aktuellt möte") (custom-format . "Eget format:") (default-format . "Standardformat") (a-string . "En text:") (some-string . "En slumpmässig text") (unspecified . "Ospecificerat") (symbolic-mark-association . "Associering") (symbolic-mark-name . "Symboliskt namn: ") (mark-type-to-assoc . "Markeringstyp att associera till: ") (prompt-for-text-no . "Fråga efter textnummer") (all-others . "Alla andra") (some-person . "Person") (format-html . "Formattera HTML:") (url-transform-regexp . "Från (regexp):") (url-transform-newtext . " Till:") (default-namedays . "Namnsdagar för aktuellt språk") (specific-namedays . "Specifik namnlängd") (several-name-lists . "Flera namnlängder") (link-pattern-for . "Mönster för") (all-conferences . "Alla mottagare") (link-specific-rcpt . "Specifik mottagare") (link-pattern . "Länkmönster") (link-replace . "Länksubstitution") (link-highlight-match . "Visa grupp") (link-fold-case . "Versaler och gemener lika") (generated-face . "Automatgenererat teckensnitt") (predefined-fonts . "Teckensnitt avsedda för specifika tillämpningar\n") (other-fonts . "Teckensnitt utan specifika tillämpningar\n") (other-face . "Annat") (ext-simple-command . "Enkelt kommando") (ext-complex-command . "Kommando med argument") (ext-complex-component . "Komanndo/argument") (lynx-xterm . "Lynx i xterm") (lynx-emacs . "Lynx i emacs terminal-mode") (morons . "Idioter och knäppskallar") (friends . "Vänner och bekanta") (me . "Mig själv och ingen annan") (i-am-supervisor . "Möten jag organiserar") (has-no-presentation . "Möten utan presentationer") (highlight-conferences . "Möten:") (highlight-face . "Utseende:") (highlight-conflist . "Möteslista") (yes-dont-pop . "Ja, men avikonifiera inte fönstret") (language . "Språk") (specific-extended-info . "Enbart vald information") (extended-info-show . "Visa:") (extended-info-type . "Informationstyp:") (extended-server-info . "All utökad serverinformation") (extended-conf-info . "All utökad mötesinformation") (extended-pers-info . "All utökad personinformation") (extended-read-faq-info . "Lästa FAQ") (extended-statistics-info . "Fullständig serverstatistik") (extended-all-other-info . "Annan information") ;; ;; Misc doc strings ;; (lyskom . "Inställningar för LysKOM") (lyskom-doc . "\ Dessa tangenter fungerar utanför redigerbara textfält. \\[lyskom-customize-save-and-quit] för att spara och avsluta, \\[lyskom-customize-save] för att spara utan att avsluta \\[lyskom-customize-quit] för att avsluta utan att spara \\[widget-forward] flyttar till nästa inställning \\[widget-button-press] ändrar värdet Tryck C-h m för en fullständig lista av kommandon. Hjälptexter: [?] Visa hjälptext [!] Göm hjälptext Listor mm.: [INS] Lägg till rad [DEL] Ta bort rad [*] Ändra värde Om rutan före inställningens namn är ikryssad kommer värdet att sparas i servern. Annars sparas det i din .emacs. Klicka med musens mittenknapp på ledtexterna för att ändra värde eller ta fram menyer.") (section . "------------------------------------------------------------------------------\n") (look-and-feel-misc . "Diverse utseende och beteende\n") (window-locations . "Fönster\n") (windows-where . "Hur skall fönster skapas:\n") (reading . "Beteende vid läsning\n") (writing . "Beteende vid skrivning\n") (urls . "Hantering av URLer\n") (personal-messages . "Hantering av personliga meddelanden\n") (remote-control . "Fjärrstyrning av LysKOM\n") (hooks . "Hook-funktioner\n") (audio-cues . "Ljudsignaler\n") (audio-cues-when . "Ge ljudsignal:\n") (automatic-replies . "Automatiskt svar\n") (new-window-netscape . "Öppna URLer i nytt fönster") (new-tab-netscape . "Öppna URLer i ny tab") (default-netscape . "Öppna URLer där de råkar hamna") (audio-cues-doc . "\ Efterföljande inställningar bestämmer vilken ljudsignal LysKOM skall ge i olika situationer. Följande alternativ går att välja: Avslaget Ingen ljudsignal alls kommer att ges. Några gånger Emacs kommer att pipa en eller flera gånger när händelsen inträffar. Antal pip anges också. Ljudfil Emacs kommer att spela upp den angivna ljudfilen. Programmet som angavs ovan som ljudspelarprogram används för att spela ljudet.") (sending-doc . "\ Följande inställningar slår på eller av vissa kontroller vid inskickning av inlägg. Kontrollerna är avsedda att hindra att man gör någonting dumt. Bekräfta multipla mottagare Om ett inlägg eller kommentar har flera mottagare så kan LysKOM fråga vilka av mottagarna som är relevanta för inlägget. Antingen görs detta innan man skriver inlägget (då får man en fråga för varje defaultmottagare), eller när man skickar in inlägget (då får man bekräfta alla mottagare i klump). Det går också att slå av helt. Kontroll av kommenterad författares medlemskap Kontrollera att författaren till det kommenterade inlägget är medlem i någon av mottagarna för kommentaren. Om så inte är fallet, erbjuder LysKOM att lägga till författaren som mottagare till inlägget. Författare som inte kontrolleras En lista av författare som inte skall kontrolleras även om kontroll av kommenterad författares medlemskap är påslaget. Kontroll av olästa kommentarer När detta är påslaget så kontrollerar LysKOM att det inlägg man kommenterar inte har några kommentarer man inte har läst. Detta är främst användbart för att undvika att man skriver någonting som någon annan redan har skrivit.") (windows-doc . "\ Följande inställningar bestämmer hur fönster skapas i LysKOM. Alternativen som finns är följande: Något annat fönster I ett annat fönster i samma frame som LysKOM. Om det bara finns ett fönster så kommer ett nytt att skapas (och tas bort när man är klar). I en annan frame I en annan frame än LysKOM. Om det bara finns en frame så kommer en ny frame att skapas, och (tas bort när man är klar). I en ny frame En ny frame skapas för ändamålet, och tas bort när man är klar. LysKOM-buffertens fönster LysKOM-buffertens fönster kommer att användas, och LysKOM kommer att återställas till fönstret när man är färdig. Ett fönster som visar bufferten Om det finns ett fönster någonstans som visar den angivna bufferten så kommer detta fönster att användas. Det kan till exempel vara användbart om man hela tiden har ett fönster öppet, men inte beöver det just medan man utför något visst kommando.") ;; ;; Doc strings for variables ;; (kom-ansaphone-replies-doc . "\ Den här inställningen styr automatsvar i detalj. Det går att ställa in svar för specifika avsändare, mottagare och till och med meddelanden. Om meddelandet som skall besvaras inte stämmer in på något i den här listan så används svarsmeddelandet ovan istället. För varje mönster går det att ställa in meddelandetyp, avsändare som meddelandet skall ha, mottagare som meddelandet skall ha, ett mönster som meddelandet skall innehålla och vilket svar som skall skickas. Det är lämpligt att ställa in att inget svar skall skickas på något gruppmeddelande eller alarmmeddelande.") (kom-bury-buffers-doc . "\ Bestämmer hur bufferten hanteras när man går till ett annat KOM med Nästa LysKOM och liknande funktioner. Påslaget innebär att den aktuella bufferten läggs sist i buffertlistan när man byter LysKOM.") (kom-personal-messages-in-window-doc . "\ Bestämmer i vilket fönster som bufferten med personliga meddelanden visas. För att den här inställningen skall spela någon roll så måste personliga meddelanden visas i en separat buffert, och bufferten måste visas varje gång det kommer meddelanden.") (kom-write-texts-in-window-doc . "\ Bestämmer i vilket fönster nya texter skrivs.") (kom-prioritize-in-window-doc . "\ Bestämmer i vilket fönster man prioriterar om möten.") (kom-edit-filters-in-window-doc . "\ Bestämmer i vilket fönster man ändrar filter.") (kom-customize-in-window-doc . "\ Bestämmer i vilket fönster man gör dessa inställningar.") (kom-view-commented-in-window-doc . "\ Bestämmer i vilket fönster man visar kommenterarer medan man skriver nya.") (kom-list-membership-in-window-doc . "\ Bestämmer i vilket fönster man listar medlemskap.") (kom-user-prompt-format-doc . "\ Format för LysKOM-prompten. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%] - \" Standardprompt \"%[%s: %c% %m%] - \" Till exempel \"LysKOM: Se tiden - \"") (kom-user-prompt-format-executing-doc . "\ Format för LysKOM-prompten efter man trycker på SPC eller RET. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%].\" Standardprompt \"%[%s: Kör %c% %m%]...\" Till exempel \"LysKOM: Kör Se tiden...\"") (kom-anonymous-prompt-format-doc . "\ Format för LysKOM-prompten när man är anonym. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%] - \" Standardprompt \"%[%s: %c% %m%] - \" Till exempel \"LysKOM: Se tiden - \"") (kom-anonymous-prompt-format-executing-doc . "\ Format för LysKOM-prompten efter man trycker på SPC eller RET och är anonym. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%].\" Standardprompt \"%[%s: Kör %c% %m%]...\" Till exempel \"LysKOM: Kör Se tiden...\"") (kom-enabled-prompt-format-doc . "\ Format för LysKOM-prompten när man är i administratörsmod. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%] - \" Standardprompt \"%[%s: %c% %m%] - \" Till exempel \"LysKOM: Se tiden - \"") (kom-enabled-prompt-format-executing-doc . "\ Format för LysKOM-prompten efter man trycker på SPC eller RET och är i administratörsmod. Vissa teckenkombinationer sätter in speciella texter: %c - Sätter in kommandot som körs om man trycker på SPC eller RET. %[ - Sätter in '[' om automatsvar är påslaget. %] - Sätter in ']' om automatsvar är påslaget. %m - Sätter in information om antal inspelade meddelanden. %s - Sätter in LysKOM-systemets namn %S - Sätter in LysKOM-serverns namn %p - Sätter in namnet på den person som är inloggad. %w - Sätter in namn på aktuellt möte. %a - Sätter in \"anonym\" %A - Sätter in \"Anonym\" %# - Sätter in sessionsnummer. % - Sätter in mellanslag om det ser ut att behövas. %% - Sätter in ett procenttecken. Några exempel: \"%[%c% %m%].\" Standardprompt \"%[%s: Kör %c% %m%]...\" Till exempel \"LysKOM: Kör Se tiden...\"") (kom-cite-string-doc . "\ Text som sätts in före varje rad i ett citerat inlägg. Normalt brukar någonting i stil med \"> \" användas. Notera dock att det inte är brukligt att citera KOM-inlägg som man gör med sladdpost och News eftersom det kommenterade inlägget oftast finns tillgängligt.") (kom-created-texts-are-read-doc . "\ Om detta är påslaget kommer alla inlägg man själv skriver att läsmarkeras automatiskt. Om inställningen är avslagen så får man läsa sådant man själv skriver.") (kom-default-mark-doc . "\ Den markeringstyp som används för nya markeringar. En markeringstyp är ett heltal mellan 0 och 255 (inklusive). Om ingen defaultmarkeringstyp är vald frågar LysKOM efter markeringstyp varje gång man markerar en text. Detta kan användas för att hålla isär olika sorters markeringar. Till exempel kan man markera inlägg som innehåller intressant information med ett visst tal och inlägg som man ska komma ihåg att kommentera vid ett senare tillfälle med ett annat tal.") (kom-symbolic-marks-alist-doc . "\ För att slippa behöva memorera vad man tänkte sig att de heltaliga markeringstyperna ska innebära kan man definiera en lista med symboliska markeringstyper. En symbolisk markeringstyp är en beskrivande sträng som associeras med en heltalig markeringstyp.") (kom-reading-puts-comments-in-pointers-last-doc . "\ Bestämmer om kommentarslänkar visas före eller efter en text. Normalt brukar man visa kommentarslänkar efter texten. Före: 398331 1996-09-24 13:22 /2 rader/ George Berkeley Mottagare: Filosofimötet <1226> Kommentar i text 398374 av John Locke Ärende: ------------------------------------------------------------ En abstrakt idé är en självmotsägelse. (398331) ----------------------------------- Efter: 398331 1996-09-24 13:22 /2 rader/ George Berkeley Mottagare: Filosofimötet <1226> Ärende: ------------------------------------------------------------ En abstrakt idé är en självmotsägelse. (398331) ----------------------------------- Kommentar i text 398374 av John Locke ") (kom-show-author-at-end-doc . "\ Om detta är påslaget så visas namnet på författaren efter inläggstexten. Naturligtvis så visas även namnet i inläggshuvudet. Påslaget (med streckade linjer också påslaget): 892342 1996-09-24 19:21 /2 rader/ Claude Shannon Mottagare: Presentation (av nya) Medlemmar Ärende: Claude Shannon ------------------------------------------------------------ Informationsteoretiker (892342) /Claude Shannon/------------------------------ Avslaget: 892342 1996-09-24 19:21 /2 rader/ Claude Shannon Mottagare: Presentation (av nya) Medlemmar Ärende: Claude Shannon ------------------------------------------------------------ Informationsteoretiker (892342) ----------------------------------- Om man har streckade linjer avslaget så visas författaren på samma sätt, men de streckade linjerna finns naturligtvis inte med.") (kom-truncate-threshold-doc . "\ Om detta är påslaget kommer inlägg som är längre än maxantalet att kortas ner när man återser kommentarer, återser markerade inlägg eller återser de senaste eller första. Inlägg kortas inte av då man återser inlägg, återser träd eller bara läser nästa inlägg.") (kom-truncate-show-lines-doc . "\ Antalet rader som visas när ett inlägg avkortats.") (kom-dashed-lines-doc . "\ Om detta är påslaget visas streckade linjer före och efter inläggstexten, annars visas en tomrad efter ärenderaden, och ingenting speciellt i slutet. Påslaget: 892343 1996-09-24 19:21 /2 rader/ Tycho Brahe Mottagare: Presentation (av nya) Medlemmar Ärende: Tycho Brahe ------------------------------------------------------------ Astronom och upptäckare av stjärnor med hemvist på Ven. (892343) ----------------------------------- Avslaget: 892343 1996-09-24 19:21 /2 rader/ Tycho Brahe Mottagare: Presentation (av nya) Medlemmar Ärende: Tycho Brahe Astronom och upptäckare av stjärnor med hemvist på Ven. (892343) De flesta brukar ha detta påslaget.") (kom-autowrap-doc . "\ Om detta är påslaget så kommer LysKOM att försöka bryta om raderna i stycken vars rader egentligen är längre än skärmen är bred. Stycken som verkar vara förformatterade av författaren bryts dock aldrig om. Det går att ange en maximal längd i tecken på inlägg som får brytas om (vilket kan vara användbart för att undvika mycket långa inlägg).") (kom-autowrap-timeout-doc . "\ Denna inställning begränsar hur lång tid automatisk ombrytning av raderna i ett inlägg får ta (i sekunder). En begränsning är särskilt användbar när man läser mycket långa inlägg. Notera att tiden är högst ungefärlig. Ombrytningen kan pågå i flera sekunder längre än detta värde. Begränsningen gör också att all inläggsvisning går aningen långsammare. Om begränsningen är avstängd kan man ändå avbryta ombrytningen genom att trycka C-g.") (kom-print-number-of-unread-on-entrance-doc . "\ Om detta är påslaget så visas antalet olästa i ett möte när man går till mötet: Påslaget: Gå till nästa möte... Presentation (av nya) medlemmar - 3 olästa Läsa nästa text - Avslaget: Gå till nästa möte... Presentation (av nya) medlemmar Läsa nästa text - ") (kom-presence-messages-in-echo-area-doc . "\ Om man vill ha meddelanden i ekoarean när någon loggar in, ut eller byter namn i LysKOM bör man slå på den här inställningen. Meddelanden visas i ekoarean. Om man vill ha information om endast vissa personer går det att ange en lista av personer. Vill man inte ha några meddelanden alls är det bara att ange en tom lista.") (kom-presence-messages-in-buffer-doc . "\ Om man vill ha meddelanden i LysKOM-bufferten när någon loggar in, ut eller byter namn i LysKOM bör man slå på den här inställningen. Meddelanden visas i LysKOM-bufferten. Om man vill ha information om endast vissa personer går det att ange en lista av personer. Vill man inte ha några meddelanden alls är det bara att ange en tom lista.") (kom-show-where-and-what-doc . "\ Information i vilkalistan om varifrån en person är inloggad och vad personen gör visas bara om detta är påslaget. Påslaget: Användare Närvarande i möte Kör från Gör -------------------------------------------------------------------------- 6810 George Berkeley Filosofimötet berkeley@emp1.tcd.ie (Skriver en kommentar.) 7571 John Locke Filosofimötet eridy@cc.ox.ac.uk (Väntar.) Avslaget: Användare Närvarande i möte -------------------------------------------------------------------------- 6810 George Berkeley Filosofimötet 7571 John Locke Filosofimötet") (kom-show-since-and-when-doc . "\ Information i vilkalistan om när en person loggade in och hur länge sedan personen var aktiv.") (kom-remember-password-doc . "\ Om denna inställning är påslagen sparas lösenordet till LysKOM-servern som en lokal variabel i sessionsbufferten och kan på så vis användas vid återinloggning ifall sessionen kopplas ner. OBS: Lösenordet sparas i klartext, detta gör att om någon får tillgång till din LysKOM- sessionsbuffer (även nedkopplad sådan) kan han/hon få reda på ditt lösenord ifall du aktiverar detta val.") (kom-idle-hide-doc . "\ I vilkalistan visas normalt enbart de sessioner som har varit aktiva under den senaste tiden. Denna inställning bestämmer hur många minuter en session får ha varit inaktiv och ändå visas i vilkalistan.") (kom-show-footnotes-immediately-doc . "\ Fotnoter visas normalt på samma sätt som kommentarer, men om detta är påslaget så visas fotnoter direkt efter inlägget de hör till.") (kom-follow-comments-outside-membership-doc . "\ Normalt så visar inte LysKOM kommentarer till ett inlägg om man inte är medlem i något av mötena kommentaren har som mottagare. Om man vill följa kommentarskedjor utanför de möten man är medlem i kan man slå på den här inställningen.") (kom-read-depth-first-doc . "\ LysKOM kan visa inlägg antingen i den ordning de skapades, eller i den ordning de ligger i kommentarsträdet. Ta till exempel följande inlägg: Inlägg 1002 är inte en kommentar till någonting. Inlägg 1003 och 1004 är kommentarer till inlägg 1002. Inlägg 1005 och 1007 är kommentarer till inlägg 1004 och inlägg 1006 är en kommentar till inlägg 1003. Då ser kommentarsträdet ut ungefär så här: 1002 +-- 1003 --- 1006 | +-- 1004 +-- 1005 | +-- 1007 Om man läser inläggen i tidsordning kommer de att visas i ordningen 1002, 1003, 1004, 1005, 1006 och 1007. I kommentarsordning blir det i stället 1002, 1003, 1006, 1004, 1005 och 1007.") (kom-continuous-scrolling-doc . "\ Påslaget innebär att klienten scrollar bufferten medan ny text sätts in, så man ser det senaste som har satts in. Detta fungerar bra om man har en snabb terminal, men kan vara värt att slå av om terminalen är långsam, och scrollning i Emacs tar tid.") (kom-deferred-printing-doc . "\ För att snabba upp LysKOM så skrivs vissa saker, som person- och mötesnamn inte ut omedelbart, utan skrivs först ut som \"[...]\", vilket sedan byts ut mot den rätta utskriften när texten finns tillgänglig. Detta snabbar upp svarstiderna i klienten ganska mycket, men går att stänga av med den här inställningen om man tycker det ser otrevligt ut.") (kom-higher-priority-breaks-doc . "\ När texter kommer in till möten som har högre prioritet än det man läser kan klienten låta en läsa dessa texter omedelbart, efter den aktuella kommentarskedjan eller efter man har läst ut mötet.") (kom-login-hook-doc . "\ Kommandon som skall köras när man loggar in, innan någon inmatning från tangentbordet tas emot. Till exempel kan man göra Lista nyheter här för att få se en lista av nyheter varje gång man loggar in.") (kom-do-when-done-doc . "\ Kommandon som skall köras när man har läst ut alla inlägg. Det är ganska vanligt att man har Återse alla markerade här. Både tangentbordsmakron och regelrätta funktioner går bra.") (kom-page-before-command-doc . "\ LysKOM-bufferten kan scrollas före alla kommandon så att text som sätts in av kommandot hamnar överst i fönstret. Denna variabel talar om före vilka kommandon detta skall ske.") (kom-permissive-completion-doc . "\ Om detta är påslaget så kommer TAB bara att fylla ut namn på inloggade personer när kommandot bara kan utföras på inloggade personer (till exempel Status (för) session och Sända meddelande). Om det är avslaget kommer TAB att fylla ut även med namn på personer som inte är inloggade.") (kom-membership-default-priority-doc . "\ Detta bestämmer hur prioriteten på möten man går med i sätts. Om det är en siffra mellan 1 och 255 så kommer nya medlemskap att få den prioriteten. I annat fall kommer klienten att fråga för varje nytt medlemskap vilken prioritet det skall ha.") (kom-membership-default-message-flag-doc . "\ Detta bestämmer om gruppmeddelanden tas emot i möten man går med i. `Ja' betyder att gruppmeddelanden tas emot, `Nej' att meddelanden inte tas emot. `Fråga varje gång' att klienten frågar när du går med i möten.") (kom-show-personal-messages-in-buffer-doc . "\ Denna inställning bestämmer var personliga meddelanden, gruppmeddelanden och alarmmeddelanden visas. Meddelanden kan antingen visas i LysKOM-bufferten, kastas bort helt eller visas i en namngiven buffert.") (kom-pop-personal-messages-doc . "\ Om personliga meddelanden skall visas i en egen buffert och denna inställning också är påslagen så kommer den bufferten att visas så fort ett meddelande anländer.") (kom-audio-player-doc . "\ Om man vill att LysKOM skall spela ljudfiler i stället för att pipa vid olika tillfällen måste denna inställning peka ut ett program som klarar att spela ljudfilerna. Programmet skall ta ett argument: namnet på filen som skall spelas.") (kom-default-message-recipient-doc . "\ Denna inställning bestämmer vem som kommer att vara defaultmottagare för personliga meddelanden man skickar. Alternativen som finns är att meddelanden normalt är allmänna, att avsändaren för det senast mottagna meddelandet skall vara default eller att mottagaren för det senaste gruppmeddelandet (eller avsändaren av det senaste personliga eller allmänna meddelandet) skall vara mottagare.") (kom-filter-outgoing-messages-doc . "\ Om denna inställning är påslagen så kommer meddelanden som skickas automatiskt, till exempel automatiska svar och svar på fjärrkontrollförsök även att visas som om man hade skickat det manuellt.") (kom-friends-doc . "\ Namnen på personerna i denna lista kommer att visas med ett speciellt utseende i LysKOM-bufferten. Kommandot Vilka vänner är inloggade (och andra liknande kommandon) använder också denna lista.") (kom-morons-doc . "\ Namnen på personerna i denna lista kommer att visas med ett varnande utseende i LysKOM-bufferten.") (kom-url-viewer-preferences-doc . "\ Denna inställning bestämmer vilken WWW-läsare som i första hand skall användas för att öppna URLer som förekommer i LysKOM. Om den första läsaren i listan inte klarar den typ av URL som man försöker öppna så används nästa läsare och så vidare.") (kom-windows-browser-command-doc . "\ Denna inställning talar om vilket kommando som skall användas för att starta en WWW-läsare i Windows. Om fältet är tomt testas ett antal kommandon som typiskt brukar fungera i Windows.") (kom-mosaic-command-doc . "\ Denna inställning talar om vilket kommando som skall användas för att starta Mosaic.") (kom-netscape-command-doc . "\ Denna inställning anger kommandot för att köra Netscape eller Mozilla.") (kom-galeon-command-doc . "\ Denna inställning anger kommandot för att köra Galeon.") (kom-inhibit-typeahead-doc . "\ Normalt sparas tangenttryckningar som görs medan klienten är upptagen, och utförs när det blir möjligt. Om denna inställning är avslagen så kommer LysKOM enbart att utföra kommandon som ges när klienten inte arbetar.") (kom-max-buffer-size-doc . "\ Det är möjligt att begränsa LysKOM-buffertens storlek genom att ange hur stor den får bli i den här variabeln. Om bufferten blir för stor kommer information från buffertens början att tas bort.") (kom-ansaphone-record-messages-doc . "\ LysKOM kan \"spela in\" meddelanden som kommer när funktionen för automatiskt svar är påslagen. Denna inställning bestämmer om så sker eller inte.") (kom-ansaphone-show-messages-doc . "\ Om denna inställning är påslagen kommer LysKOM att visa inkomna personliga meddelanden även om automatiskt svar är påslaget.") (kom-ansaphone-default-reply-doc . "\ Automatsvararen skickar detta meddelande om inget annat meddelande har specificerats via någon annan mekanism (och den är bara till för försiktiga experter).") (kom-remote-control-doc . "\ Påslagen innebär att det går att fjärrstyra klienten. Fjärrstyrningen är dock begränsad till vissa personer.") (kom-remote-controllers-doc . "\ Personerna i denna lista får fjärrstyra klienten.") (kom-self-control-doc . "\ Om detta är påslaget får användaren som är inloggad styra klienten från en annan session. Detta är ett alternativ till att lägga in sig själv i listan över tillåtna fjärrstyrare.") (kom-customize-format-doc . "\ Dokumentation till inställningarna kan vara på eller avslagen när inställningsfönstret öppnas. Dokumentationen kan alltid visas eller gömmas för varje enskild inställning genom att använda frågetecknet eller utropstecknet som står till höger om inställningen.") (kom-default-language-doc . "\ Språk som skall användas i LysKOM. Om du ändrar inställningen här så kommer inte inställningen ändras för aktuell session, utan du måste ge kommandot Ändra språk också. Det första språk på listan som är tillgängligt kommer att väljas av alla klienter med stöd för funktionen.") (kom-ispell-dictionary-doc . "\ Ordlista som skall användas av stavningskontrollen i LysKOM. Om detta är satt till kom-ispell-dictionary så kommer variabeln ispell-dictionary att användas istället.") (kom-show-namedays-doc . "\ Påslaget innebär att dagens namn visas när man ser tiden. Det går att välja att se namnsdagarna från namnsdagslängden som hör till det språk man för närvarande använder eller att använda en specifik lista med namn.") (kom-show-week-number-doc . "\ Se tiden visar veckonummer om detta är påslaget. Annars visas inte veckonummer.") (kom-relogin-behaviour-doc . "\ Denna inställning styr om klienten ska försöka återansluta om ett kommando ges i en nedkopplad session. På betyder att det sker automatiskt, av att klienten inte frågar om man vill återansluta.") (kom-relogin-inhibit-commands-doc . "\ Kommandon som inte skall orsaka någon återanslutning. Dessa kommandon kommer inte att orsaka att en nedkopplad klient återansluter.") (kom-membership-default-placement-doc . "\ Denna inställning styr var nya medlemskap hamnar. Först betyder att nya medlemskap hamnar före gamla med samma prioritet. Sist betyder att nya medlemskap hamnar efter gamla med samma prioritet. En siffra är en fix placering i medlemskapslistan (men medlemskapet kommer att flyttas såsmåningom).") (kom-show-imported-importer-doc . "\ Påslaget betyder visa vilken person som importerade ett importerat e-mail.") (kom-show-imported-envelope-sender-doc . "\ Visa den verkliga avsändaren till ett importerat e-mail om detta är påslaget.") (kom-show-imported-external-recipients-doc . "\ Visa externa mottagare och extra-kopiemottagare om detta är påslaget.") (kom-show-imported-message-id-doc . "\ Påslaget betyder visa meddelande-id.") (kom-agree-text-doc . "\ Text som används av kommandot Hålla med. Det kan antingen vara en text eller en lista av texter. Om det är en lista så väljs ett alternativ slumpmässigt.") (kom-silent-ansaphone-doc . "\ On detta är avslaget så piper inte klienten när det kommer meddelanden och automatsvar är påslaget.") (kom-default-session-priority-doc . "\ Läsnivå för nya sessioner. Detta är den läsnivå som nya sessioner får automatiskt.") (kom-unsubscribe-makes-passive-doc . "\ Om detta är påslaget så gör kommandot Utträda ur möte att man först blir passiv medlem i mötet. Om man utträder ur mötet igen så går man ur på riktigt. Om detta är avslaget så går man ur mötet första gången man försöker utträda.") (kom-review-priority-doc . "\ Prioritet för återsekommandon. Detta är den prioritet som inläggen man ser när man gör återse får. Det används för att avgöra om nya inlägg skall avbryta återsefunktionen. Sätt till 256 eller högre om du inte vill att nya inlägg någonsin skall avbryta en återsefunktion.") (kom-show-creating-software-doc . "\ Om detta är påslaget så visas vilken klient som skapade inlägget tillsammans med varje inlägg, förutsatt att informationen finns överhuvudtaget.") (kom-text-footer-format-doc . "\ Format för inläggsfoten. I texten ersätts %n med inläggsnumret, %P med författarens namn, %p med författarens nummer, %f med information om inlägget (ombruten, HTML mm.) och %- med en lagom lång streckad linje. En siffra efter procenttecknet är minsta bredd på texten. Ett minustecken före siffran betyder att texten skall vänsterjusteras. Ett likhetstecken betyder att fältlängden är exakt och texten kanske kortas av.") (kom-long-lines-doc . "\ Om detta är påslaget så görs de flesta streckade linjer i klienten mycket längre än normalt.") (kom-postpone-default-doc . "\ Antalet inlägg som inte skall uppskjutas med Uppskjuta läsning.") (kom-allow-incompleteness-doc . "\ Påslaget betyder att klienten inte väntar på att information om alla olästa har kommit fram innan den tillåter kommandon som Lista nyheter. Avslaget innebär att klienten väntar på information om olästa inlägg om den upptäcker att informationen behövs och inte har kommit fram.") (kom-smileys-doc . "\ Gladmän, som :-), visas grafiskt när denna inställning är på, förutsatt att Emacs klarar det och paketet smiley.el (en del av Gnus) är installerat.") (kom-ignore-message-senders-doc . "\ Visa inte personliga, grupp- och alarmmeddelanden från dessa personer.") (kom-ignore-message-recipients-doc . "\ Visa inte gruppmeddelanden riktade till dessa möten.") (kom-text-footer-dash-length-doc . "\ Den totala längden på inläggsfoten när streckade linjer, men inte extra långa linjer, och inte ett eget format används.") (kom-text-header-dash-length-doc . "\ Den totala längden på den streckade linjen ovanför inläggstexten när extra långa linjer inte används.") (kom-show-personal-message-date-doc . "\ När detta är påslaget så visas datum och klockslag för alla personliga, grupp- och alarmmeddelanden.") (kom-w3-simplify-body-doc . "\ När detta är påslaget så visas HTML utan de färger som anges i HTML-koden.") (kom-mercial-doc . "\ Denna text visas i vilkalistan då du har läst färdigt alla möten.") (kom-session-nickname-doc . "\ Hur sessionsnamn bestäms. Detta är det namn som visas i mode-raden och av Lista sessioner.") (kom-server-priority-doc . "\ Prioritet för sessionen. Sessioner med hög prioritet kan avbryta andra sessioner, beroende på inställningen av YYY.") (kom-server-priority-breaks-doc . "\ Denna inställning styr hur prioriterade sessioner avbryter andra sessioner. En session är högre prioriterad än en annan om dess sessionsprioritet är högre än den andra sessionens. Omedelbart Så fort der kommer ett inlägg i en prioriterad session så får man prompt om att gå till den sessionen. Omedelbart om det kommer brev Så fort det kommer ett personligt brev i en prioriterad session så får man prompt om att gå till den sessionen. Efter aktuell kommentarskedja Om det kommer inlägg i en prioriterad session så får man prompt om att gå till sessionen när man har läst klart den aktuella kommentarskedjan. Efter aktuell kommentarskedja om det kommer brev Om det kommer personliga brev i en prioriterad session så får man prompt om att gå till sessionen när man har läst klart den aktuella kommentarskedjan. Efter aktuellt möte Om det kommer inlägg i en prioriterad session så får man prompt om att gå till sessionen när man har läst klart det aktuella mötet. Efter aktuellt möte när det kommer brev Om det kommer brev i en prioriterad session så får man prompt om att gå till sessionen när man har läst klart det aktuella mötet. När allt är utläst Ge prompt om att byta till nästa LysKOM med olästa inlägg när allt är klart, oberoende av sessionernas prioritet. Aldrig Ge aldrig prompt om att byta session.") (kom-ding-on-no-subject-doc . "") (kom-ding-on-personal-messages-doc . "") (kom-ding-on-group-messages-doc . "") (kom-ding-on-common-messages-doc . "") (kom-ding-on-no-subject-doc . "") (kom-ding-on-wait-done-doc . "") (kom-ding-on-priority-break-doc . "") (kom-ding-on-new-letter-doc . "") (kom-check-for-new-comments-doc . "") (kom-check-commented-author-membership . "") (kom-confirm-multiple-recipients-doc . "") (kom-check-commented-author-membership-doc . "") (kom-complete-numbers-before-names-doc . "\ När detta är påslaget och man matar in en text som kan tolkas både som ett mötesnamn eller ett mötesnummer vid inläsning av mötesnamn, så tolkar klienten det i första hand som ett nummer. När detta är avslaget så tolkas det i första hand som ett mötesnamn.") (kom-keep-alive-interval-doc . "\ Antalet sekunder som skall gå mellan de meddelanden som används för att hålla nätverkskopplingen till LysKOM-servern aktiv. Om din förbindelse kopplar ned efter en stunds inaktivitet så kan du sätta detta till ungefär hälften och sedan ge kommandot \"Håll förbindelsen aktiv\".") (kom-text-no-prompts-doc . "\ Den här inställningen styr vilka kommandon som alltid frågar efter textnummer (om man inte anger ett explicit som prefixargument). För kommandon som inte står med här används inbyggda standardinställningar.") (kom-saved-file-name-doc . "\ Anger vilken fil som inlägg skall arkiveras till. Klienten kommer ändå att fråga, men detta blir det förifyllda svaret.") (kom-follow-attachments-doc . "\ Anger om bilagor till importerade brev skall läsas som kommentarer. Om detta är avstängt så läsmarkeras bilagor automatiskt, utan att man läser dem.") (kom-show-unread-in-frame-title-doc . "\ Om detta är påslaget så visas \"(Olästa)\" i titelraden för de fönster vars valda buffert hör till en LysKOM-session med olästa. Det är inte säkert att titelraden ändras om fönstret inte är öppet.") (kom-unread-mode-line-type-doc . "\ Denna inställning bestämmer hur olästa indikeras i mode-raden. `Enkel' betyder en gemensam indikering för samtliga sessioner ifall du har olästa texter eller brev. `Visa alla sessioner med olästa' betyder att alla sessioner med olästa texter indikeras separat. Förekomst med brev indikeras genom att sessionsnamnet visas med stora bokstäver (till exempel LYSLYS istället för LysLys). Om sessionsnamnet bara innehåller versaler (exempelvis LYSLYS) visas det mellan asterisker (*LYSLYS*). Notera att denna inställning bör vara samma för alla aktiva LysKom-sessioner varför det troligen är bäst att spara den i din .emacs.") (kom-created-texts-are-saved-doc . "\ Om detta är ett filnamn så sparas alla inlägg man skriver till den filen i ungefär samma format som de har när man läser dem. Inlägg som inte kan skapas sparas inte.") (kom-confirm-add-recipients-doc . "\ Om detta är påslaget och man adderar en mottagare till ett inlägg så frågar klienten om man vill att kommentarer till inlägget också skall skickas till den nya mottagaren. Om detta är avslaget så kommer kommentarer alltid att skickas även till den nya mottagaren. Det är oftast bra att ha påslaget.") (kom-trim-buffer-minimum-doc . "\ Om du begränsar LysKOM-buffertens storlek så måste den bli så här mycket för stor innan text i bufferten raderas. Variablen ska vara ett heltal, default är 4096.") (kom-dont-check-commented-authors-doc . "") (kom-print-relative-dates-doc . "\ Tidsangivelsen för inlägg (och en del andra saker) kommer att bli \"idag\" alternativt \"igår\" om denna inställning är påslagen och inlägget skrevs idag alternativt igår. Om den är avslagen kommer ett absolut datum alltid att visas.") (kom-print-seconds-in-time-strings-doc . "\ Om denna inställning är påslagen kommer en del tidsangivelser (till exempel för visade inlägg och sända meddelanden) att inkludera sekunder.") (kom-review-uses-cache-doc . "\ Om detta är påslaget så kommer kommandon som återser inlägg att använda sparade kopior av inläggen om de finns. Det gör att kommandona går lite snabbare, men det finns en viss risk för att ett inlägg kan ha ändrats sedan kopian sparades.") (kom-review-marks-texts-as-read-doc . "\ Om detta är påslaget så kommer kommandon som återser inlägg att läsmarkera de inlägg som visas. I annat fall lämnar återsekommandona din läshistorik orörd, precis som vanligt.") (kom-auto-review-faqs-doc . "\ Om detta är påslaget så kommer olästa FAQer inte att återses automatiskt när du loggar in eller går till ett möte med en oläst FAQ.") (kom-auto-list-faqs-doc . "\ Om detta är påslaget så kommer olästa FAQer att listas automatiskt när du loggar in eller går till ett möte med en oläst FAQ.") (kom-extended-status-information-doc . "\ Om detta är påslaget så visas extra statusinformation i kommandona Status (för) person, Status (för) möte och Status (för) servern (om sådan information finns tillgänglig).") (kom-highlight-first-line-doc . "\ Om detta är påslaget så visas första raden i varje inlägg (den med inläggsnummer, datum och författare) med ett annorlunda utseende än normal text.") (kom-highlight-dashed-lines-doc . "\ Om detta är påslaget så visas raderna före och efter inläggstexten med ett annorlunda utseende än normal text.") (kom-highlight-text-body-doc . "\ Om detta är påslaget så visas inläggstexter med ett annorlunda utseende än normal text.") (kom-async-highlight-dashed-lines-doc . "\ Om detta är påslaget så visas raderna före och efter personliga, grupp- och alarmmeddelanden med ett annorlunda utseende än normal text.") (kom-async-highlight-text-body-doc . "\ Om detta är påslaget så visas personliga, grupp- och alarmmeddelanden med ett annorlunda utseende än normal text.") (kom-edit-hide-add-button-doc . "\ Om detta är påslaget så kommer knappen [Addera...] att visas efter mottagare och tilläggsinformation när man skriver inlägg.") (kom-format-html-authors-doc . "\ Den här inställningen styr vilka författares HTML-meddelanden som elispklienten kommer att försöka formattera.") (kom-format-show-images-doc . "\ Den här inställningen styr om inlägg uppmärkta som bilder specialhanteras eller visas som traditionella inlägg.") (kom-keyboard-menu-immediate-selection-doc . "\ Den här inställningen styr huruvida snabbtangenter automatiskt bekräftar val i textbaserade menyer eller inte. Om detta är påslaget så måste man alltid trycka retur för att välja i textbaserade menyer.") (kom-max-overlays-doc . "\ Med denna inställning kan man begränsa antalet färgmarkeringar (som används bland annat för färgade inläggsbakgrunder). Genom att begränsa antalet markeringar kan scrollning gå mycket fortare. Varje inlägg behöver mellan 1 och 4 markeringar beroende på andra inställningar.") (kom-mark-read-texts-as-read-in-new-recipient-doc . "\ Om detta är påslaget så läsmarkeras redan lästa inlägg automatiskt i möten de adderas till medan man är inloggad. Om man inte är inloggad så sker inte denna läsmarkering. Inlägg som adderas till ens brevlåda läsmarkeras dock aldrig automatiskt.") (kom-url-transformation-rules-doc . "\ Regler för att transformera URLer innan de skickas till en webbläsare. \"Från\" är ett mönster (en regexp) som skall översättas till texten i \"Till\". Dokumentation om regexpar finns i Emacs-manualen. \"Till\" kan innehålla följande specialtecken: \\& ersätts med den text som matchar regexpen \\N ersätts med den text som matchar \(...\)-uttryck N i regexpen \\\\ ersätts med en \\.") (kom-text-links-doc . "\ Definition av textlänkar. Varje rad definierar en länk för inlägg i ett visst möte. Alla förekomster av länkmönstret blir URL-länkar genom att texten som länkmönstret matchar substitueras enligt länksubstitutionen. Den text som faktist visas som länk i LysKOM-bufferten bestäms av inställningen \"Visa grupp\". Använd 0 för att visa hela den matchande texten eller en siffta från 1 till 9 för att visa den N-te gruppen i länkmönstret (använd 0 om du inte förstår vad som avses med detta). Om inställningen \"Versaler och gemener lika\" är på så räknas versaker och gemener av samma bokstav som lika. Länksubstitutionen kan innehålla följande specialtecken: \\& ersätts med den text som matchar regexpen \\N ersätts med den text som matchar \(...\)-uttryck N i regexpen \\\\ ersätts med en \\.") (kom-active-face-doc . "\ Teckensnitt för klickbara texter förutom URLer, möten, vänner och bekanta, idioter och knäppskallar, och inläggsnummer. Värdet skall vara namnet på en så kallad `face'.") (kom-active-highlight-face-doc . "\ Teckensnitt avsett för klickbara texter som skall markeras extra tydligt. Värdet skall vara namnet på en så kallad `face'.") (kom-active-strikethrough-face-doc . "\ Teckensnitt avsett för klickbara texter som skall markeras extra tydligt. Värdet skall vara namnet på en så kallad `face'.") (kom-url-face-doc . "\ Teckensnitt för klickbara URLer.") (kom-me-face-doc . "\ Teckensnitt för ens eget namn.") (kom-highlight-face-doc . "\ Teckensnitt för markering av klickbara ytor när muspekaren förs över dem.") (kom-subject-face-doc . "\ Teckensnitt för ärenderader.") (kom-text-no-face-doc . "\ Teckensnitt för inläggsnummer.") (kom-friends-face-doc . "\ Teckensnitt för vänner och bekanta. De personer som räknas upp i listan \"vänner och bekanta\" kommer att markeras med detta teckensnitt.") (kom-morons-face-doc . "\ Teckensnitt för idioter och knäppskallar. De personer som räknas upp i listan \"Idioter och knäppskallar\" kommer att markeras med detta teckensnitt.") (kom-presence-face-doc . "\ Teckensnitt för närvaromeddelanden.") (kom-first-line-face-doc . "\ Teckensnitt för första raden i inläggshuvudet. Detta teckensnitt överlagras på standardteckensnitten i första raden, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-warning-face-doc . "\ Teckensnitt för viktiga varningar.") (kom-mark-face-doc . "\ Teckensnitt för diverse markeringar. Bland annat används detta teckensnitt för markeringen när elispklienten bläddrar mindre än en hel skärmsida. Detta teckensnitt överlagras på standardteckensnitten där det används, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-dim-face-doc . "\ Teckensnitt för diverse diskreta texter. Detta teckensnitt används bland annat för att visa passiva medlemskap.") (kom-text-body-face-doc . "\ Teckensnitt för inläggstexter. Detta teckensnitt överlagras på standardteckensnitten i inläggstexten, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-dashed-lines-face-doc . "\ Teckensnitt för streckrader runt inlägg. Detta teckensnitt överlagras på standardteckensnitten i streckraden, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-async-text-body-face-doc . "\ Teckensnitt för meddelanden. Detta teckensnitt överlagras på standardteckensnitten i meddelandet, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-async-dashed-lines-face-doc . "\ Teckensnitt för streckrader runt meddelanden. Detta teckensnitt överlagras på standardteckensnitten i streckraderna, så de egenskaper som inte sätts av detta teckensnitt kommer inte att påverkas.") (kom-lynx-terminal-doc . "\ Lynx kan köras inuti Emacs eller i en xterm (eller motsvarande). Här väljer du vilket.") (kom-lynx-terminal-command-doc . "\ Kommandot som används för att starta Lynx i Emacs terminal-mode. Ska normalt vara så enkelt som \"lynx\".") (kom-lynx-xterm-command-doc . "\ Kommandot som används för att starta Lynx i en xterm. Kommandot ska starta både xterm och lynx.") (kom-show-sync-messages-doc . "\ Om denna inställning är påslagen så kommer klienten att visa ett meddelande i ekoarean nät servern signallerar att den håller på spara databasen.") (kom-highlight-conferences-doc . "\ Denna inställning styr hur mötesnamn färgläggs. För varje val kan ett utseende anges. Utseendena är namn på faces i Emacs.") (kom-netscape-variant-doc . "\ Denna inställning styr var elispklienten försöker öppna URLer. Hur bra de olika valen fungerar beror på vilken variant av Netscape eller Mozilla man använder, och till och med vilket operativsystem man använder.") (kom-auto-confirm-new-conferences-doc . "\ Om den här inställningen är påslagen så kommer kommandona \"Lista nya möten\" och \"Lista nya personer\" automatiskt markera nya möten och personer som kända.") (kom-text-properties-doc . "\ Om den här inställningen är på så kommer klienten att använda olika typsnitt och färger till olika saker. Till exempel kommer textnummer och annat man kan klicka på att visas med en avvikande färg.") (kom-fontify-text-doc . "\ Om den här inställningen är på så kommer fet och kursiv stil att användas i inläggstext. Till exempel så kommer ord och fraser omgivna av understrykningstecken att visas med kursiv text.") ;; ;; Tags for variables ;; (kom-ansaphone-replies-tag . "Detaljerade automatsvar") (kom-bury-buffers-tag . "Begrav buffertar när man byter LysKOM:") (kom-personal-messages-in-window-tag . "Personliga meddelanden: ") (kom-customize-in-window-tag . "Inställningar för LysKOM: ") (kom-write-texts-in-window-tag . "Skriv inlägg: ") (kom-prioritize-in-window-tag . "Prioritera möten: ") (kom-edit-filters-in-window-tag . "Ändra filter: ") (kom-view-commented-in-window-tag . "Återse kommentarer: ") (kom-list-membership-in-window-tag . "Lista medlemskap: ") (kom-user-prompt-format-tag . "Promptformat:") (kom-user-prompt-format-executing-tag . "Promptformat vid körning:") (kom-anonymous-prompt-format-tag . "Promptformat (anonym):") (kom-anonymous-prompt-format-executing-tag . "Promptformat vid körning (anonym):") (kom-enabled-prompt-format-tag . "Promptformat (admin):") (kom-enabled-prompt-format-executing-tag . "Promptformat vid körning (admin):") (kom-higher-priority-breaks-tag . "Läs prioriterade texter: ") (kom-created-texts-are-read-tag . "Läsmarkera skapade texter: ") (kom-default-mark-tag . "Defaultmarkering: ") (kom-print-number-of-unread-on-entrance-tag . "Visa olästa när man går till ett möte: ") (kom-follow-comments-outside-membership-tag . "Följ kommentarskedjor utanför medlemskap: ") (kom-show-footnotes-immediately-tag . "Visa fotnoter omedelbart: ") (kom-membership-default-priority-tag . "Prioritet för nya medlemskap: ") (kom-membership-default-message-flag-tag . "Mottag gruppmeddelanden för nya medlemskap: ") (kom-dashed-lines-tag . "Streckade linjer kring inläggstexten: ") (kom-autowrap-tag . "Automatisk radbrytning vid läsning: ") (kom-autowrap-timeout-tag . "Tidsbegränsning av automatisk radbrytning: ") (kom-show-author-at-end-tag . "Visa författarens namn efter inlägget: ") (kom-truncate-threshold-tag . "Korta av långa inlägg: ") (kom-truncate-show-lines-tag . "Rader att visa vid avkortade inlägg: ") (kom-reading-puts-comments-in-pointers-last-tag . "Kommentarslänkar visas:") (kom-read-depth-first-tag . "Läsordning:") (kom-deferred-printing-tag . "Fördröjda utskrifter:") (kom-continuous-scrolling-tag . "Omedelbar scrollning:") (kom-presence-messages-in-echo-area-tag . "Närvaromeddelanden i ekoarean: ") (kom-presence-messages-in-buffer-tag . "Närvaromeddelanden i LysKOM-bufferten:") (kom-page-before-command-tag . "Rensa skärmen:") (kom-remember-password-tag . "Kom ihåg LysKOM-sessionslösenordet:") (kom-idle-hide-tag . "Antal minuter en session får vara inaktiv och ändå visas: ") (kom-show-where-and-what-tag . "Visa varifrån personer är inloggade och vad de gör: ") (kom-show-since-and-when-tag . "Visa när personer loggade in och när de var aktiva: ") (kom-login-hook-tag . "Kommandon som körs vid login:") (kom-do-when-done-tag . "Kommandon som körs efter allt är utläst:") (kom-permissive-completion-tag . "Petig utfyllnad av namn:") (kom-show-personal-messages-in-buffer-tag . "Var visas meddelanden: ") (kom-pop-personal-messages-tag . "Ploppa upp meddelandebufferten: ") (kom-default-message-recipient-tag . "Defaultmottagare för meddelanden:") (kom-audio-player-tag . "Ljudspelarprogram:") (kom-ding-on-new-letter-tag . "När det kommer brev: ") (kom-ding-on-priority-break-tag . "När det kommer prioriterade inlägg: ") (kom-ding-on-wait-done-tag . "När man har väntat klart: ") (kom-ding-on-common-messages-tag . "Vid alarmmeddelanden: ") (kom-ding-on-group-messages-tag . "Vid gruppmeddelanden: ") (kom-ding-on-personal-messages-tag . "Vid personliga meddelanden: ") (kom-ding-on-no-subject-tag . "När ärenderad saknas: ") (kom-filter-outgoing-messages-tag . "Visa automatiska meddelanden:") (kom-friends-tag . "Vänner och bekanta:") (kom-morons-tag . "Idioter och knäppskallar:") (kom-url-viewer-preferences-tag . "Öppna URLer med följande program:") (kom-windows-browser-command-tag . "Kommando för att starta en WWW-läsare i Windows:") (kom-mosaic-command-tag . "Kommando för att starta NCSA Mosaic:") (kom-netscape-command-tag . "Kommando för att starta Netscape eller Mozilla:") (kom-galeon-command-tag . "Kommando för att starta Galeon:") (kom-symbolic-marks-alist-tag . "Symboliska markeringstyper:") (kom-cite-string-tag . "Citatmarkering:") (kom-confirm-multiple-recipients-tag . "Bekräfta multipla mottagare: ") (kom-check-commented-author-membership-tag . "Kontrollera kommenterad författares medlemskap:") (kom-check-for-new-comments-tag . "Kontrollera olästa kommentarer: ") (kom-ansaphone-record-messages-tag . "Spara meddelanden då automatiskt svar är påslaget: ") (kom-ansaphone-show-messages-tag . "Visa meddelanden då automatiskt svar är påslaget: ") (kom-ansaphone-default-reply-tag . "Svarsmeddelande:") (kom-inhibit-typeahead-tag . "Buffra tangenttryckningar:") (kom-max-buffer-size-tag . "Maximal buffertstorlek:") (kom-remote-control-tag . "Fjärrstyrning: ") (kom-self-control-tag . "Tillåt fjärrstyrning av mig själv: ") (kom-remote-controllers-tag . "Tillåtna fjärrstyrare:") (kom-customize-format-tag . "Visa hjälptexterna för inställningar:") (kom-default-language-tag . "Språklista:") (kom-ispell-dictionary-tag . "Ordlista:") (kom-show-namedays-tag . "Visa dagens namn:") (kom-show-week-number-tag . "Visa veckonummer:") (kom-relogin-behaviour-tag . "Återanslut automatiskt:") (kom-relogin-inhibit-commands-tag . "Kommandon för vilka återanslutning aldrig sker automatiskt:") (kom-membership-default-placement-tag . "Placering av nya medlemskap:") (kom-show-imported-importer-tag . "Visa importör av importerade inlägg:") (kom-show-imported-envelope-sender-tag . "Visa avsändare av importerade inlägg:") (kom-show-imported-external-recipients-tag . "Visa externa mottagare till importerade inlägg:") (kom-show-imported-message-id-tag . "Visa meddelande-id för importerade inlägg:") (kom-agree-text-tag . "Text för Hålla med:") (kom-silent-ansaphone-tag . "Pip när automatsvar är påslaget:") (kom-default-session-priority-tag . "Läsnivå för nya sessioner:") (kom-unsubscribe-makes-passive-tag . "Utträda ur möte gör om medlemskap till passiva:") (kom-review-priority-tag . "Prioritet för återsekommandon:") (kom-show-creating-software-tag . "Visa skapande klient:") (kom-text-footer-format-tag . "Format för inläggsfot:") (kom-long-lines-tag . "Långa streckade linjer:") (kom-postpone-default-tag . "Skönsvärde för uppskjuta läsning:") (kom-allow-incompleteness-tag . "Tillåt ofullständig information om olästa:") (kom-smileys-tag . "Visa gladmän grafiskt:") (kom-ignore-message-senders-tag . "Visa inte meddelanden från:") (kom-ignore-message-recipients-tag . "Visa inte meddelanden till:") (kom-text-footer-dash-length-tag . "Inläggsfotens längd:") (kom-text-header-dash-length-tag . "Längden på linjen ovanför inläggstexten:") (kom-show-personal-message-date-tag . "Visa datum för alla meddelanden:") (kom-w3-simplify-body-tag . "Visa HTML utan standardfärger:") (kom-mercial-tag . "Text när allt är utläst:") (kom-session-nickname-tag . "Hur bestäms sessionsnamn:") (kom-server-priority-tag . "Sessionsprioritet:") (kom-server-priority-breaks-tag . "Byt till LysKOM med olästa:") (kom-complete-numbers-before-names-tag . "Läs mötesnummer före mötesnamn:") (kom-keep-alive-interval-tag . "Intervall för håll förbindelsen igång:") (kom-text-no-prompts-tag . "Hur kommandon frågar efter textnummer:") (kom-saved-file-name-tag . "Fil att arkivera inlägg i:") (kom-follow-attachments-tag . "Läs importerade bilagor som vanligt:") (kom-show-unread-in-frame-title-tag . "Visa olästamarkering i titelraden:") (kom-unread-mode-line-type-tag . "Typ av olästaindikering i mode-raden:") (kom-created-texts-are-saved-tag . "Spara författade inlägg:") (kom-confirm-add-recipients-tag . "Fråga om kommentarer skall sändas till nya mottagare:") (kom-trim-buffer-minimum-tag . "Minsta storlek av LysKOM-bufferten som tas bort:") (kom-dont-check-commented-authors-tag . "Författare som inte kontrolleras:") (kom-print-relative-dates-tag . "Visa relativa datumangivelser:") (kom-print-seconds-in-time-strings-tag . "Inkludera sekunder i tidsangivelser:") (kom-review-uses-cache-tag . "Återsekommandon använder sparade inlägg:") (kom-review-marks-texts-as-read-tag . "Återsekommandon läsmarkerar visade texter:") (kom-auto-review-faqs-tag . "Visa nya FAQer automatiskt:") (kom-auto-list-faqs-tag . "Lista nya FAQer automatiskt:") (kom-extended-status-information-tag . "Utökad statusinformation:") (kom-highlight-first-line-tag . "Annorlunda bakgrundsfärg på första raden:") (kom-highlight-dashed-lines-tag . "Annorlunda bakgrundsfärg före och efter inläggstexten:") (kom-highlight-text-body-tag . "Annorlunda bakgrundsfärg på inläggstexten:") (kom-async-highlight-dashed-lines-tag . "Annorlunda bakgrundsfärg före och efter meddelanden:") (kom-async-highlight-text-body-tag . "Annorlunda bakgrundsfärg på meddelanden:") (kom-edit-hide-add-button-tag . "Visa Addera-knappen när man skriver inlägg:") (kom-format-html-authors-tag . "Formattera HTML-meddelanden per författare:") (kom-format-show-images-tag . "Visa bildinlägg som bilder:") (kom-keyboard-menu-immediate-selection-tag . "Snabbval i textmenyer kräver bekräftelse:") (kom-max-overlays-tag . "Högsta antal färgmarkeringar:") (kom-mark-read-texts-as-read-in-new-recipient-tag . "Markera lästa inlägg lästa även i nya mottagare:") (kom-url-transformation-rules-tag . "Transformation av URLer:") (kom-text-links-tag . "Textlänkar:") (kom-active-face-tag . "Övriga klickbara texter:") (kom-active-highlight-face-tag . "Tydligare markerade klickbara texter:") (kom-active-strikethrough-face-tag . "Överstrukna klickbara texter:") (kom-url-face-tag . "Klickbara URLer:") (kom-me-face-tag . "Mitt eget namn:") (kom-highlight-face-tag . "Markering av klickbara ytor:") (kom-subject-face-tag . "Ärenderader:") (kom-text-no-face-tag . "Inläggsnummer:") (kom-friends-face-tag . "Vänner och bekanta:") (kom-morons-face-tag . "Idioter och knäppskallar:") (kom-presence-face-tag . "Närvaromeddelanden:") (kom-first-line-face-tag . "Första raden i inläggshuvudet:") (kom-warning-face-tag . "Viktiga varningar:") (kom-mark-face-tag . "Diverse markeringar:") (kom-dim-face-tag . "Diverse diskreta texter:") (kom-text-body-face-tag . "Inläggstexter:") (kom-dashed-lines-face-tag . "Streckrader runt inlägg:") (kom-async-text-body-face-tag . "Meddelanden:") (kom-async-dashed-lines-face-tag . "Streckrader runt meddelanden:") (kom-lynx-terminal-command-tag . "Kommando för Lynx i Emacs:") (kom-lynx-terminal-tag . "Var ska Lynx köra:") (kom-lynx-xterm-command-tag . "Kommando för Lynx i xterm:") (kom-show-sync-messages-tag . "Visa databasen-sparar-meddelanden:") (kom-highlight-conferences-tag . "Färgläggning av namn:") (kom-netscape-variant-tag . "Var ska Netscape/Mozilla öppna URLer:") (kom-auto-confirm-new-conferences-tag . "Markera alltid nya möten och personer som kända:") (kom-text-properties-tag . "Använd typsnitt och färger:") (kom-fontify-text-tag . "Visa fetstil och kursiv text i inlägg:") ) ) ;;;; ============================================================ ;;;; The default Ansaphone message goes here. The more complex ;;;; message specification probably should too, but it's not here ;;;; yet. People who know how to use it are smart enough to do it ;;;; right. (lyskom-language-var local kom-ansaphone-default-reply sv "Jag läser inte LysKOM just nu. Skicka gärna ett brev i stället.") ;;;; ============================================================ ;;;; Other language-dependent variables ;;;; (lyskom-language-var local kom-ispell-dictionary sv "svenska") ;;;; ================================================================ ;;;; Tell phrases should really be configured with the default ;;;; language used at the server and not for person reading if they ;;;; happen to differ. This is of coarse because they are sent to the ;;;; server for everybody else to see. ;;;; Aronsson was here 4 DEC 1990, thus creating version 0.18 ; Created *-tell-* ;;;; kom-tell-phrases ;;; To coders of the elisp-client: ;;; if you change kom-tell-phrases here, make sure the list of valid ;;; keywords is updated it in vars.el. ;;; lyskom-tell-phrases-validation-keyword-list, lyskom-tell-phrases-validate (eval-when-compile (defvar kom-tell-phrases)) (lyskom-language-strings local kom-tell-phrases sv '((kom-tell-silence . "") ; Why ? (kom-tell-send . "Försöker lägga in en text.") (kom-tell-login . "Loggar in.") (kom-tell-read . "Läser.") (kom-tell-1st-pres . "Skriver den första presentationen.") (kom-tell-write-comment . "Skriver en kommentar.") (kom-tell-write-footnote . "Skriver en fotnot.") (kom-tell-write-letter . "Skriver ett brev.") (kom-tell-write-reply . "Skriver ett privat svar.") (kom-tell-write-text . "Skriver inlägg.") (kom-tell-conf-pres . "Skriver presentation för ett nytt möte.") (kom-tell-recover . "Återstartar kom. Suck.") (kom-tell-wait . "Väntar.") (kom-tell-regret . "Ångrar sig och slänger inlägget.") (kom-tell-review . "Återser.") (kom-tell-change-name . "Ändrar sitt namn till något annat.") (kom-tell-change-supervisor . "Ändrar organisatör för något.") (kom-tell-next-lyskom . "Hoppar till ett annat LysKOM."))) (if (and (boundp 'kom-tell-phrases) kom-tell-phrases) (lyskom-language-strings local kom-tell-phrases sv (mapcar (function (lambda (x) (cond ((and (consp x) (symbolp (car x)) (stringp (cdr x))) x) ((and (consp x) (symbolp (car x)) (consp (cdr x)) (stringp (car (cdr x)))) (cons (car x) (car (cdr x)))) (t nil)))) kom-tell-phrases))) ;; Placed here because this must NOT be evaluated before ;; kom-tell-phrases is defined: (lyskom-language-var local kom-mercial sv (lyskom-get-string 'kom-tell-wait 'kom-tell-phrases)) ;;; (lyskom-language-strings local lyskom-error-texts sv '((error-0 . "Inget fel har inträffat") (error-2 . "Ännu ej implementerat i servern") (error-3 . "Inte längre implementerat i servern") (error-4 . "Felaktigt lösenord") (error-5 . "Strängen för lång") (error-6 . "Du är inte inloggad") (error-7 . "Ingen får logga in i LysKOM just nu") (error-8 . "Du försökte använda möte nummer 0") (error-9 . "Odefinierat eller hemligt möte") (error-10 . "Odefinierad eller hemlig person") (error-11 . "Ingen skriv- eller läsrättighet") (error-12 . "Otillåten operation") (error-13 . "Du är inte medlem i mötet") (error-14 . "Inget sådant textnummer") (error-15 . "Du kan inte använda globalt textnummer 0") (error-16 . "Inget sådant lokalt textnummer") (error-17 . "Du kan inte använda lokalt textnummer 0") (error-18 . "Namnet för kort, för långt eller innehåller felaktiga tecken") (error-19 . "Index utanför gränserna") (error-20 . "Mötet existerar redan") (error-21 . "Personen existerar redan") (error-22 . "Hemligt, men ej lässkyddat") (error-23 . "Du får inte ändra person/mötesflaggan") (error-24 . "Fel i databasen. Attans otur.") (error-25 . "Otillåten mottagartyp eller kommentarslänk") (error-26 . "Otillåten infotyp. (Bug i klienten)") (error-27 . "Redan mottagare till denna text") (error-28 . "Redan kommentar till denna text") (error-29 . "Redan fotnot till denna text") (error-30 . "Inte mottagare till denna text") (error-31 . "Inte kommentar till denna text") (error-32 . "Inte fotnot till denna text") (error-33 . "För många mottagare") (error-34 . "För många kommentarer") (error-35 . "För många fotnoter") (error-36 . "För många markeringar") (error-37 . "Du är inte författare till texten") (error-38 . "Du kan inte koppla upp dig till servern") (error-39 . "Minnet slut") (error-40 . "Servern har ballat ur") (error-41 . "Klienten tror att servern säger att den inte förstår klienten") (error-42 . "Ingen sådan session finns") (error-43 . "Ogiltigt reguljärt uttryck") (error-44 . "Texten är inte markerad") (error-45 . "Tillfälligt fel. Försök senare") (error-46 . "Serven vägrade ta emot en array") (error-47 . "Mottagaren tar inte emot anonyma texter") (error-48 . "Otillåten tilläggsinformation") (error-49 . "Otillåten ändring av tilläggsinformation") (error-50 . "Okänt asynkront meddelande") (error-51 . "Internt fel i servern") (error-52 . "Funktionen avstängd i servern") (error-53 . "Mottagaren var kanske inte inloggad") (error-54 . "Otillåten typ på medlemskap") (error-55 . "Ogiltigt intervall") (error-56 . "Ogiltig kombination av intervall") (error-57 . "Odefinierad mätning") (error-58 . "Otillåten prioritet") (error-59 . "Otillåten viktning") (error-60 . "Viktning noll ej giltig") (error-61 . "Ogiltigt sanningsvärde") (error--1 . "Du är inte medlem i något mottagarmöte") )) (lyskom-language-var global lyskom-unread-mode-line sv (lyskom-make-lyskom-unread-mode-line)) (lyskom-language-var global lyskom-unread-title-format sv (lyskom-make-lyskom-unread-title-format)) (lyskom-language-var local lyskom-help-data sv lyskom-sv-help-data) (provide 'lyskom-language-sv) ;;; swedish-strings.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: english-strings.el,v 44.352 2005/01/12 19:32:05 qha Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: english-strings.el ;;;; ;;;; This file contains all strings in the LysKOM elisp client. ;;;; Language: English. ;;;; ================================================================ ;;;; ;;;; Translation from swedish-strings.el: David Byers ;;;; (require 'lyskom-vars "vars") (require 'lyskom-language "language") (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: english-strings.el,v 44.352 2005/01/12 19:32:05 qha Exp $")) ;;; ================================================================ ;;; The language definition (lyskom-define-language 'en 'iso-8859-1 "English" "Engelska") ;;; ================================================================ ;;; lyskom-edit-mode-map English version (defvar lyskom-en-edit-mode-map nil) (lyskom-language-keymap lyskom-edit-mode-map en lyskom-en-edit-mode-map) ;;; Set the keymap for lyskom-edit-mode (defvar lyskom-en-edit-prefix) (defvar lyskom-en-edit-review-prefix) (defvar lyskom-en-edit-insert-prefix) (defvar lyskom-en-edit-aux-prefix) (defvar lyskom-en-edit-add-prefix) (if lyskom-en-edit-mode-map nil (setq lyskom-en-edit-mode-map (make-sparse-keymap)) (define-prefix-command 'lyskom-en-edit-prefix) (define-prefix-command 'lyskom-en-edit-review-prefix) (define-prefix-command 'lyskom-en-edit-insert-prefix) (define-prefix-command 'lyskom-en-edit-aux-prefix) (define-prefix-command 'lyskom-en-edit-add-prefix) (define-key lyskom-en-edit-mode-map (kbd (lyskom-keys (lyskom-xemacs-or-gnu 'button2 'button2up))) 'kom-button-click-or-yank) (define-key lyskom-en-edit-mode-map (kbd (lyskom-keys (lyskom-xemacs-or-gnu 'button2up 'button2))) 'kom-mouse-null) (define-key lyskom-en-edit-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-en-edit-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-en-edit-mode-map (kbd "*") 'kom-button-press-or-self-insert-command) (define-key lyskom-en-edit-mode-map (kbd "=") 'kom-menu-button-press-or-self-insert-command) (define-key lyskom-en-edit-mode-map (kbd "TAB") 'kom-edit-next-button-or-self-insert) (define-key lyskom-en-edit-mode-map (kbd "M-TAB") 'kom-edit-prev-button) (define-key lyskom-en-edit-mode-map (kbd "") 'kom-edit-prev-button) (define-key lyskom-en-edit-mode-map (kbd "C-c") 'lyskom-en-edit-prefix) (define-key lyskom-en-edit-prefix (kbd "C-x") 'lyskom-en-edit-aux-prefix) (define-key lyskom-en-edit-prefix (kbd "C-r") 'lyskom-en-edit-review-prefix) (define-key lyskom-en-edit-prefix (kbd "C-i") 'lyskom-en-edit-insert-prefix) (define-key lyskom-en-edit-prefix (kbd "TAB") 'lyskom-en-edit-insert-prefix) (define-key lyskom-en-edit-prefix (kbd "C-a") 'lyskom-en-edit-add-prefix) (define-key lyskom-en-edit-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-edit-prefix (kbd "*") 'kom-button-press) (define-key lyskom-en-edit-prefix (kbd "=") 'kom-menu-button-press) (define-key lyskom-en-edit-prefix (kbd "C-y") 'kom-edit-insert-commented) (define-key lyskom-en-edit-prefix (kbd "C-b") 'kom-edit-insert-buglist) (define-key lyskom-en-edit-prefix (kbd "C-c") 'kom-edit-send) (define-key lyskom-en-edit-prefix (kbd "C-s") 'kom-edit-ispell-message) (define-key lyskom-en-edit-prefix (kbd "C-k") 'kom-edit-quit) (define-key lyskom-en-edit-review-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-edit-review-prefix (kbd "C-c") 'kom-edit-show-commented) (define-key lyskom-en-edit-insert-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-edit-insert-prefix (kbd "C-c") 'kom-edit-insert-commented) (define-key lyskom-en-edit-insert-prefix (kbd "C-y") 'kom-edit-insert-commented) (define-key lyskom-en-edit-insert-prefix (kbd "1") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "2") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "3") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "4") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "5") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "6") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "7") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "8") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "9") 'kom-edit-insert-digit-text) (define-key lyskom-en-edit-insert-prefix (kbd "SPC") 'kom-edit-insert-text) (define-key lyskom-en-edit-insert-prefix (kbd "C-l") 'kom-edit-insert-link) (define-key lyskom-en-edit-insert-prefix (kbd "C-i") 'kom-edit-insert-last-info-nodename) (define-key lyskom-en-edit-add-prefix (kbd "C-r") 'kom-edit-add-recipient) (define-key lyskom-en-edit-add-prefix (kbd "C-c") 'kom-edit-add-copy) (define-key lyskom-en-edit-add-prefix (kbd "") 'kom-edit-move-text) (define-key lyskom-en-edit-add-prefix (kbd "C-x") 'kom-edit-add-cross-reference) (define-key lyskom-en-edit-add-prefix (kbd "C-p") 'kom-edit-add-personal-comments) (define-key lyskom-en-edit-add-prefix (kbd "C-n") 'kom-edit-add-no-comments) (define-key lyskom-en-edit-add-prefix (kbd "C-r") 'kom-edit-add-read-confirm-request) (define-key lyskom-en-edit-add-prefix (kbd "?") 'lyskom-help)) (lyskom-language-missing-string lyskom-message cgdag en) (lyskom-language-missing-string lyskom-message sixjune en) (lyskom-language-missing-string lyskom-message holdnose en) (lyskom-language-missing-string lyskom-message 13dayxmas en) (lyskom-language-missing-string lyskom-message 20dayxmas en) (lyskom-language-missing-string lyskom-message kyndeldag en) (lyskom-language-missing-string lyskom-message skottdag en) (lyskom-language-missing-string lyskom-message intwomday en) (lyskom-language-missing-string lyskom-message mariebdag en) (lyskom-language-missing-string lyskom-message johannesddag en) (lyskom-language-missing-string lyskom-message fnday en) (lyskom-language-missing-string lyskom-message allhelgonadag en) (lyskom-language-missing-string lyskom-message varnlosdag en) (lyskom-language-missing-string lyskom-message luciaday en) (lyskom-language-ending-mismatch lyskom-message carbon-copy-prefix en sv) (lyskom-language-ending-mismatch lyskom-message blank-carbon-copy-prefix en sv) (lyskom-language-ending-mismatch lyskom-message newyeareve en sv) ;;; Formely known as lyskom-strings (lyskom-language-strings local lyskom-message en '( ; From vars.el: ; From komtypes.el: nil ; From clienttypes.el: nil ; From startup.el: (server-q . "LysKOM server? (%#1s) ") (try-connect . "LysKOM elisp client version %#1s.\nAttempting to connect to %#2s.\n") (too-old-server . "The server is too old for this version of the client.") (connection-done . "Connection established. Server version is %#1s.\n\n") (what-is-your-name . "What is your name? ") (password . "Your password? ") (wrong-password . "Incorrect password.\n") (wrong-password-help . " If you have forgotten your password you may be able to get a new one by e-mailing the site administrators at one of the addresses listed below:\n") (wrong-password-email . "* %#1t\n") (are-logged-in . "You have entered LysKOM. Please wait...\n") (you-have-motd . "\nYou have a notice on your mailbox:\n\n") (server-has-motd . "There is a notice on the server:\n") (lyskom-motd-was-garbed . "\nThe login message does not exist! The message that was supposed to be shown after login has disappeared. Please contact the LysKOM administrator.\n") (first-greeting . "%#1s This appears to be the first time you use LysKOM. Welcome! Please make sure you have spelled your name correctly. You should use your full name and organisation, eg. \"Joe Hacker, MIT\". If your name is spelled incorrectly, or you wish to change it, answer 'no' to the question below. At present the LysKOM server stores most of the information so that anybody can read it. Only passwords are encrypted. If you are uncertain about how to use LysKOM, you can retrieve a manual by anonymous ftp to ftp.lysator.liu.se. Ask your system administrator for help on how to do this. You can also type \"?\" for the command \"Help\". ") (is-name-correct . "Is the name %#1s correct? ") (personal-password . "Enter a personal password: ") (repeat-password . "Repeat for confirmation: ") (repeat-failure . "The passwords were not the same.\n") (could-not-create-you . "LysKOM couldn't create that user.\n") (presentation-subject . "%#1s") (presentation-form . "\ Name: Address: Telephone: E-mail: WWW: Other: ") (presentation-help . "You are writing your presentation.\n") (not-present-anywhere . "Not in any conference.") (unknown-person . "Unknown user") (in-secret-conference . "Secret conference (%#1d).") (start-new-session-same-server . "You are already connected to that server. Do you want a new session? ") (new-session-in-buffer . "\n\n---- New session at %s ----\n\n") (warning-about-uncompiled-client . " NOTE: The LysKOM client is not compiled. It is recommended to run a compiled client for performance reasons. Read the accompanying README to learn how to do that. ") ; From internal.el: (shaky-tcp . "At the moment I can't reach the server. The TCP/IP connection is shaky%#1s") (retrying-tcp . "Retrying.") ; From parse.el: (protocol-error . "protocol error: %s") ; From services.el: (interrupted . "Interrupted\n") ; From cache.el: ; No entries. ; From commands1.el: (appreciation . "You are a very special person, beautiful and wise, respected by everybody around you. You are doing a splendid job. Many people love you, body and soul. You make life easier for others. You are a very warm and sensitive person. Be proud of being You! You have a very good reason.\n\n") (abuse . "You are a nuisance, ugly and stupid, disrespected by everybody around you. You are doing a worthless job. Many people hate you, body and soul. You make life harder for others. You are a very cold and unfeeling person. Be ashamed of being You! You have a very good reason.\n\n") (what-conf-to-delete . "Conference/user to delete: ") (what-conf-to-change . "Conference to modify: ") (confirm-delete-pers-or-conf . "Really delete %#1s %#2s? ") (the-pers . "the user") (the-conf . "the conference") (deletion-not-confirmed . "Deletion aborted\n") (somebody-else-deleted-that-conf . "Somebody else just deleted the conference.\n") (conf-is-deleted . "OK, %#1s is now deleted.\n") (you-could-not-delete . "%#1M can't be deleted by you.\n") (you-have-deleted-yourself . "You have deleted yourself.\n") (what-text-to-delete . "Remove which text? ") (delete-marked-text . "The text is %#1s. Delete anyway? ") (delete-marked-by-you . "marked by you") (delete-marked-by-you-and-others . "marked by you and %#1?d%[someone else%]%[%#1d others%]") (delete-marked-by-several . "marked by %#1d user%#1?d%[%]%[s%]") (delete-commented-text-help . "\ The text you are about to remove has comments. If you remove it the comments will lose their context, and this annoys and even angers many readers. You should consider moving it to another conference instead of removing it.") (delete-commented-text . "The text has comments. Remove anyway? ") (really-delete-commented-text . "Removing a commented text may annoy many readers. Remove anyway?") (deleting-text . "Removing text %#1:n...") (presentation-for-whom . "View presentation for which conference/user? ") (text-to-see-author-of . "Review presentation of author of which text? ") (unread-presentation-for-whom . "Unread presentation for which conference/user? ") (text-to-unread-author-of . "Mark presentation of author of which text as unread? ") (somebody-deleted-that-conf . "Somebody just deleted that conference.\n") (review-presentation-of . "Review presentation of %#1M.\n") (has-no-presentation . "%#1:M has no presentation.\n") (have-to-read . "You must read a text first.\n") (no-comment-to . "There is no commented text.\n") (no-text-at-point . "There is no text at point.\n") (what-ancestor . "Which of the commented texts do you want? ") (who-letter-to . "Send a letter to whom? ") (who-send-text-to . "Send text to which conference? ") (has-motd . "%#1P has a notice on his/her mailbox:\n\n") (motd-persist-q . "Do you still want to write the text? ") (who-to-add . "Whom do you want to add? ") (where-to-add . "To which conference? ") (where-to-add-self . "Join which conference? ") (priority-q . "Priority of your membership? (0 (low) - 255 (high)) ") (other-priority-q . "Priority of the membership? (0 (low) - 255 (high)) ") (done . "done.\n") (cancelled . "cancelled.\n") (nope . "didn't work.\n") (add-already-member . "%#1P is already a member of %#2M.\n") (you-already-member . "You are already a member of %#1M.\n") (cant-find-supervisor . "Can't find supervisor of %#1M.\n") (is-read-protected-contact-supervisor . "%#1M is closed. Send a letter to %#2P to apply for membership.\n") (conf-does-not-exist . "\nThe conference doesn't exist.\n") (who-to-exclude . "Who do you want to remove? ") (where-from-exclude . "From which conference? ") (leave-what-conf . "Leave which conference? ") (error-fetching-person . "Error retrieving user.\n") (error-fetching-conf . "Error retrieving conference.\n") (name-of-conf . "Conference name? ") (anyone-member . "May anyone join? ") (secret-conf . "Secret conference? ") (comments-allowed . "Are comments allowed? ") (anonymous-allowed . "Are anonymous texts allowed? ") (secret-members-allowed . "Are secret members permitted? ") (what-comment-no . "Comment text number: ") (what-footnote-no . "Footnote text number: ") (what-private-no . "Private reply to text number: ") (quit-in-spite-of-unsent . "You have an unsent text. Do you really want to quit? ") (really-quit . "Do you really want to quit LysKOM? ") (session-ended . " -------------------------------------------- LysKOM session finished You are now disconnected from the server -------------------------------------------- ") (session-ended-long . " ------------------------------------------------------------------------------- LysKOM session finished You are now disconnected from the server ------------------------------------------------------------------------------- ") (session-auto-ended . " ============================================================ Disconnecting from LysKOM since all connections are in use and you have finished reading. Please come back later. ============================================================\n\n") (session-auto-ended-long . " =============================================================================== Disconnecting from LysKOM since all connections are in use and you have finished reading. Please come back later. =============================================================================== \n") (what-to-change-pres-you . "Change presentation of whom/what: ") (what-to-change-faq-you . "Change FAQ for which conference: ") (who-to-put-motd-for . "Post notice on whom/what: ") (what-to-set-pres-you . "Set presentation for whom/what: ") (what-text-to-set-as-pres-no . "Which text do you want as the new presentation: ") (what-to-set-motd-you . "Set notice on whom/what: ") (what-text-to-set-as-motd-no . "Which text do you want as the new notice: ") (conf-already-has-pres . "The conference/person already has a presentation. Continue anyway? ") (conf-already-has-motd . "The conference/person already has a notice. Continue anyway? ") (setting-conf-pres . "Setting presentation of %#1M to text %#2n...") (setting-conf-motd . "Setting notice for %#1M to text %#2n...") (who-to-remove-pres-for . "Remove presentation from whom: ") (removing-pres-for-conf . "Removing presentation (text %#2n) from %#1M...") (cant-get-conf-stat . "Cannot get the status of that conference.\n") (go-to-conf-p . "Go to conference: ") (want-become-member . "Do you want to join? ") (no-ok . "Okiedokie, whatever you say.\n") (who-to-remove-motd-for . "Remove notice from whom/what: ") (conf-all-read . "no unread texts") (no-in-conf . "You are not present in any conference.\n") (search-for-pers . "Enter search key (RETURN for all users): ") (search-for-conf . "Enter search key (RETURN for all conferences): ") (search-re . "Enter search regexp: ") (search-re-for-what . "What do you want to search for? ") (search-re-persons . "ppersons") (search-re-confs . "cconferences") (search-re-all . "bboth") (no-matching-confs . "No conferences match \"%#1s\".\n") (no-matching-perss . "No persons match \"%#1s\".\n") (no-matching-anys . "No persons or conferences match \"%#1s\".\n") (no-confs-exist . "There are no conferences in the database.\n") (no-pers-confs-exist . "There are no persons or conferences in the database.\n") (list-confs-created-by . "List owned conferences for: ") (listing-confs-created-by . "Listing owned conferences for %#1P\ C=Created, O=Supervisor, S=Letterbox is super conf; S=Secret, P=Protected\n") (list-pers-confs-created-by . "List owned conferences and persons for: ") (getting-all-confs . "Retrieving a list of all conferences from the server...") (getting-all-pers-confs . "Retrieving a list of all persons and conferences from the server...") (getting-all-confs-done . "Retrieving a list of all conferences from the server...done") (getting-all-pers-confs-done . "Retrieving a list of all persons and conferences from the server...done") (finding-created-confs . "Finding owned conferences (%#1d of %#2d done)") (finding-created-pers-confs . "Finding owned persons and conferences (%#1d of %#2d done)") (no-created-confs . "%#1P is not creator, supervisor or super conference for any conference.\n") (name-to-be-changed . "Name to change: ") (no-such-conf-or-pers . "The conference or user doesn't exist.\n") (new-name . "New name: ") (new-paren . "New parenthesis: ") (too-many-parens-in-name . "Multiple parentheses in name. Use \"Change name\" instead.\n") (no-paren-in-name . "The name doesn't contain a parenthesis.\n") (who-to-change-supervisor-for . "Change supervisor of whom/what? ") (new-supervisor . "New supervisor: ") (text-to-mark . "Mark which text? ") (text-to-unmark . "Unmark which text? ") (what-mark . "Set which mark type (name or 0-255)? ") (erroneous-mark . "Erroneous mark type.\n") (want-to-create-symbolic-mark . "The mark type \"%#1s\" does not exist. Do you want to create it? ") (creating-symbolic-mark-type . "Creating mark type \"%#1s\" (%#2d).\n") (no-mark-types-left . "Sorry, there are no free mark types. Remove an old one first.") (unmarking-textno . "Unmarking text %#1n...") (marking-textno . "Marking text %#1n with mark %#2?b%[\"%#2s\" (%#3d)%]%[%#3d%]...") (list-which-mark . "List texts with which mark type (name or 0-255, RET for all)? ") (new-passwd-again . "Repeat the new password for confirmation: ") (what-mark-to-unread . "Mark which mark type as unread (name or 0-255, RET for all)? ") (what-mark-to-view . "Review which mark type (name or 0-255, RET for all)? ") (whos-passwd . "Change password for whom? ") (old-passwd . "Your current password: ") (new-passwd . "The new password: ") (changing-passwd . "Changing password...") (retype-dont-match . "You didn't reenter the same passwrod. Try again.\n") (palindrome . " (a palindrome!)") (lyskom-name . "User") (is-in-conf . "In conference") (from-machine . "At") (is-doing . "Activity") (connection-time . "Connected") (active-last . "Active last") (active . "Active") (lyskom-client . "Client") (text-to-add-recipient . "Add recipient to which text:") (text-to-add-copy . "Add recipient of carbon copy to which text:") (text-to-add-bcc . "Add recipient of blind carbon copy to which text:") (text-to-delete-recipient . "Remove recipient from which text:") (text-to-move . "Which text do you want to move:") (text-tree-to-move . "Which text is the root of the tree you want to move:") (text-to-add-comment-to . "Add comment to which text:") (text-to-delete-comment-from . "Remove comment from which text:") (text-to-add-footnote-to . "Add footnote to which text:") (text-to-delete-footnote-from . "Remove footnote from which text:") (text-to-add-cross-reference-to . "Add cross reference to which text:") (text-has-no-recipients-r . "Text %#1n has no recipients\n") (cant-move-from-to-same . "Source and target conferences must be different.\n") (where-on-list-q . "Placement in your list? (0-%#1d) ") (accepting-invitation . "Accepting invitation to %#2M%#3?b%[ %#3s%]%[%]...") (member-in-conf . "Joining %#2M%#3?b%[ %#3s%]%[%]...") (member-in-conf-with-low-priority . "%#1M has lower priority than your session priority, and will not be shown.\n") (member-in-conf-with-unread-date . "with unread from %#2s %#3d, %#1d") (member-in-conf-with-unread . "unread %#1d unread") (add-member-in . "Adding %#1P as a member of %#2M...") (change-priority-for-q . "Change priority of conference: ") (cant-change-priority-of-passive . "Can't change priority of passive memberships.\n") (change-priority-for . "Changing priority of %#2M...") (unsubscribe-to . "Leaving %#1M...") (unsubscribe-to-2 . "Leaving %#1M%#2s...") (confirm-each-join . "Confirm joining individual conferences? ") (confirm-each-msg . "Confirm reception of group messages in individual möten? ") (receive-each-msg . "Do you want to receive group messages in all conferences? ") (no-confirm-each-sure . "Are you sure you want to join %#1d conferences automatically? ") (confirm-join . "Join %#1M? ") (getting-all-confs . "Getting a list of all conferences...") (getting-all-confs-progress . "Getting a list of all conferences (%#1d/%#2d)...") (getting-all-confs-done . "Getting a list of all conferences...done") (unsub-all-skipping-letterbox . "nix\nThis is your letterbox.\n") (unsub-all-skipping-supervised . "nix\nYou are the supervisor of the conference.\n") (unsub-secret-conf-q . "%#1M is secret. Leave anyway? ") (unsub-all-secret . "aLeave all secret conferences") (unsub-closed-conf-q . "%#1M är close. Leave anyway? ") (unsub-all-closed . "aLeave all closed conferences") (unsub-open-conf-q . "Leave %#1M? ") (unsub-all-open . "aLeave all open conferences") (abc-yes . "yYes") (abc-no . "nNo") (abc-yes-all . "aJa to all") (abc-no-all . "xNej to all") (move-tree-move . "mMove") (move-tree-sub . "rRemove") (move-tree-add . "aAdd") (move-tree-ign . "nNothing") (move-tree-jump . "jJump") (move-tree-quit . "qCancel") (move-tree-add-rcpt-type . "Add as: ") (move-tree-rcpt . "rRecipient") (move-tree-cc . "cCarbon copy") (move-tree-bcc . "dBlind carbon copy") (move-tree-leave-cc-q . "Leave original recipient as carbon copy recipient? ") (exclude-from . "Removing %#1P from %#2M...") (unsubscribe-failed . "\nDidn't work. Perhaps %#1P isn't a member of %#2M?\n") (activate-mship . "Become active member of %#1M...") (activate-mship-done . "Activated passive membership of %#1M.\n") (passivate-done . "You are now a passive member of %#1M. Leave the conference again to unsubscribe completely.\n") (You . "You") (could-not-create-conf . "Couldn't create the conference \"%#1s\".\n") (created-conf-no-name . "Conference number %[%#3@%#1:m %#2:M%] has been created.\n") (cant-read-textno . "You are not allowed to read text %#1:n.\n") (not-supervisor-for . "You are not the supervisor of %#1M.\n") (not-supervisor-for-server . "You do not have administrative rights on this LysKOM-server.\n") (go-to-conf . "Go to conference %#1M.\n") (cant-go-to-his-mailbox . "You are not allowed to go to %#1M's mailbox.\n") (not-member-of-conf . "You are not a member of %#1M.\n") (about-to-change-name-from . "%#1M\n") (change-name-done . "Done. New name: %[%#2@%#1:M%].\n") (change-name-nope . "Couldn't change name to %#1s. Error code %#3d. %#2s.\n") (change-supervisor-from-to . "Change supervisor of %#1M to %#2P...") (change-supervisor-nope . "\nDidn't work. Perhaps you are not allowed to change the supervisor of %#1M?\n") (no-marked-texts . "You have not marked any texts.\n") (no-marked-texts-mark . "You have not marked any texts with mark type \"%#1s\".\n") (weekdays . ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"]) (weekdays-short . ["Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"]) (time-is . "The time is %#1s%#2s (according to the server).") (time-is-week . "The time is %#1s%#2s, week %#3d (according to the server).") (xmaseve . "Christmas eve!\nYou didn't open any gifts early, did you?") (xmasday . "Christmas day.\nDid you get any nice gifts this year?") (newyearday . "\nMay %#1d be a prosperous and good year for you!") (newyeareve . "Happy New Year!") (newyearevelate . "Less than an hour left of %#1d...") (lysbday . " On this day, in 1973, the Lysator Academic Computer Society was formed, and it was a great day in the history of computing in Sweden. Read all about it at http://www.lysator.liu.se/history/") (total-users . " A total of %#1d users (%#2s).\n") (total-users-sans-date . " A total of %#1d users\n") (total-visible-users . " A total of %#1d visible user%#1?d%[%]%[s%] (%#2s).\n") (total-active-users . " A total of %#1d active user%#1?d%[%]%[s%] (%#2s).\n") (total-visible-active-users . " A total of %#1d visible%#1?d%[%]%[%] active user%#1?d%[%]%[s%] (%#2s).\n") (client-statistics . " Distribution of clients:\n") (client-statistics-line . " %4#2d %#1s%#3?d%[%]%[ [%#3d variants]%]") (who-to-add-q . "Add whom/what as a recipient? ") (who-to-add-copy-q . "Add which conference/user as carbon copy recipient? ") (who-to-add-bcc-q . "Add which conference/user as blind carbon copy recipient? ") (add-footnotes-too-q . "Try to add recipient to footnotes? ") (add-attachments-too-q . "Try to add recipient to attachments? ") (really-add-as-recpt-q . "Send future comments to the text to %#1M too? ") (who-to-sub-q . "Remove whom/what as a recipient? ") (sub-footnotes-too-q . "Try to remove recipient from footnotes? ") (sub-attachments-too-q . "Try to remove recipient from attachments? ") (who-to-move-from-q . "Move from where? ") (who-to-move-to-q . "Move to where? ") (who-to-move-to-or-sub-q . "Move to where (empty to just remove recipient)? ") (move-footnotes-too-q . "Try to move footnotes? ") (move-attachments-too-q . "Try to move attachments? ") (move-text-not-recipient . "incorrect recipient.\n") (adding-name-as-recipient . "Adding %#1M as recipient of text %#2n...") (adding-name-as-copy . "%#1M will receive a carbon copy of text %#2n...") (adding-name-as-bcc . "%#1M will receive a blind carbon copy of text %#2n...") (remove-name-as-recipient . "Removing %#1M as recipient of text %#2n...") (adding-cross-reference . "Adding cross reference...") (error-recipient-limit . "Text %#1n has too many recipients.\n") (error-already-recipient . "%#2M is already a recipient of text %#1n.\n") (error-permission-denied-add-recpt . "Only the author of %#1n or supervisor for %#2M can change recipient types.\n") (error-permission-denied-sub-recpt . "Only the author of %#1n or supervisor for %#2M can remove the recipient.\n") (error-access-denied-add-recpt . "You are not allowed to add texts to %#2M.\n") (error-not-recipient . "%#2M is not a recipient of text %#1n.\n") (moving-tree-what-action-q . "What do you want to do? ") (moving-cant-read . "Can't move text %#1n (unable to read text).\n") (moving-name . "Moving text %#3n from %#1M to %#2M...") (moving-already-moved . "Text %#1n does not have %#2M as a recipient.\nSkipping this text and its comments.\n") (text-to-add-q . "Add which text as a comment to %#1n? ") (text-to-remove-q . "Remove which text as a comment from %#1n? ") (text-to-add-footn-q . "Add which text as a footnote to %#1n? ") (text-to-remove-footn-q . "Remove which text as a footnote from %#1n? ") (add-comment-to . "Adding text %#1n as a comment to text %#2n...") (sub-comment-to . "Removing text %#1n as a comment to text %#2n...") (add-footnote-to . "Adding text %#1n as a footnote to text %#2n...") (sub-footnote-to . "Removing text %#1n as a footnote to text %#2n...") (comment-keep-recpt-p ."Should %#1s remain a recipient? ") (comment-all-relevant-p . "There are multiple recipients. Are they all relevant? ") (please-edit-recipients . "Modify the recipient list and send the text again.") (add-recipient-p . "Add recipient%#2?b%[ %#2M to reach%]%[%] %#1P? ") (checking-rcpt . "Checking recipients...") (checking-rcpt-done . "Checking recipients...done") (checking-comments . "Checking commented texts...") (checking-comments-done . "Checking commented texts...done") (please-check-commented-texts . "Review the commented text and its comments.") (have-unread-comment . "Send despite unread comments to text %#1n? ") (duplicate-recipients . "Unable to post. A recipient is duplicated (%#1M)") (no-recipients . "Unable to post text. No recipients were specified.") (matching-regexp . "Conferences/users matching `%#1s'\n") (matching-regexp-perss . "Users matching `%#1s'\n") (matching-regexp-confs . "Conferences matching `%#1s'\n") (who-is-active-all . "Showing all sessions.\n") (who-is-active-last-minutes . "Showing all sessions active the last %#1d minutes.\n") (showing-invisibles . "Showing invisible sessions.\n") (null-who-info . "No one (active) is logged on.\n") (no-other-lyskom-r . "There are no other active LysKOM sessions.\n") (no-lyskom-session . "There are no active LysKOM sessions.") (no-other-unread-lyskom-r . "There is no another LysKOM session with unread texts.\n") (no-unread-lyskom-r . "There is no active LysKOM session with unread texts.\n") (no-unread-lyskom . "There is no active LysKOM session with unread texts.") (who-is-on-in-what-conference . "Who in which conference: ") (who-is-present-in-what-conference . "Who present in which conference: ") (who-is-friend . "Only friends are shown.\n") (who-is-active-and-member . "Only members in %#1M are shown.\n") (who-is-active-and-present . "Only members present in %#1M are shown.\n") (personal-comment-to-anonymous . "It is not possible to write a personal comment to an anonymous text.\n") ;; Used for kom-is-person-member-of-conference: (pers-to-check-mship-for . "Whose membership do you want to check? ") ;-) (conf-to-check-mship-of . "...for which conference? ") (conf-is-empty . "The conference %#1M is empty.\n") (pers-is-member-of-conf . "Yes, %#1P is a member of the conference %#2M.\n") (pers-is-passive-member-of-conf . "Well, %#1P is only a passive member of the conference %#2M.\n") (pers-is-not-member-of-conf . "No, %#1P is not a member of the conference %#2M.\n") (pers-is-member-of-conf-2 . "Number of unread: %#2D (last access %#1s)\n") (pers-will-receive-async . "Reception of group messages %#1?b%[enabled%]%[disabled%]\n") (pers-mship-priority . "Membership priority: %#1d\n") (Unknown-number . "Unknown number") (text-to-check-will-read-for . "...for membership in recipients of text: ") (pers-to-check-will-read-for . "Person to check: ") (pers-is-member-of-rcpt . "Yes, %#1P is a member of at least one recipient to text %#2n.\n") (pers-is-passive-member-of-rcpt . "Well, %#1P is only a passive member of at least one recipient of %#2n.\n") (pers-is-not-member-of-rcpt . "No, %#1P is not a member of any recipient of %#2n.\n") ; From commands2.el: (your-memberships . "Your LysKOM conference memberships:\n") (memberships-header . "Last access Prio Unread Conference\n") (memberships-line . "%16#1s %#2d\t%#3d\t%#4M\n") (conf-for-status . "Get status of which conference? ") (no-such-conf . "The conference doesn't exist.\n") (status-record . "Status of conference %#1M (%#1m)%#2s\n\n") (change-type-prompt . "Change conference type for %#1M (%#1m) (%#2s)...") (Mailbox . "Mailbox") (Protected . "Protected") (no-comments . "No comments") (closed . "Closed") (allow-anon . "anonymomus ok") (allow-secret . "secret members") (created-by . "Created by person %24#1p %#3s(%#2P)\n") (created-at . "Created:%34#1s\n") (members . "Number of members: %19#1d\n") (conf-allows-secret-members . "Secret members: %#1s\n") (conf-allows-anon-texts . "Anonymous texts: %#1s\n") (anon-texts-permitted . "Anonymous texts are permitted") (anon-texts-not-permitted . "Anonymous texts are not permitted") (secret-members-permitted . "Secret members are permitted") (secret-members-not-permitted . "Secret members are not permitted") (garb-nice . "Expiration time: %16#1d day%#1?d%[%]%[s%]\n") (keep-commented . "Min. expiration time for commented texts: %#1d day%#1?d%[%]%[s%]\n") (lowest-local-no . "Lowest local number: %21#1d\n") (highest-local-no . "Highest local number: %20#1d\n") (last-text-time . "Time of last text: %20#1s (according to your cache)\n") (no-of-motd . "Notice in text: %13#1n\n") (pers-has-privileges . "Privileges: %#1s\n") (pers-has-privileges-2 . "%28#1s") (superconf-is-no-name . "Superconference: %25#1m %#3s(%#2M)\n") (permitted-submitters-no-name . "Allowed authors: %25#1m %#3s(%#2M)\n") (supervisor-is-no-name . "Supervisor: %30#1p %#3s(%#2P)\n") (presentation-no . "Presentation: %25#1n\n") (conf-has-motd . "\n%#1M has a notice on his/her mailbox:\n") (conf-mship-priority . "Prioritet: %25#1n%#2?b%[ %#2s%]%[%]\n") (status-conf-generic . "%-40#1s %#2s\n") (status-aux-item . "Unknown property: %11#1s%#3s (created by %#2M)\n") (conf-mx-list-name . "Imported mailing list: %#1s %#2s\n") (conf-mx-refuse-import . "Refuse import of: %#1s %#2s\n") (recommended-conf-aux . "Recommended conference: %#1M <%#1m> %#2s\n") (bad-recommended-conf-aux . "Recommended conference: \"%<20...#1s\" %[%#2@[invalid]%] %#3s\n") (status-read-faq-aux-item . "Read FAQ: %15#2n for %#1?z%[%#1M <%#1m>%]%[the server%] %#3s\n") (bad-status-read-faq-aux-item . "Read FAQ: \"%<20...#1s\" %[%#2@[invalid]%] %#3s\n") (status-rejected-recommendation-aux-item . "Rejected recommendation for: %#1M %#2s\n") (bad-status-rejected-recommendation-aux-item . "Rejected recommendation for: \"%<20...#1s\" %[%#2@[invalid]%] %#3s\n") (status-send-comments-to . "Redirect comments to: %#1M <%#1m> %#2s\n") (bad-status-send-comments-to . "Redirect comments to: \"%<20...#1s\" %[%#2@[invalid]%] %#3s\n") (Everybody . "Everyone") (show-members-list-also-q . "List members? ") (show-membership-info-q . "Show membership info number of unreads? ") (conf-has-these-members . "\n%#1M has the following members:\n") (conf-has-no-members . "\n%#1M has no members.\n") (member-list-header . "\nLast entered Unread Name\n") (secret-membership . "--- Secret line ---\n") (conf-membership-line . "%#4@%#1s%#2M %#3s\n") (conf-membership-line-2 . " Added %#1s by %#2P\n") (pers-for-status . "Get status of which user? ") (text-to-see-author-status-of . "Get status of the author of which text? ") (no-such-pers . "The user doesn't exist.\n") (pers-status-record . "Status of user %#1P (%#1p)\n") (created-time . "Created:%34#1s\n\n") (created-confs . "Conferences created:%22#1d\n") (created-persons . "Users created:%28#1d\n") (created-texts . "Texts created:%28#1d\n") (created-lines . "Lines created:%28#1d\n") (created-chars . "Characters created:%23#1d\n") (no-of-sessions . "Session count:%28#1d\n") (present-time-d-h-m-s . "Total presence:%16#1d d %02#2d:%02#3d:%02#4d\n") (last-log-in . "Last login or logout:%21#1s\n") (user-name . "User: %36#1s\n") (read-texts . "Texts read:%31#1d\n") (marked-texts . "Texts marked:%29#1d\n") (time-for-last-letter . "Time of last letter:%22#1s (according to your cache)\n") (superconf . "Superconference: %25#1m %#3s(%#2M)\n") (supervisor . "Supervisor: %30#1p %#3s(%#2P)\n") (member-of-confs . "Member of (conferences):%18#1d\n") (presentation . "Presentation: %25#1n\n") (show-membership-list-also-q . "List memberships? ") (not-allowed-see-confs . "%#1P is not a member of any conferences.\n") (is-member-of . "\n%#1P is a member of the following conferences:\n") (membership-list-header . "\nLast access Unread Conference\n") (pers-membership-line . "%#5@%#1s%#2s%#3M %#4s\n") (pers-membership-line-2 . " Added %#1s by %#2P\n") (is-supervisor-mark . "O ") (who-to-send-message-to . "Send message to whom? (%#1s) ") (send-empty-message-p . "The message is empty. Send it anyway? ") (his-total-unread . "\n%#1M has %#2d unread texts (plus %#3d in passive memberships).\n") (message-prompt . "Message%#1?z%[%]%[ (till alla inloggade)%]: ") (message-sent-to-user . "\ %[%#3$================================================================ %]%[%#4$Your message for %#2M: %#1t %]%[%#3$---------------------------------------------------------------- %]") (message-sent-to-all . "\ %[%#3$================================================================ %]%[%#4$Your public message %#1t %]%[%#3$---------------------------------------------------------------- %]") (message-sent-to-user-long . "\ %[%#3$\ =============================================================================== %]%[%#4$Your message for %#2M: %#1t %]%[%#3$\ ------------------------------------------------------------------------------- %]") (message-sent-to-all-long . "\ %[%#3$\ =============================================================================== %]%[%#4$Your public message %#1t %]%[%#3$\ ------------------------------------------------------------------------------- %]") (message-use-alarm-instead . "Use %#1s to send alarm messages.\n") (message-all-info . "\ %#1@Send alarm message to all users. %[%#3FConsider using \"%#2C\" to send your message to a specific conference or user.%] ") (message-recipient-info . "Send message to %#1M\n") (message-nope . "Unable to send message. %#3s\ The message you were sending to %#1M was: %#2t\n") (only-last . "Last texts in %#1s: ") (initial-unread . "Initial number of unread (empty for all texts): ") (only-error . "Something went wrong. Sorry.\n") (lp--only-last . "Number of text to read: ") (session-list-unreads-in-confs . "You have %#2?z%[%#2d unread letter%#2?d%[%]%[s%], in total %]%[%]%#3d unread text%#3?d%[%]%[s%] in %#4d conference%#4?d%[%]%[s%] in %#1s.\n") (session-list-no-unread-in . "You have no unread texts in %#1s.\n") (you-have-unreads . "You have %#1d unread text%#1?d%[%]%[s%] in %#2M\n") (you-have-unreads-special . "You have %#1d uncommented text%#1?d%[%]%[s%] in %#2M\n") (you-have-no-unreads . "You have read everything in %#1M\n") (you-have-read-everything . "No news (is bad news).\n") (no-unreads-shown . "Found no conferences meeting that criterion.\n") (total-unreads . "You have %#1d unread text%#1?d%[%]%[s%] texts in %#2d conference%#2?d%[%]%[s%].\n") (shown-unreads . "Showed %#1d unread text%#1?d%[%]%[s%] in %#2d conference%#2?d%[%]%[s%].\n") (list-unread-with-n-unread . "Listing conferences with at least %#1d unread.\n") (list-unread-with-at-most-n-unread . "Listing conferences with at most %#1d unread.\n") (waiting-for-anything . "You are waiting for a text in any conference.\n") (waiting-higher-than . "You are waiting for a text in any conference with a priority higher than %#1d.\n") (have-to-be-in-conf-with-unread . "You must go to a non-empty conference first.\n") (Texts . "Text") (Written . "Written") (Lines . "Lines") (Author . "Author") (Subject . "Subject") (Comments . "Co") (Num-marks . "Mk") (mark-type . "Type") (mark-no . "Mrk") (could-not-read . "You couldn't read the text (%#1n).\n") (multiple-choice . "There are several alternatives.") (does-not-exist . "Unknown command.") ; Only people fixing bugs or receiving bug reports should change these: (summary-line . "%=-8#1n%#2s%4#3d %[%#4@%#5:P%] %[%#6@%#7r%]\n") (diff-what-text-old . "Old text to compare: ") (diff-what-text-new . "New text to compare: ") ; Only people fixing bugs or receiving bug reports should change these: (buggreport-compilestart . "Creating bug report...") (buggreport-compileend . "Creating bug report...done") (buggreport-description . "This is what I was doing: \(Fill in your comments below\)\n================\n\n ================ In the information below are the 100 most recently pressed keys from your emacs. If you recently logged on, you password may be contained in this list. If that is the case, change the characters corresponding to your password to asterisks. When you have finished writing this, send your bug report to the LysKOM developers. You can do this either by email to bug-lyskom@lysator.liu.se or by mailing a hardcopy of your bug report to: Lysator, c/0 ISY, Linkoping Univerity, S-581 83 Linkoping, SWEDEN. Mark the envelope with \"LysKOM bug report\"\n\n") (buggreport-internals . "LysKOM's internal information:\n\n") (buggreport-version . "lyskom-version:") (buggreport-emacs-version . "emacs-version:") (buggreport-system-id . "system-id:") (buggreport-ctl-arrow-doc . "ctrl-doc:") (buggreport-unparsed . "\nlyskom-unparsed-buffer:") (buggreport-command-keys . "Recently pressed keys:") (buggreport-backtrace . "\n*Backtrace*:\n%#1s\n") (buggreport-communications . "\nlyskom-debug-communications-to-buffer-buffer:") (buggreport-all-kom-variables . "\n\nOther variables:\n***** *********") (buggreport-instead-of-byte-comp . "byte-code(\"byte-string\"") (buggreport-subject . "Bugreport elisp-client version %#1s") (not-logged-in . "You are not logged on. ") (name-is-not-in-conf . "%#1s is not in any conference.\n") (name-is-in-conf . "%#1s is in\n%#2s\n") (connected-during . "Connect time: %#1d seconds.\n") (conf-to-set-permitted-submitters-q . "For which conference do you want to set the allowed authors? ") (conf-to-set-super-conf-q . "Set superconference of which conference? ") (new-super-conf-q . "Which conference do you want as superconference? ") (new-permitted-submitters-q . "Allow members of which conference as authors in %#1s? (all) ") (super-conf-for-is . "Changing superconference of %#1M to %#2M...") (permitted-submitters-removed-for-conf . "Allowing all authors to conference %#1M...") (submitters-conf-for-is . "Changing authors admitted to conference %#1M to the members of %#2M...") (conf-to-set-garb-nice-q . "Set expiration time for which conference? ") (new-keep-commented-q . "How many days shall new comments protect texts from removal? ") (new-garb-nice-q . "After how many days shall texts be removed? ") (garb-nice-for-is . "Changing expiration for %#1M to %#2d day%#2?d%[%]%[s%]...") (keep-commented-for-is . "Changing minimum expiration for commented texts in %#1M to %#2d day%#2?d%[%]%[s%]...") (really-shutdown . "Are you sure you want to shut down the server? ") (closing-server . "Shutting down the server...") (really-sync . "Are you sure you want to save the database? ") (syncing-server . "Saving the database...") (administrator . "administrator") (no-longer-administrator . "a regular user again") (you-are-now . "Ok, you are now running as %#1s.\n") (setting-motd . "Changing login message to text %#1n.\n") (set-motd-success . "You have set a new login message.\n") (set-motd-failed . "Didn't work. Perhaps you were not an administrator.\n") (removing-motd . "Removing the login message.\n") (removed-motd . "You have removed the login message.\n") (who-to-throw-out . "Whose session do you want to kill? ") (throwing-out . "Killing session %#1d... ") (postpone-prompt . "How much do you want to read now? ") (set-session-priority . "Set reading level: ") ; From review.el: (no-unread-done . "You need to unread something before you can unread more.\n") (no-review-done . "You need to review something before you can review more.\n") (not-reviewing . "You are currently not reviewing anything.\n") (unread-how-many . "Unread how many?") (unread-how-many-more . "Unread how many more?") (review-how-many . "Review how many?") (review-how-many-more . "Review how many more?") (latest-n . "last %#1d") (first-n . "first %#1d") (review-by-whom . "Review %#1s by whom: ") (review-to-conf . "Review %#1s to conference: ") (unread-by-whom . "Unread %#1s by whom: ") (unread-to-conf . "Unread %#1s to conference: ") (all-confs . "all conferences") (unread-info-by-to . "Unread %#1s by %#2P to %#3M.\n") (unread-more-info-by-to . "Unread %#1s by %#2P to %#3M.\n") (unread-rest . "the rest") (unread-more . "%#1d more") (review-info-by-to . "Review %#1s by %#2P to %#3M forwards.\n") (review-more-info-by-to . "Review %#1s by %#2P to %#3M forwards.\n") (review-rest . "the rest") (review-more . "%#1d more") (you-review . "You are now reviewing %#1s.\n") (read-text-first . "You must read a text first.\n") (cannot-read-last-text . "You cannot review the last read text.\n") (review-n-texts . "Review %#1d texts.\n") (review-marked . "Review %#1d marked texts.\n") (review-text-no . "Review text %#1n\n") (review-many-comments . "Review %#2?d%[one%]%[%#2d%] comment%#2?d%[%]%[s%] to text %#1n.\n") (view-many-comments . "Read %#2?d%[one%]%[%#2d%] comment%#2?d%[%]%[s%] to %#1n.\n") (view-texts-in-conf . "Grand total of %#1d texts to read in %#2M.\n") (not-reading-anywhere . "You are not reading in any conference.\n") (read-normally-read . "How many texts to you want to read again? ") (review-conf-gone . "The conference does not exist.\n") (review-pers-gone . "The user does not exist.\n") (review-cant-read-conf . "You can't review texts to a closed conference you are not a member of.\n") (review-cant-read-letterbox . "You can't review texts to somebody else's mailbox.\n") (review-cant-read-empty . "The conference is empty.\n") (cant-review-everything . "You cannot review every text in LysKOM.\n") (cant-unread-everything . "You cannot unread every text in LysKOM.\n") (more-than-one-root . "Text %#1n has more than one root.\n") (more-than-one-root-review . "\ Text %#1n has more than one root but only one of the trees will be shown.\n") ; From edit-text.el: (press-C-c-C-c . "Enter C-c C-c to post the text.") (recipient . "Recipient") (carbon-copy . "Carbon copy") (blank-carbon-copy . "Blind Carbon copy") (recipient-prefix . "\\([Rr]\\)") (carbon-copy-prefix . "[Cc]\\([Aa]\\|[Cc]\\)") (blank-carbon-copy-prefix . "[Bb]\\([Ll]\\|[Cc][Cc]\\)") (add-recipient . "Add a recipient") (add-recipient-or-xref . "Add...") (secret-aux-flag . "secret") (anonymous-aux-flag . "anonymous") (inherit-aux-flag . "inherited") (aux-item-prefix . "[*]") (aux-item-prefix-regexp . "\\[\\*\\]\\s-*") (comment-item-prefix . "#\\s-*") (text-no-comment . "%#1d %#2s /%#3d line%#3?d%[%]%[s%]/ %#4P %#5?b%[ [anonymous]%]%[%]\n") (cant-fcc-text-file-error . "Unable to save text %#1n to \"%#2s\" (%#3s: %#4s).\n") (cant-fcc-text . "Unable to save text %#1n to \"%#2s\" (%#3s).\n") (header-subject . "Subject: ") (header-separator . "\\\ --- Write below. \ Post: \\[kom-edit-send], \ Kill: \\[kom-edit-quit], \ Help: \\[describe-mode] ---") (text-mass . "%#4s%#1s%[%#6@\n%]%[%#5@%#2s%]%[%#7@\n%]%#3s") (comment-to-by . "%#1s to text %#2n%#3s.\n") (already-sent . "You have already posted this text. Post it anyway? ") (subject . "Subject: ") (subject-prefix . "[Ss]") (enter-subject-idi . "Enter a subject.") (which-text-include . "Include which text? ") (added-recipient . "Recipient: ") (added-carbon-copy . "Carbon copy to conference: ") (added-blank-carbon-copy . "Blind carbon copy to conference: ") (text-to-comment-q . "Which text do you want to comment? ") (conf-has-motd-no . "The conference has a notice. (%#1d)\n\n%#2s") (still-want-to-add . "Do you still want to add the conference as a recipient? ") (could-not-create-text . "\nCouldn't create the text. Error: %#2s.\n") (no-get-text . "You were not allowed to retrieve the text.") (unknown-header . "Unknown header") (transform-error . "Send unformatted (%#1s)? ") (cant-find-info-node . "Can't find the info buffer") (link-type . "What to you want to link to? ") (which-text-to-link . "Add link to text: ") (which-text-to-link-err . "Text not found. Add link to text: ") (which-pers-to-link . "Add link to user: ") (which-conf-to-link . "Add link to conference: ") ; From view-text.el: (view-text-first-line . "%#7$%#2@%#1n %#3s /%#4d line%#4?d%[%]%[s%]/ %#5P%#6?b%[%#6s%]%[%]\n") (marked-by-you . "Marked by you (type: %#1s).\n") (marked-by-you-and-others . "Marked by you (type: %#2s) and %#1?d%[someone else%]%[%#1d others%].\n") (marked-by-several . "Marked by %#1d user%#1?d%[%]%[s%].\n") (timeformat-day-yyyy-mm-dd-hh-mm-ss . "%#7s %4#1d-%02#2d-%02#3d %02#4d:%02#5d:%02#6d") (timeformat-yyyy-mm-dd-hh-mm-ss . "%4#1d-%02#2d-%02#3d %02#4d:%02#5d:%02#6d") (timeformat-yyyy-mm-dd-hh-mm . "%4#1d-%02#2d-%02#3d %02#4d:%02#5d") (timeformat-yyyy-mm-dd . "%4#1d-%02#2d-%02#3d") (timeformat-hh-mm-ss . "%02#4d:%02#5d:%02#6d") (timeformat-hh-mm . "%02#4d:%02#5d") (format-time-date-and-time . "%#1s %#2s") (format-time-just-date . "%#1s") (format-time-just-time . "%#2s") (today . "today") (yesterday . "yesterday") (no-such-text-no . "The text doesn't exist. (%#1:n)\n") (text-created-at . "Created: %#1s\n") (text-imported-at . "Imported: %#1s\n") (text-imported-at-by . "Imported: %#1s by %#2P\n") (head-Subject . "Subject: ") (Recipient . "Recipient") (Extra-recipient . "CC") (Hidden-recipient . "BCC") (mx-Recipient . "External recipient") (mx-Extra-recipient . "External CC") (mx-Extern-reply-to . "External replies to") (Strange-recipient . "Also to") (send-at . " Posted: %#1s\n") (sent-by . " Posted by %#1P\n") (received-at . " Received: %#1s\n") (comment-to-text . "Comment to text %#1n") (footnote-to-text . "Footnote to text %#1n") (comment-in-text . "Comment in text %#1n") (footnote-in-text . "Footnote in text %#1n") (attachment-to-text . "Attachment %#3sto text %#1n") (attachment-in-text . "Attachment %#3sin text %#1n") (envelope-sender . "Sent by: %#1s\n") (attachment-filename . "Attachment file name: \"%#1s\"\n") (message-id . "Message-ID: %#1s\n") (comment-to-text-by . "Comment to text %#1n by %#2P") (footnote-to-text-by . "Footnote to text %#1n by %#2P") (comment-in-text-by . "Footnote in text %#1n by %#2P") (footnote-in-text-by . "Footnote in text %#1n by %#2P") (written-by . " by %#1P\n") ; From async.el: (name-has-changed-to-name . "%#1:P has changed name to %#2:P") (name-has-changed-to-name-r . "%[%#3@%#1:P%] has changed name to %[%#3@%#2:P%]\n") (you-changed-name-to . "You have now changed your name to %[%#2@%#1:P%].\n") (database-sync . "Synching database.") (lyskom-is-full . "\ =========================================================== Message from the LysKOM system: Somebody tried to connect, but failed since all connections available to LysKOM are in use. Please leave and return later if you are just waiting for a text. ===========================================================\n") (lyskom-is-full-long . "\ =============================================================================== Message from the LysKOM system: Somebody tried to connect, but failed since all connections available to LysKOM are in use. Please leave and return later if you are just waiting for a text. =============================================================================== ") (has-entered . "%#1:P has entered %#2s.") (has-entered-r . "%#2@%#1P has entered %#3s.\n") (has-left . "%#1:P has left %#2s.") (has-left-r . "%#2@%#1P has left %#3s.\n") (Unknown . "Unknown") (unknown . "unknown") (Unknown2 . "Unknown") (no-longer-member . "You are no longer a member of %#1M.\n") (no-longer-member-n . "You are no longer a member of %#1m (conference is gone).\n") (have-become-member . "You have become a member of %#1M.\n") (have-become-invited-member . "You have been invited to %#1M. Go to the conference to accept or decline the invitation. You can also use the command 'Join conference' to accept the invitation.\n") (have-become-passive-member . "You have become a passive member of %#1M.\n") (message-broadcast . "\ %[%#4$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$\ Alarm from %#1P (%#3s): %#2t %]%[%#4$\ ---------------------------------------------------------------- %]") (message-broadcast-long . "\ %[%#4$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$Alarm from %#1P (%#3s): %#2t %]%[%#4$\ ------------------------------------------------------------------------------- %]") (message-from . "\ %[%#4$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$Personal message from %#1P (%#3s): %#2t %]%[%#4$\ ---------------------------------------------------------------- %]") (message-from-long . "\ %[%#4$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#5$Personal message from %#1P (%#3s): %#2t %]%[%#4$\ ------------------------------------------------------------------------------- %]") (message-from-to ."\ %[%#5$\ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#6$Group message to %#3M\nfrom %#2P (%#4s): %#1t %]%[%#5$\ ---------------------------------------------------------------- %]") (message-from-to-long ."\ %[%#5$\ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %]%[%#6$Group message to %#3M\nfrom %#2P (%#4s): %#1t %]%[%#5$\ ------------------------------------------------------------------------------- %]") (text-is-created . "Text %#1n has been created!") ; Used in mode-line-process (mode-line-waiting . ": waiting") (mode-line-working . ": working") (mode-line-saving . ": saving") (mode-line-down . ": down") ; From completing-read.el: (person-or-conf-no-regexp . "\\`[ \t]*[mpMP]\\w*[ \t]+\\([0-9]+\\)\\'") (session-no-regexp . "\\`[ \t]*[sS]\\w*[ \t]+\\([0-9]+\\)\\'") (conf-prompt . "Which conference/person? ") ; From flags.el: (saving-settings . "Saving options...") (saving-settings-done . "Saving options...done") (save-options-failed-internal . "\ Failed to save options because of an internal error. Global options: %#1?b%[Encoding failed%]%[OK%] Elisp client options: %#2?b%[Encoding failed%]%[OK%] Other client options: %#3?b%[Encoding failed%]%[OK%] Rapportera gärna detta fel till elispklientens utvecklare. ") (hang-on . "Wait a moment...\n") (no-changes . "Nothing was saved since no options had been changed.\n") (could-not-save-options . "Couldn't save options.\n") (could-not-create-area . "Couldn't create the text.\n") (could-not-set-user-area . "Couldn't alter the user area. The server says error: %#1d\n") (you-dont-exist . "You don't exist. Go away.\n") (error-in-options . "There was an error in one of your variables (%#1s) It was set to \"%#2s\" in the user area. It is set to nil instead. Send a bug report.\n") (error-in-options-short . "There was an error in your saved settings. Some settings have not been read.") (reading-settings-from-server . "Saved settings have changed on the server. Re-reading saved settings.\n") ; From elib-string.el: ; No entries. ; From lyskom-rest.el: (mode-line-unread . " Unread ") (mode-line-letters . "letters ") (frame-title-unread . "Unread") (frame-title-letters . " letters") (sessions-with-unreads . "Sessions with unread texts") (unread-letters . "unread letters") (bad-text-no-prefix . "Unable to translate prefix `%s' to a text number") (prefix-arg-try-again . "Specify another text or press control-g to abort.\n") (error-code . "%#2?+%[Error code %#2d/%#3S: %]%[%]%#1s.\n") (error-in-kom-do-when-done . "The variable kom-do-when-done has an erroneous value. You should set it to a better value.\n") (extended-command . "LysKOM: ") (wait-for-server . "LysKOM is waiting for a response from the server. Wait for the prompt.\n") (review-text-q . "Review text: ") (completely-read-conf . "You have seen all the texts in this conference.\n") (not-in-any-conf . "You are not in a conference now.\n") (all-conf-unread-r . "You have nothing unread.\n") (all-conf-unread-s . "You have nothing unread. ") (enter-conf-unread . "%#1d unread text%#1?d%[%]%[s%]") (enter-conf-unread-faq . "%#1d unread FAQ%#1?d%[%]%[s%]") (save-one-on-file-q . "Save copy of text %#1n in file: ") (save-many-on-file-q . "Save copies of %#1d texts in file: ") (saving-one-on-file . "Saving copy of text %#1n in %#2s.\n") (saving-many-on-file . "Saving %#1d texts in %#2s.\n") (save-text-to-file-q . "Save body of text %#1n in which file: ") (save-text-confirm . "File %#1s exists. Overwrite? ") (saving-text . "Saving text %#1n as %#2s...") (what-save-no . "Which text do you want to save? ") (wait-for-prompt . "Wait for the prompt.") (conference-no . "") (person-no . "") (prompt-several-messages . "(%d messages)") (prompt-single-message . "(%d message)") (text-buffer-missing . "The text buffer no longer exists.\n") (re-edit-text-prompt . "Edit the text that couldn't be created") (go-to-pri-conf-prompt . "Go to next prioritized conference") (go-to-pri-mailbox-prompt . "Gå to your mailbox (prioritized)") (read-pri-text-conf . "Read next prioritized text") (read-pri-letter-prompt . "Read next letter (prioritized)") (review-next-text-prompt . "Review next text") (review-next-comment-prompt . "Review next comment") (review-next-marked-prompt . "Review next marked text") (review-next-faq-prompt . "Review next FAQ") (read-next-letter-prompt . "Read next letter") (read-next-footnote-prompt . "Read next footnote") (read-next-comment-prompt . "Read next comment") (read-next-text-prompt . "Read next text") (read-next-attachment-prompt . "Read next attachment") (go-to-conf-of-marked-prompt . "Resume reviewing marked") (go-to-conf-of-review-tree-prompt . "Resume reviewing comments") (go-to-conf-of-review-prompt . "Resume reviewing texts") (go-to-conf-of-review-faq-prompt . "Resume reviewing FAQs") (go-to-next-conf-prompt . "Go to next conference") (go-to-your-mailbox-prompt . "Go to your mailbox") (next-pri-session-prompt . "Go to prioritized LysKOM \"%#1s\"") (next-unread-session-prompt . "Go to LysKOM \"%#1s\"") (no-such-kom-session . "No such session with unread texts.\n") (the-command . "Command: %#1C") (error-in-login-hook . "There was an error in your kom-login-hook: %#1s\n") (give-a-number . "Enter a number: ") (yes-regexp . "\\`[yY][eE][sS]\\'") (no-regexp . "\\`[nN][oO]\\'") (yes-string . "Yes") (no-string . "No") (yes-or-no-nag . "Answer yes or no.") (yes-or-no . "(yes or no) ") (y-or-n-instring . "yYnN ") (j-or-n-nag . "Answer y or n. ") (j-or-n . "(y or n) ") (y-instring . "yY ") (a-or-b-or-c-nag . "Pleas press a valid key. ") (person-does-not-exist . "User %#1d (does not exist).") (conference-does-not-exist . "Conference %#1d (does not exist).") (conf-no-does-not-exist-r . "Conference %#1d does not exist.") (person-is-anonymous . "Anonymous user") (process-signal . "Signal from the process.") (dead-session . "No active LysKOM session.") (resurrect-session . "The LysKOM session is not active. Do you want to reconnect? ") (not-lyskom-buffer . "This is not an active LysKOM session.") (closed-connection . " ************************************************** %#2s LysKOM session killed abnormally Error message: %#1s**************************************************") (error-not-found . "Error code %#1d. No explanation available.") ; Useful in more places than one: (illegal-command . "Illegal command.\n") (no-such-text . "The text doesn't exist.\n") (no-such-text-m . "The text doesn't exist.") (nobody . "nobody") (everybody . "everyone") (everything . "everything") (anybody . "anyone") (forward . "forward") (backward . "backward") (wait . "Wait a moment...\n") (comment . "Comment") (comment-prefix . "\\([Cc][Oo]\\)") (footnote . "Footnote") (footnote-prefix . "\\([Ff]\\)") (by . " by %#1P") (text-created . "Text %#1n has been created.\n") (text-created-anonymous . "\ Text %#1n has been created (anonymously). To make it more difficult for others to figure out that you wrote the text, you should wait a while before reading it.\n") (resolve-session . "Which session: ") (starting-program . "Starting %#1s...") (super-jump . "Filtering subject \"%#1r\" in conference \"%#2M\"\n") (no-recipient . "There are no recipients for this text.\n") (filtered . "[Filtered]") (filter-error-specification . "Error in the filter specification") (filter-error-bad-not . "Error in the filter specification after 'not'") (filter-error-unknown-key . "The filter key '%S' is unknown.") (filter-error-key-arg . "Bad filter data (%S %S)") (filter-tree . "Skipping text %#1n \"%#2r\" by %#3P and all its comments.\n") (filter-text . "Skipping text %#1n \"%#2r\" by %#3P.\n") (filter-permanent . "Permanent? ") (filter-action . "Filter how? ") (filter-in-conf . "In which conference? (all) ") (filter-subject . "Filter which subject? ") (filter-recipient . "Filter which recipient? ") (filter-which-text . "Filter texts containing: ") (filter-author . "Filter which author? ") (permanent . "(permanent)") (temporary . "(temporary)") (filter-edit-buffer-name . "*LysKOM Filter Edit*") (filter-edit-empty-list . "Empty list") (filter-edit-start-of-list . "Beginning of list") (filter-edit-end-of-list . "End of list") (filter-edit-filter-how . "Filter how? ") (filter-edit-filter-what . "What do you want to filter? ") (filter-edit-bad-argument . "Bad input: %s") (filter-edit-outside-entry . "Can't do that outside a filter") (filter-edit-outside-list . "Can't do that outside the list") (filter-edit-end-of-pattern . "End of filter") (filter-edit-save-p . "Save changes? ") (filter-edit-remove-empty . "Empty filters cause all texts to be filtered. Do you want to remove these? ") (filter-edit-restart-p . "You have made changes. Really revert? ") (filter-edit-help . "p Up, n Down, i New line, M-i New filter, d Delete line, M-d Delete filter") (filter-edit-header . "Edit filters on \"%s\"\n") (filter-edit-saving . "Saving changes...") (filter-edit-saving-done . "Saving changes...done") (filter-edit-saving-error . "Couldn't save changes!") (filter-edit-insert-pred . "%#1s (=,!=): ") (filter-edit-insert-arg . "%#1s %#2s (what): ") (no-filters . "No filters are defined.\n") (view-filters-header . "\nActive filters:\n\n") (view-filters-footer . "") (ansaphone-new-message . "New Ansaphone message: ") (ansaphone-message . "Ansaphone message: ---------------------------------------------------------------------- %#1t ---------------------------------------------------------------------- ") (ansaphone-message-long . "Ansaphone message: ------------------------------------------------------------------------------- %#1t ------------------------------------------------------------------------------- ") (ansaphone-state . "The Ansaphone is %#1s.") (ansaphone-state-r . "The Ansaphone is now %#1s.\n") (ansaphone-messages-gone . "Recorded messages have been erased.") (ansaphone-no-messages . "No recorded messages.\n") (ansaphone-message-list-start . "Recorded messages:\n\n") (ansaphone-message-list-end . "\n\n") (ansaphone-message-header . "Automatic reply (set %#1s):\n") (remote-erase-messages . "Remote control (%#1P %#2s): Erased recorded messages\n") (remote-set-message . "Remote control (%#1P %#2s): Ansaphone message: ---------------------------------------------------------------------- %#3t ---------------------------------------------------------------------- ") (remote-set-message-long . "Remote control (%#1P %#2s): Ansaphone message: ------------------------------------------------------------------------------- %#3t ------------------------------------------------------------------------------- ") (remote-set-ansaphone . "Remote control (%#1P %#2s): The ansaphone is %#3s\n") (remote-list-messages . "Remote control (%#1P %#2s): Listed recorded messages\n") (remote-quit . "Remote control (%#1P %#2s): Quit\n") (illegal-remote . "Illegal remote control attempt: Time: %#1s From: %#2P <%#2p> To : %#3P <%#3p> Text: %#4t") (illegal-remote-reply . "Remote control rejected: %#1s") (remote-not-in-list . "Unauthorised person") (remote-bad-command . "Unknown or malformed command") (remote-unknown-error . "Unknown error") (remote-control-who . "Remotely control which session? ") (remote-control-autoreply . "Ansaphone on or off? ") (state-on . "on") (state-off . "off") (text-popup-title . "Text %#1s") (conf-popup-title . "Conference %#1s") (pers-popup-title . "User %#1s") (url-popup-title . "URL %#1s") (aux-popup-title . "Property") (timestamp-popup-title . "Timestamp %#1s") (recpt-type-popup-title . "Recipient type: %#1s") (add-recpt-button-text . "[Add...]") (add-recpt-button-text-regex . "\\[Add\\.\\.\\.\\]") (generic-popup-title . "%#1s") (who-i-am-not-present . "%#1P (not in any conference) \n") (who-i-am-present . "%#1P is present in %#2M\n") (who-i-am-client . "The program is lyskom.el, version %#1s%#2?b%[ (MULE)%]%[%].\n") (who-i-am-server . "This is %#1s, version %#2s.\n") (who-i-am-emacs . "Running under %#1s%#2?b%[ (MULE)%]%[%].\n") (no-such-session-r . "That session does not exist. Perhaps the user is not logged on.\n") (person-not-logged-in-r . "%#1P %#2?b%[has not been logged on since %#2s%]%[is not logged on%].\n") (session-status . "Session %#1d is %#2P <%#2p> %#5s %#7s %#4M Using %#6D from %#3s\n") (session-status-9 . "Session %#1d is %#2P <%#2p> %#5s %#7s %#4M Using %#6D from %#3s On since %#8s%#9s") (session-status-inactive . "\nHas been inactive for %#1s\n") (one-day . "one day") (one-hour . "one hour") (one-minute . "one minute") (years . "years") (year . "år") (month . "month") (months . "months") (days . "days") (day . "day") (hours . "hours") (minutes . "minutes") (and . "and") (session-is-active . " and is currently active.\n") (session-is-invisible . "This session is invisible.\n") (status-for-session . "Session status for whom? ") (unknown-doing-what . "Exists") (doing-where-conn . "in") (doing-nowhere-conn . "but is") (waiting-for-membership . "Waiting for the membership list to be fetched...%d/%d") ;; From slow.el (no-such-command . "There is no such command.\n") (command-completions . "You may mean one of the following:\n %#1s\n") (which-language . "Change language to: ") (send-formatted . "Send as formatted text? ") (changing-language-to . "Changing to %#1s.\n") (language-set-to . "Language set to %#1s%#2?b%[ %#3@[%#2s]%]%[%].\n") (language-not-loaded . "%#1s is unavailable.\n") (reformat-html . "HTML") (reformat-enriched . "enriched") (reformat-filled . "filled") (reformat-image . "image") (image-no-show . "< The image cannot be shown. >") (reformat-truncated . "truncated") (reformat-signature . "designed") (reformat-deswascii . "was swascii") (reformat-rot13 . "rot13") (need-library . "The \"%#1s\" package is required for this command.\n") (calc-expression . "Expression: ") (do-send-anonymous . "Send the text anonymously? ") (remove-self-sending-anonymous . "Remove yourself as a recipient of the text? ") (anonymous . "anonymous") (Anonymous . "Anonymous") (secret-conf-letter . "S") (protected-conf-letter . "P") (created-conf-letter . "C") (superconf-conf-letter . "S") (supervisor-conf-letter . "O") ;; Some Help (where-is-doesnt-exist . "The command %#1s does not exist") (where-is-on-no-key . "%#1s is not on any key") (where-is-on-key . "%#1s is on %#2s") ;; From aux-items.el (content-type-aux . "Content type: %#1s") (content-type-regexp . "Content type: \\(\\S-+\\)") (agreeing . "Agreeing with text %#1n...") (fast-replying . "Remark to text %#1n...") (author-fast-replies . "Remarks by the author:") (author-fast-reply-aux . " \"%#1t\"") (other-fast-replies . "Remarks:") (other-fast-reply-aux . " \"%#1t\" /%#2P/") (fast-reply-too-long . "Can't create remarks that consist of more than one line.\n") (conf-to-list-faqs . "List FAQ for which conference: ") (faq-for-conf-aux . "FAQ for %#1M <%#1m>") (bad-faq-for-conf-aux . "FAQ: \"%<20...#1s\" %[%#2@[invalid]%] %#3s") (faq-for-server-aux . "FAQ for the LysKOM-server") (faq-in-text-aux . "FAQ in text: %10#1n %#2D") (bad-faq-in-text-aux . "FAQ in text: \"%<20...#1s %[%#2@[invalid]%] %#3s") (conf-to-add-faq . "Which conference do you want to add an FAQ for? ") (text-to-add-as-faq . "Which text is the new FAQ? ") (text-to-change-as-faq . "Which FAQ do you want to change? ") (adding-faq . "Adding text %#1n as an FAQ for %#2?b%[%#2M%]%[the server%]...") (conf-to-del-faq . "Which conference do you want to remove an FAQ from? ") (text-to-del-as-faq . "Which text do you want to remove as FAQ? ") (deleting-faq . "Removing text %#1n as FAQ for %#2?b%[%#2M%]%[the server%]...") (conf-has-no-faq . "%#1?b%[%#1M%]%[The server%] has no FAQ\n") (unread-which-faq . "Mark FAQ for which conference as unread? ") (view-which-faq . "View FAQ for which conference? ") (review-faq-for-r . "View FAQ for %#1?b%[%#1M%]%[the server%].\n") (set-faq-for-conf-done . "FAQ for %#1?b%[%#1M%]%[the server%] set to text %#3n.\n") (set-faq-for-conf-failed . "Unable to set the FAQ for %#1?b%[%#1M%]%[the server%] to text %#3n.\n") (changed-faq-for-conf-done . "FAQ in text %#2n for %#1?b%[%#1M%]%[the server%] changed to text %#3n.\n") (changed-faq-for-conf-failed . "Unable to change FAQ for %#1?b%[%#1M%]%[the server%] to text %#3n. %#2?b%[Text %#2n is still the FAQ. %]%[%]%#4s") (faq-in-text . "FAQ in text %#1n %#3s%#4s") (faq-in-text-by . "FAQ in text %#1n %#5s %#3sby %#2P %#4s") (server-has-new-faq . "\nThere %#1?d%[is a new FAQ%]%[are %#1d new FAQs%] for the server.\n") (unread-faqs-header . "\nUnread FAQ%#1?d%[%]%[s%] for %#2?b%[%#2M%]%[the server%]::\n") (all-faqs-header . "All FAQs for %#1?b%[%#1M%]%[the server%]:\n") (too-many-languages . "Cannot code that many character sets. Send uncoded? ") (too-many-content-types . "Cannot figure out what content type you want. Simplify the text.") (cross-reference-text-status-aux . "See text: %10#1n /%#2P/") (cross-reference-conf-status-aux . "See conference: <%#1m> %#1M /%#2P/") (cross-reference-pers-status-aux . "See person: <%#1p> %#1P /%#2P/") (strange-cross-reference-status . "See also: %#1s (whatever that means)") (cross-reference-text-aux . "See text %#1n /%#2P/") (cross-reference-conf-aux . "See conference <%#1m> %#1M /%#2P/") (cross-reference-pers-aux . "See person <%#1p> %#1P /%#2P/") (cross-reference-text-regexp . "See text \\([0-9]+\\)") (cross-reference-conf-regexp . "See conference <\\([0-9]+\\)>") (cross-reference-pers-regexp . "See person <\\([0-9]+\\)>") (strange-cross-reference . "See %#1s, whatever that might mean") (no-comments-aux . "The author has requested others not to comment this text") (no-comments-edit-aux . "Request that others do not comment") (no-comments-regexp . "Request that others do not comment") (personal-comment-aux . "The author has requested private replies only") (personal-comment-edit-aux . "Request private replies only") (personal-comment-regexp . "Request private replies only") (request-confirmation-aux . "%#1P has requested confirmation of reading") (request-confirmation-edit-aux . "Request confirmation of reading") (request-confirmation-regexp . "Request confirmation of reading") (confirm-read-q . "Confirm reading text %#1n? ") (read-confirm-aux . "Confirmed reading: %#1P %#2s") (redirect-email-aux . "Send e-mail to %#1s") (redirect-lyskom-aux . "Send texts to conference %#1M") (label-what-kind . "Set personal label on what (text, conference, user)? ") (label-what-text . "Set personal label on text: ") (label-what-conf . "Set personal label on which conference? ") (label-what-pers . "Set personal label on which person? ") (label-what-label . "Personal label: ") (label-secret . "Should others to be able to see the label? ") (creating-software-aux . "Created with %#1s") (world-readable-text-aux . "The text can be read without logging on") (world-readable-text-edit-aux . "Make the text readable without logging on") (cant-get-aux-item . "Can't find property\n") (aux-item-no-info . "No information available\n") (aux-item-info . "\ Number: %#1d %#6s Type: %#2d (%#3s) Created by: %#4P <%#4p> Created: %#5s Flags: %#7s Inherit limit: %#8s Contents: \"%#9s\" ") (secret . "Secret") (deleted . "Deleted") (hide-creator . "Secret creator") (inherit . "Inherited") (unlimited-inherit . "Unlimited inheritance") (no-inheritance . "Inheritance is off") (no-more-inheritance . "Inherit limit reached; will not be further inherited") (inherit-steps . "%#1d steps") (aux-item-for . "Properties for ") (aux-item-for-conference-no . "conference <%#1m> %#1M") (aux-item-for-text-no . "text %#1n") (aux-item-for-server . "the server") (what-fast-reply-no . "Remark to which text? ") (fast-reply-prompt . "Remark: ") (agree-prompt . "Text: ") (default-agree-string . "I agree") (what-agree-no . "Agree with which text? ") (what-kind-to-add-aux-to . "Attach information to what? ") (which-conf-to-add-aux-to . "Which conference to you want to attach information to? ") (which-text-to-add-aux-to . "Which text to you want to attach information to? ") (which-aux-item-tag . "Information tag: ") (which-aux-item-inherit . "Set the inherit-flag? ") (which-aux-item-secret . "Set the secret-flag? ") (which-aux-item-anonymous . "Set the anonymous-flag? ") (which-aux-item-rsv1 . "Set the dont-garb-flag? ") (which-aux-item-rsv2 . "Set the reserved2-flag? ") (which-aux-item-rsv3 . "Set the reserved3-flag? ") (which-aux-item-rsv4 . "Set the reserved4-flag? ") (which-aux-item-inherit-limit . "Inherit limit: ") (which-aux-item-data . "Data: ") ;; Cross-reference stuff (Person . "User") (person . "user") (persons . "users") (Conference . "Conference") (conference . "conference") (conferences . "conferences") (Text . "Text") (text . "text") (texts . "texts") (Server . "Server") (server . "server") (servers . "servers") (abc-person . "pPerson") (abc-conference . "cConference") (abc-text . "tText") (xref-type . "What to you want to refer to? ") (which-text-to-xref . "Add reference to text: ") (which-text-to-xref-err . "Text not found. Add reference to text: ") (which-pers-to-xref . "Add reference to user: ") (which-conf-to-xref . "Add reference to conference: ") ;; Aux-item stuff from edit-text (no-comments-q . "The author doesn't want comments. Comment anyway? ") (private-answer-q . "The author wants private replies. Write private reply? ") (your-invited . "You have been invited to %#1M by %#2P. By accepting the invitation you will continue to be a member of %#1M. If you decline the invitation you will not be a member of the conference. ") (accept-invitation . "Do you want to accept the invitation now? ") (enter-passive . "You are a passive member of %#1M. You must become an active member of the conference to enter it.\n") (convert-passive . "Do you want to become an active member of %#1M? ") (bug-secret-mship . "You are a secret member of %#1M\n") (invitation-mt-type . "invited") (passive-mt-type . "passive") (secret-mt-type . "secret") (message-flag-off-mt-type . "no group messages") (message-flag-on-mt-type . "group messages") (Invitation-mt-type . "Invited") (Passive-mt-type . "Passive") (Secret-mt-type . "Secret") (Message-flag-mt-type . "Group messages") (not-author . "You are not the author of text %#1n.") (not-author-try-anyway-p . "You are not the author of the text. Try anyway? ") (what-no-comments-no . "Which text do you want to prevent comments to: ") (adding-no-comments . "Preventing comments to text %#1n...") (already-no-comments . "Text %#1n already prevents comments.\n") (what-private-answer-no . "Which text do you want private replies to: ") (adding-private-answer . "Requesting only private replies to text %#1n...") (already-private-answer . "Text %#1n already has a request for private replies only.\n") (what-request-confirm-no . "Which text do you want read confirmations for: ") (adding-request-confirm . "Requesting read confirmations for text %#1n...") (already-request-confirm . "Text %#1n already has a request for read confirmations.\n") (review-mail-headers-to-what . "Which text's mail headers do you want to see? ") (no-mail-headers . "Text %#1n has no mail headers\n") (mail-headers-for . "Mail headers for text %#1n:\n") (email-name-prefix . "") (email-name-suffix . "") (you-are-anonymous . "You are now somewhat anonymous.\n") (you-are-nonanonymous . "You are no longer anonymous.\n") (you-are-already-anonymous . "You are already somewhat anonymous.\n") (you-are-already-nonanonymous . "You are already non-anonymous.\n") (start-keep-alive . "Sending data at %#1d second intervals to keep the connection active.") (stop-keep-alive . "No longer keeping connection active by sending extra data.") (review-converted-q . "Review which text converted?") (review-noconversion-q . "Review which text unconverted?") (review-rot13-q . "Review which text in rot13?") (unread-commented-q . "Mark the commented for which text as unread?") (review-commented-q . "Review the commented for which text?") (review-tree-q . "Review all comments recursively for which text?") (find-root-q . "Review original text for text?") (find-root-review-q . "Review tree of which text?") (review-comments-q . "Review all comments to which text?") (review-xrefs-q . "Review all cross references from which text?") (unread-tree-q . "Unread all comments recursively for which text?") (unread-root-q . "Unread original text for text?") (unread-root-review-q . "Unread tree of which text?") (unread-comments-q . "Unread all comments to which text?") (confusion-who-to-reply-to . "I can't figure out which text you want to write a private reply to.\n") (confusion-what-to-answer-to . "I can't figure out which text you want to write a reply to.\n") (confusion-what-to-view . "I can't figure out which text you want to view.\n") (confusion-what-to-reply-to . "I can't figure out which text you want to write a remark to.\n") (confusion-what-to-agree-to . "I can't figure out which text you want to agree with.\n") (confusion-what-to-request-confirmation . "I can't figure out which text you want read confirmations for.\n") (confusion-what-to-comment . "I can't figure out which text you want to comment.\n") (confusion-what-to-footnote . "I can't figure out to which text you want to write a footnote to.\n") (confusion-what-to-delete . "I can't figure out which text you want to delete.\n") (confusion-what-to-add-sub-recipient . "I can't figure out which text you want to %#1s.\n") (add-rcpt-action-name . "add a recipient to") (add-copy-action-name . "add a carbon copy recipient to") (add-bcc-action-name . "add a blind carbon copy recipient to") (sub-action-name . "remove a recipient from") (move-action-name . "move") (confusion-what-to-add-comment-to . "I can't figure out which text you want to add a comment to.\n") (confusion-what-to-sub-comment-from . "I can't figure out which text you want to remove a comment from.\n") (confusion-what-to-add-footnote-to . "I can't figure out which text you want to add a footnote to.\n") (confusion-what-to-sub-footnote-from . "I can't figure out which text you want to remove a footnote from.\n") (confusion-what-to-mark . "I can't figure out which text you want to mark.\n") (confusion-what-to-unmark . "I can't figure out which text you want to unmark.\n") (confusion-what-to-save . "I can't figure out which text you want to save.\n") (confusion-what-to-review-mail-headers . "I can't figure out which text's mail headers you want to see.\n") (confusion-what-to-unread-root . "I can't figure out which text's root you want to mark as unread.\n") (confusion-what-to-unread-root-review . "I can't figure out which tree you want to mark as unread.\n") (confusion-what-to-find-root . "I can't figure out which text's root you want to see.\n") (could-not-find-root . "Unable to identify the root text. The comment structure may be cyclic.\n") (confusion-what-to-find-root-review . "I can't figure out which tree you want to review.\n") ;; Help stuff (help-with-what . "What do you want help with? ") (help-for . "Help for \"%#1s\"\n") ;; Button actions (lyskom-button-view-text-action . "View text") (lyskom-button-unread-text-action . "Unread text") (lyskom-button-copy-text-no-action . "Copy text number") (lyskom-button-review-converted-action . "Review converted") (lyskom-button-review-noconversion-action . "Review unconverted") (lyskom-button-review-rot13-action . "Review rot13") (lyskom-button-find-root-review-action . "Review tree") (lyskom-button-find-root-action . "Review root text") (lyskom-button-comment-text-action . "Write comment") (lyskom-button-private-comment-text-action . "Write personal reply") (lyskom-button-mark-text-action . "Mark text") (lyskom-button-unmark-text-action . "Unmark text") (lyskom-button-save-text-action . "Save archive copy") (lyskom-button-save-text-body-action . "Save text body") (lyskom-button-review-comments-action . "Review all comments") (lyskom-button-review-tree-action . "Review all comments recursively") (lyskom-button-write-footnote-action . "Write footnote") (lyskom-button-fast-reply-action . "Remark") (lyskom-button-view-conf-presentation-action . "View presentation") (lyskom-button-view-conf-status-action . "View conference status") (lyskom-button-goto-conf-action . "Go to conference") (lyskom-button-send-message-action . "Send group message") (lyskom-button-add-self-action . "Join conference") (lyskom-button-sub-self-action . "Leave conference") (lyskom-button-view-pers-presentation-action . "View presentation") (lyskom-button-view-pers-status-action . "View user status") (lyskom-button-view-session-status-action . "View session status") (lyskom-button-mail-action . "Send letter") (lyskom-button-send-message-action . "Send personal message") (lyskom-button-open-url-action . "Open") (lyskom-button-copy-url-action . "Copy") (lyskom-button-goto-info-node-action . "Open") (lyskom-button-open-email-action . "Send mail") (lyskom-button-copy-email-action . "Copy") (lyskom-button-info-aux-action . "Information") (lyskom-button-delete-aux-action . "Delete") (lyskom-button-copy-timestamp-action . "Copy") (lyskom-button-recpt-type-recipient . "Recipient") (lyskom-button-recpt-type-copy . "Carbon copy") (lyskom-button-recpt-type-bcc . "Blind Carbon copy") (lyskom-button-recpt-type-sub . "Remove") (lyskom-button-recpt-add-recipient . "Recipient") (lyskom-button-recpt-add-copy . "Carbon copy recipient") (lyskom-button-recpt-add-bcc . "Blind carbon copy recipient") (lyskom-button-aux-type-xref . "Reference to conference/person/text") (lyskom-button-aux-type-no-comments . "Request no comments") (lyskom-button-aux-type-personal-comments . "Request personal reply") (lyskom-edit-toggle-secret-aux-action . "Toggle \"secret\"") (lyskom-edit-toggle-anonymous-aux-action . "Toggle \"anonymous\"") (lyskom-edit-toggle-inherit-aux-action . "Toggle \"inherited\"") (lyskom-edit-delete-aux-action . "Delete") (lyskom-prioritize-flag-toggle-action . "Toggle") (lyskom-prioritize-flag-set-action . "Set") (lyskom-prioritize-flag-clear-action . "Clear") (server-status-header . "Status for LysKOM-server %#1s%#2?b%[ (%#2s:%#3d)%]%[%]\n\n") (server-status-server . "Canonical server name: %#1s%#2?b%[:%#2s%]%[%]\n") (server-status-version . "Software version: %#1s %#2s\n") (server-status-protocol . "Protocol version: %15#1d\n") (server-status-sessions . "\ Number of sessions: %21#1d (total) %21#2d active in the last %#7d minutes %21#3d inactive sessions %21#4d unknown activity %21#5d invisible sessions %21#6d not logged on/secret/zombies\n") (server-status-first-text . "Oldest existing text: %14#1n\n") (server-status-last-text . "Youngest existing text: %14#1n%#2?b%[ (%#2n at start)%]%[%]\n") (server-status-texts . "Number of texts: %14#1d (%#2s now, %#3d at start)\n") (server-status-confs . "Number of conferences: %14#1d (%#2s now, %#3d at start)\n") (server-status-pers . "Number of persons: %14#1d (%#2s now, %#3d at start)\n") (server-status-has-motd . "\nThe server has a notice:\n") (server-status-time . "Current server time: %#1s\n") (server-status-boot-time . "Server start time: %#1s\n") (server-status-save-time . "Initial database save time: %#1s%#2?b%[ (%#2s)%]%[%]\n") (mship-type-invitation-q . "Membership invitation? ") (mship-type-passive-q . "Passive membership? ") (mship-type-secret-q . "Secret membership? ") (recommend-which-conf . "Which conference do you want to recommend? ") (recommend-set-priority-q . "Recommend a priority? ") (recommend-set-mship-type-q . "Recommend a membership type? ") (recommending-conf . "Recommending %#1M%#2?b%[ (priority %#2d)%]%[%]%#3?b%[ %#3s%]%[%]...") (has-recommended-conf . "%#1P has recommended conference %#2M. Do you want to become a member?\n") (accept-recommendation . "Join conference %#1M? ") (accepting-recommendation . "Joining recommended conference %#2M...") (redirect-for-whom . "Redirect comments for whom: ") (redirect-to-which-conf . "Redirect comments to: ") (redirecting-comments-to . "Redirecting comments for %#1P to %#2M%#3?b%[ (old %#1M)%]%[%]...") (kom-redirect-comments-e49 . "You do not have permission to perform this redirection") (kom-redirect-comments-e48 . "Comment redirection is not supported by the server") (external-program-missing . "Can't find the external program \"%#1s\" that is required for this command.") (ignored-user-area-var . "\ Ignoring the following variables in your settings: %#1s These variables are not registered as LysKOM variables and cannot be read from the server. You can remove the variables from the server by giving the command \"Save options\". %#2?b%[%#5F\ Unknown variables may be the result of saving your settings in version %#3s of the client; this is version %#4s. %]%[%]") (unknown-aux-item . "Unknown property") (text-header-aux-item . "%#1s: <%#2d> \"%#3s\" %#4s") (aux-content-type-name . "Content type") (aux-fast-reply-name . "Remark") (aux-cross-reference-name . "Reference") (aux-no-comments-name . "Request for no comments") (aux-personal-comment-name . "Request for personal replies") (aux-request-confirmation-name . "Request for read confirmation") (aux-read-confirm-name . "Read confirmation") (aux-redirect-name . "Redirect") (aux-x-face-name . "Picture") (aux-alternate-name-name . "Alternate name") (aux-pgp-signature-name . "PGP signature") (aux-pgp-public-key-name . "PGP public key") (aux-e-mail-address-name . "E-mail address") (aux-faq-text-name . "FAQ in text") (aux-creating-software-name . "Creating software") (aux-mx-author-name . "E-mail author") (aux-mx-from-name . "E-mail from") (aux-mx-reply-to-name . "E-mail reply to") (aux-mx-to-name . "E-mail to") (aux-mx-cc-name . "E-mail CC") (aux-mx-date-name . "E-mail date") (aux-mx-message-id-name . "E-mail message ID") (aux-mx-in-reply-to-name . "E-mail in reply to") (aux-mx-misc-name . "E-mail headers") (aux-mx-allow-filter-name . "E-mail allow-filter") (aux-mx-reject-forward-name . "E-mail reject-forward") (aux-notify-comments-name . "Notify me about comments") (aux-faq-for-conf-name . "FAQ for conference") (aux-recommended-conf-name . "Conference recommendation") (aux-allowed-content-type-name . "Allowed content type") (aux-canonical-name-name . "Canonical name") (aux-mx-list-name-name . "Mailing list name") (aux-send-comments-to-name . "Send comments to") (aux-world-readable-name . "World-readable") (aux-mx-refuse-import . "Refuse text import") (aux-elisp-client-read-faq-name . "Read FAQ") (aux-elisp-client-rejected-invitation-name . "Rejected invitation") (review-marking-as-read . "Review marks as read") (review-not-marking-as-read . "Review does not mark as read") (review-using-cache . "Review uses cache") (review-not-using-cache . "Review doesn't use cache") (using-ssh-connection . "Using ssh connection to %#1s...") (opening-ssh-connection . "Opening ssh connection to %#1s...") (ssh-cant-connect . "Unable to open ssh connection: %s") (ssh-closing . "Closing ssh connection to %#1s") (ssh-unknown-host . "unknown host") (keyboard-cancel . "Cancel") (keyboard-menu-help . "(choose: C-n, C-p; confirm: RET)") (customize-help . "See the beginning of the buffer for more information") (no-mule-warning . "\ %#1@You have disabled support for multibyte characters (MULE) in emacs. This may be due to a call to standard-display-european in your .emacs or in one of the shared emacs startup files. This software is designed to run with support for multibyte characters enabled. Without this support texts may be displayed incorrectly, and you may encounter problems writing texts. Consider enabling sypport for multibyte characters in emacs. ") (coding-system-mismatch-warning . "\ %#3@Your emacs is configured to encode characters using \"%#1s\", but the LysKOM server you are using recommends \"%#2s\". You may encounter problems when writing comments, and comments to your texts may contain a mix of characters that cannot be encoded or displayed correctly. Please consider changing your language environment to one that uses \"%#2s\" to encode text. ") (has-nameday-1 . "Today's name is %#1s%#2?b%[ (%#2s)%]%[%].") (has-nameday-2 . "Today's names are %#1s and %#2s%#3?b%[ (%#3s)%]%[%].") (no-nameday . "No nameday today%#2?b%[ (%#2s)%]%[%]") (invalid-date-entry . "Invalid date") (number-out-of-range . "Invalid number") (or-date . "or date") (set-unread-n . "Only read the most recent %#1?d%[text%]%[%#1d texts%].\n") (set-unread-date . "Only read texts since %#2s %#3d, %#1d.\n") (jump-from-text . "Skip comments to which text? ") (jumping-from-text . "Skipping comments to text %#1n.\n") (jumping-from-text-review . "Skipping reviewed comments.\n") (session-to-copy-options-from . "Session to copy options from: ") (reading-settings-from . "Reeading options from %s...") (reading-settings-from-done . "Reading options from %s...done") (super-jump-q . "Super jump which text? ") (conf-list-legend . "* Not member; - Passive member\n") (unread-text-q . "Make which text unread? ") (marking-text-unread . "Marking text %#1n as unread...") (cant-mark-text-unread . "Couldn't mark %#1n as unread (%#2s)\n") (confusion-what-to-mark-unread . "I can't figure out what text you want to mark as unread.\n") (no-comment-to-to-unread . "There is no commented text to mark as unread.\n") (mx-refuse-import-html . "HTML") (mx-refuse-import-spam . "Spam") (mx-refuse-import-all . "All texts") (abc-html . "hHTML") (abc-spam . "sSpam") (abc-everything . "aAll texts") (limit-import-to-conf . "Limit import to which conference? ") (limit-import-of-what . "Limit import of what? ") (limit-import-not-super . "You do not seem to be the supervisor of the conference. Try anyway? ") (limiting-import . "Limiting import of %#1s to %#2M...") (set-message-flag-for-conf . "Sett message flag for which conference? ") (set-message-flag-to-what . "Receive grupp messages to %#1M? ") (setting-message-flag . "%#1?b%[Enabling%]%[Disabling%] reception of group messages to %#2M...") (text-has-no-comments . "Text %#1n has no comments\n") (text-has-no-footnotes . "Text %#1n has no footnotes\n") (set-message-flag-q . "Accept group messages to %#1M? ") (why-you-got-no-presentation . "\ %#1@\ ======================================================================== You do not have a presentation%#2?z%[ but you've written %#2d texts%]%[%] Use the command \"Change presentation\" to write or change your presentation. %[%#4F\ Your presentations serves to give other users of %#3s some information about who you are, and this contributes to the sense of community in %#3s. This message will be repeated at random intervals until you have written a presentation.%] ======================================================================== ") (status-server-stats . "Server statistics:\n\n") (current-average . "current") (unit-second . "second") (unit-minute . "minute") (unit-hour . "hour") (unit-day . "day") (unit-mongth . "month") (unit-year . "year") (db-status-backup . "information loss may have occurred") (no-support-in-server . "No support in server for this command.\n") (mark-confs-as-known . "Mark these %#2d %#1s as known? ") (no-new-conferences . "No new %#2s%#1?b%[ since %#1s%]%[%].\n") (new-conferences-since . "New %#2s%#1?b%[ since %#1s%]%[%]:\n") (list-confs-from-date . "List %#1s created since what date (empty for everything)? ") (privs-wheel . "wheel") (privs-admin . "administrator") (privs-statistic . "statistics") (privs-create-conf . "create conferences") (privs-create-pers . "create persons") (privs-change-name . "change names") (privs-flg7 . "unknown (7)") (privs-flg8 . "unknown (8)") (privs-flg9 . "unknown (9)") (privs-flg10 . "unknown (10)") (privs-flg11 . "unknown (11)") (privs-flg12 . "unknown (12)") (privs-flg13 . "unknown (13)") (privs-flg14 . "unknown (14)") (privs-flg15 . "unknown (15)") (privs-flg16 . "unknown (16)") (lyskom-no-privileges . "no permissions") (what-pers-privs-to-change . "Whose privileges do you want to change? ") (change-pers-privs-prompt . "\ Current privileges for %#1P (%#1p): %#2s Change privileges for %#1P (%#1p)...") (set-wheel-priv-q . "Activate wheel privileges? ") (set-admin-priv-q . "Activate administrator privileges? ") (set-statistic-priv-q . "Activate statistics privileges? ") (set-create-conf-priv-q . "Activate right to create conferences? ") (set-create-pers-priv-q . "Activate right to create persons? ") (set-change-name-priv-q . "Activate right to change names? ") (set-flg7-priv-q . "Activate unknown privilege 7? ") (set-flg8-priv-q . "Activate unknown privilege 8? ") (set-flg9-priv-q . "Activate unknown privilege 9? ") (set-flg10-priv-q . "Activate unknown privilege 10? ") (set-flg11-priv-q . "Activate unknown privilege 11? ") (set-flg12-priv-q . "Activate unknown privilege 12? ") (set-flg13-priv-q . "Activate unknown privilege 13? ") (set-flg14-priv-q . "Activate unknown privilege 14? ") (set-flg15-priv-q . "Activate unknown privilege 15? ") (set-flg16-priv-q . "Activate unknown privilege 16? ") (canceling-command . "Canceling command...") ;; From mship-edit.el (no-selection . "No selection") (selection . "%#1d selected") (lp-no-hidden . "") (lp-hidden . "(%#1d hidden)") (priority-prompt . "New priority for %#1M: ") (priority-prompt-marked . "New priority for selected conferences: ") (lp-no-creation-info . "No information on when the membership was created") (lp-invited . "Invited") (lp-added . "Added") (lp-nope . "Operation failed: %#1s") (lp-no-entry . "No membership on this line") (lp-no-active-filter . "(no filters active)") (lp-active-filters . "Active filters: %#1s") (lp-mark-mship-with-prio . "Select memberships with priority: ") (lp-unmark-mship-with-prio . "Deselect memberships with priority: ") (lp-no-selection . "No memberships selected") (lp-at-min-prio . "Already at minimum priority") (lp-at-max-prio . "Already at maximum priority") (lp-beginning-of-list . "Beginning of list") (lp-end-of-list . "End of list") (lp-goto-priority . "Go to priority: ") (lp-mode-name . "Membership") (lp-header-main . "Membership for %#1M on %#2s") (lp-list-header . " Prio %#1s Last entered Unread IHPM\n") (lp-help-footer . " Select membership: SPC Select region: C-w Flytta markerade: C-y Set priority: p Increase prio: + Decrease prio: - Move up: M-p Move down: M-n Toggle flags: I,H,P,M Postpone reading: P Only last: o Quit: C-c C-c More help: C-h m ") (lp-hide-read-after . "Hide memberships read after: ") (lp-hide-read-since . "Hide memberships not read since: ") (lp-skipping-missing-meeting . "Conference %#1M no longer exists, skipping.") )) (lyskom-language-var local lyskom-month-names en '(("january" . 1) ("jan" . 1) ("february" . 2) ("feb" . 2) ("march" . 3) ("mar" . 3) ("april" . 4) ("apr" . 4) ("may" . 5) ("may" . 5) ("june" . 6) ("jun" . 6) ("july" . 7) ("jul" . 7) ("august" . 8) ("aug" . 8) ("september" . 9) ("sep" . 9) ("october" . 10) ("oct" . 10) ("november" . 11) ("nov" . 11) ("december" . 12) ("dec" . 12))) ;;; ================================================================ ;;; The commands and their associated functions ;;; Formely known as lyskom-commands (lyskom-language-strings local lyskom-command en '( (kom-help . "Help") (kom-slow-mode . "Long commands") (kom-quick-mode . "Short commands") (kom-send-message . "Send message") (kom-send-alarm . "Send alarm") (kom-create-conf . "Create conference") (kom-delete-conf . "Delete conference/user") (kom-delete-text . "Remove text") (kom-display-time . "Time") (kom-go-to-conf . "Go (to) conference") (kom-go-to-next-conf . "(Go to) next conference") (kom-jump . "Skip (all) comments") (kom-list-created-conferences . "List owned conferences") (kom-list-conferences . "List conferences") (kom-list-persons . "List users") (kom-list-news . "List news") (kom-list-sessions . "List sessions") (kom-list-re . "List (using) regexps") (kom-membership . "List memberships") ;; (kom-list-marks . "List marks") (kom-postpone . "Postpone reading") (kom-set-session-priority . "Set reading level") (kom-prioritize . "Prioritize conferences") (kom-status-person . "Status (of) person") (kom-status-conf . "Status (of) conference") (kom-add-self . "Join conference") (kom-change-priority . "Change priority") (kom-list-summary . "List text (subjects)") (kom-sub-self . "Leave (a) conference") (kom-quit . "Quit") (kom-recover . "Recover") (kom-start-anew . "New User") (kom-view . "Review text") (kom-find-root-review . "Review tree") (kom-review-comments . "Review all comments") (kom-review-tree . "Review all comments recursively") (kom-review-clear . "Review and skip") (kom-review-last-normally-read . "Review again") (kom-review-cross-references . "Review all cross references") (kom-review-converted . "Review converted") (kom-review-noconversion . "Review unconverted") (kom-review-rot13 . "Review rot13") (kom-review-next . "Review next") (kom-find-root . "Review original (text)") (kom-review-by-to . "Review last") (kom-review-first . "Review first") (kom-review-all . "Review all") (kom-review-more . "Review more") (kom-view-commented-text . "Review (the) commented (text)") (kom-view-previous-commented-text . "Review (the) previously commented (text)") (kom-review-stack . "Review stack") (kom-review-presentation . "Review presentation") (kom-review-backward . "(Review) Backwards") (kom-view-next-text . "(Read) next text") (kom-who-is-on . "Who (is on)") (kom-who-is-on-in-conference . "Who (is on in) conference") (kom-who-is-present-in-conference . "Who (is) present (in) conference") (kom-who-is-on-and-friend . "Which friends (are on)") (kom-who-am-i . "Where (am) i") (kom-list-clients . "List clients") (kom-busy-wait . "Wait (for news)") (kom-write-comment . "(Write) comment") (kom-comment-previous . "(Write) comment (to) previous text") (kom-write-footnote . "(Write) footnote") (kom-private-answer . "(Write) personal reply (by letter)") (kom-private-answer-previous . "(Write) personal (reply to) previous text (by letter)") (kom-set-unread . "Only (the) last") (kom-write-text . "Write (a) text") (kom-send-letter . "Write (a) letter") (kom-change-name . "Change name") (kom-change-parenthesis . "Change parenthesis") (kom-change-password . "Change password") (kom-change-supervisor . "Change supervisor") (kom-change-presentation . "Change presentation") (kom-get-appreciation . "(Please) pat my head") (kom-get-abuse . "(Please) kick my butt") (kom-mark-text . "Mark (text)") (kom-unmark-text . "Unmark (text)") (kom-review-marked-texts . "Review marked (texts)") (kom-review-all-marked-texts . "Review all marked (texts)") (kom-add-recipient . "Add recipient") (kom-add-copy . "Add (recipient of) carbon copy") (kom-add-bcc . "Add (recipient of) blind carbon copy") (kom-sub-recipient . "Remove recipient") (kom-move-text . "Move text") (kom-move-text-tree . "Move tree") (kom-add-comment . "Add comment") (kom-sub-comment . "Remove comment") (kom-add-cross-reference . "Add cross reference") (kom-add-member . "Add (a) member") (kom-sub-member . "Remove (a) member") (kom-change-conf-motd . "(Post) notice (on the) conference") (kom-set-garb-nice . "Change expiration") (kom-set-super-conf . "Change superconference") (kom-set-permitted-submitters . "Change allowed authors") (kom-unset-conf-motd . "Remove notice") (kom-save-text . "Archive (copy of) text (in file)") (kom-save-text-body . "Save text body (in file)") (kom-save-options . "Save options") (kom-shutdown-server . "Shut down (server)") (kom-sync-database . "Save (the) database") (kom-enable-adm-caps . "Become administrator") (kom-disable-adm-caps . "Become (normal) user") (kom-set-motd . "Change login message") (kom-remove-motd . "Remove login message") (kom-force-logout . "Kill session") (kom-filter-author . "Filter author") (kom-filter-subject . "Filter subject") (kom-filter-recipient . "Filter recipient") (kom-super-jump . "Super jump") (kom-filter-edit . "Edit filters") (kom-filter-text . "Filter contents") (kom-list-filters . "List filters") (kom-show-user-area . "Show user area") (kom-change-conf-type . "Change conference type") (kom-change-auto-reply . "Change ansaphone message") (kom-toggle-auto-reply . "Ansaphone") (kom-list-messages . "List messages") (kom-erase-messages . "Erase messages") (kom-remote-autoreply . "Remote control ansaphone") (kom-remote-set-message . "Remote control change ansaphone message") (kom-remote-list-messages . "Remote control list messages") (kom-remote-erase-messages . "Remote control erase messages") (kom-remote-quit . "Remote control quit") (kom-status-session . "Status (of) session") (kom-customize . "Customize LysKOM") (kom-next-kom . "Next LysKOM") (kom-previous-kom . "Previous LysKOM") (kom-next-unread-kom . "Next unread LysKOM") (kom-change-language . "Change language") (kom-calculate . "Calculate") (kom-list-marks . "List marked texts") (kom-where-is . "Where (is the) command") (kom-fast-reply . "Remark (to text)") (kom-agree . "Agree") (kom-add-faq . "Add FAQ") (kom-del-faq . "Remove FAQ") (kom-review-faq . "View FAQ") (kom-sub-footnote . "Remove footnote") (kom-add-footnote . "Add footnote") (kom-add-no-comments . "Prevent comments") (kom-add-private-answer . "Request private reply") (kom-add-request-confirm . "Request confirmation of reading") (kom-review-mail-headers . "Review mail headers") (kom-compare-texts . "Compare two texts") (kom-diff-texts . "View diff") (kom-become-anonymous . "Become anonymous") (kom-become-nonanonymous . "Become non-anonymous (come forth into the light)") (kom-keep-alive . "Keep connection alive") (kom-stop-keep-alive . "Stop keeping connection alive") (kom-is-person-member-of-conference . "Check (if person is a) member (of conference)") (kom-will-person-read-text . "Check (if person will) read (text)") (kom-change-conf-faq . "Change FAQ") (kom-make-review-mark-as-read . "Review marks as read") (kom-make-review-not-mark-as-read . "Review does not mark as read") (kom-set-presentation . "Add presentation") (kom-remove-presentation . "Remove presentation") (kom-set-motd-text . "Add notice") (kom-create-aux-item . "Create propoerty") (kom-status-server . "Status (of) server") (kom-add-server-faq . "Add server FAQ") (kom-del-server-faq . "Remove server FAQ") (kom-review-server-faq . "Review server FAQ") (kom-change-server-faq . "Change server FAQ") (kom-recommend-conference . "Recommend conference") (kom-redirect-comments . "Redirect comments") (kom-copy-options . "Copy options") (kom-mark-unread . "Unread text") (kom-unread-by-to . "Unread last") (kom-unread-more . "Unread more") (kom-unread-commented-text . "Unread (the) commented (text)") (kom-unread-previous-commented-text . "Unread (the) previously commented (text)") (kom-unread-comments . "Unread all comments") (kom-unread-tree . "Unread all comments recursively") (kom-unread-root . "Unread original (text)") (kom-unread-root-review . "Unread tree") (kom-unread-last-normally-read . "Unread again") (kom-unread-first . "Unread first") (kom-unread-all . "Unread all") (kom-unread-presentation . "Unread presentation") (kom-unread-server-faq . "Unread server FAQ") (kom-unread-faq . "Unread FAQ") (kom-unread-marked-texts . "Unread marked (texts)") (kom-unread-all-marked-texts . "Unread all markeed (texts)") (kom-join-all-conferences . "Join all conferences") (kom-leave-all-conferences . "Leave (almost) all conferences") (kom-limit-import . "Limit imported texts") (kom-change-message-flag . "Change reception (of) group messages") (kom-list-faqs . "List FAQs") (kom-list-server-faqs . "List server-FAQs") (kom-list-new-conferences . "List new conferences") (kom-list-new-persons . "List new users") (kom-change-privileges . "Change privileges") )) (lyskom-language-var global lyskom-language-codes en '((aa . "Afar") (ab . "Abkhazian") (af . "Afrikaans") (am . "Amharic") (ar . "Arabic") (as . "Assamese") (ay . "Aymara") (az . "Azerbaijani") (ba . "Bashkir") (be . "Byelorussian") (bg . "Bulgarian") (bh . "Bihari") (bi . "Bislama") (bn . "Bengali") (bo . "Tibetan") (br . "Breton") (ca . "Catalan") (co . "Corsican") (cs . "Czech") (cy . "Welsh") (da . "Danish") (de . "German") (dz . "Bhutani") (el . "Greek") (en . "English") (eo . "Esperanto") (es . "Spanish") (et . "Estonian") (eu . "Basque") (fa . "Persian") (fi . "Finnish") (fj . "Fiji") (fo . "Faroese") (fr . "French") (fy . "Frisian") (ga . "Irish") (gd . "Scots Gaelic") (gl . "Galician") (gn . "Guarani") (gu . "Gujarati") (ha . "Hausa") (he . "Hebrew") (hi . "Hindi") (hr . "Croatian") (hu . "Hungarian") (hy . "Armenian") (ia . "Interlingua") (id . "Indonesian") (ie . "Interlingue") (ik . "Inupiak") (is . "Icelandic") (it . "Italian") (iu . "Inuktitut") (ja . "Japanese") (jw . "Javanese") (ka . "Georgian") (kk . "Kazakh") (kl . "Greenlandic") (km . "Cambodian") (kn . "Kannada") (ko . "Korean") (ks . "Kashmiri") (ku . "Kurdish") (ky . "Kirghiz") (la . "Latin") (ln . "Lingala") (lo . "Laotian") (lt . "Lithuanian") (lv . "Latvian Lettish") (mg . "Malagasy") (mi . "Maori") (mk . "Macedonian") (ml . "Malayalam") (mn . "Mongolian") (mo . "Moldavian") (mr . "Marathi") (ms . "Malay") (mt . "Maltese") (my . "Burmese") (na . "Nauru") (ne . "Nepali") (nl . "Dutch") (no . "Norwegian") (oc . "Occitan") (om . "Oromo") (or . "Oriya") (pa . "Pundjabi") (pl . "Polish") (ps . "Pashto") (pt . "Portuguese") (qu . "Quechua") (rm . "Rhaeto-Romance") (rn . "Kirundi") (ro . "Romanian") (ru . "Russian") (rw . "Kiyarwanda") (sa . "Sanskrit") (sd . "Sindhi") (sg . "Sangho") (sh . "Serbo-Croatian") (si . "Singhalese") (sk . "Slovak") (sl . "Slovenian") (sm . "Samoan") (sn . "Shona") (so . "Somali") (sq . "Albanian") (sr . "Serbian") (ss . "Siswati") (st . "Sesotho") (su . "Sudanese") (sv . "Swedish") (sw . "Swahili") (ta . "Tamil") (te . "Telugu") (tg . "Tajik") (th . "Thai") (ti . "Tigrinya") (tk . "Turkmen") (tl . "Tagalog") (tn . "Setswana") (to . "Tonga") (tr . "Turkish") (ts . "Tsonga") (tt . "Tatar") (tw . "Twi") (ug . "Uigur") (uk . "Ukrainian") (ur . "Urdu") (uz . "Uzbek") (vi . "Vietnamese") (vo . "Volapük") (wo . "Wolof") (xh . "Xhosa") (yi . "Yiddish") (yo . "Yorouba") (za . "Zhuang") (zh . "Chinese") (zu . "Zulu") (-- . "Unknown language (%#1s)"))) (lyskom-language-missing-string lyskom-menu kom-help en) (lyskom-language-missing-string lyskom-menu kom-change-language en) (lyskom-language-strings global lyskom-menu en '((lyskom . "LysKOM") (read . "Read") (dont-read . "Jump") (write . "Write") (conference . "Conference") (other . "Other") (person . "User") (server . "Server") (marks . "Marks") (filters . "Filters") (move . "Go") (info . "About") (send . "Send message") (review . "Review") (unread . "Unread") (receivers . "Receivers") (commented . "Commented") (aux-items . "Properties") (conf-admin . "Conference admin") (server-admin . "Server admin") (membership . "Membership") (pers-admin . "User admin") (autoreply . "Auto-reply") (remote-control . "Remote control") (language . "Change language") (kom-change-global-language . "Display and commands") (kom-change-local-language . "Display language only") (kom-edit-send . "Send") (kom-edit-send-anonymous . "Send anonymously") (kom-edit-quit . "Throw away") (kom-ispell-message . "Check spelling") (kom-edit-add-recipient . "Add recipient") (kom-edit-add-copy . "Add carbon copy") (kom-edit-show-commented . "Review commented") (kom-edit-insert-commented . "Cite commented") (kom-edit-insert-buglist . "Paste commented bug list") (kom-edit-add-bcc . "Add blind carbon copy") (kom-edit-add-cross-reference . "Add cross reference") (kom-edit-add-no-comments . "Request no comments") (kom-edit-add-personal-comments . "Request personal replies") (kom-edit-add-read-confirm-request . "Request read confirmation") (kom-edit-move-text . "Move to new recipient") (lp--toggle-membership-selection . "Toggle membership selection") (lp--select-region . "Select region") (lp--select-priority . "Select priority") (lp--deselect-priority . "Deselect priority") (lp--deselect-all . "Deselect all") (lp--membership-expansion . "Membership expansion") (lp--toggle-entry-expansion . "Toggle expansion") (lp--expand-entry . "Expand membership") (lp--contract-entry . "Contract membership") (lp--membership-priority . "Priority") (lp--set-priority . "Change priority") (lp--move-up . "Move up") (lp--move-down . "Move down") (lp--increase-priority . "Increase priority") (lp--decrease-priority . "Lower priority") (lp--yank . "Move selected") (lp--filter . "Filter") (lp--show-hide-memberships-read-before . "Toggle display of memberships read before...") (lp--show-hide-memberships-read-after . "Toggle display of memberships read after...") (lp--show-hide-read-memberships . "Toggle display of memberships without unreads") (lp--show-hide-passive-memberships . "Toggle display of passive memberships") (lp--show-all . "Show all memberships") (lp--membership-type . "Membership type") (lp--toggle-invitation . "Toggle invitation") (lp--toggle-passive . "Toggle passive") (lp--toggle-message-flag . "Toggle messages") (lp--toggle-secret . "Toggle secret") (lp--set-unread . "Only last") (lp--quit . "Quit") )) (lyskom-language-var local lyskom-onoff-table en '(("on" . on) ("off" . off))) (lyskom-language-var local lyskom-filter-predicate-list en '(("=" . nil) ("!=" . t))) (lyskom-language-var local lyskom-filter-what en '((author . "Author") (author-no . "Author (number)") (author-re . "Author (regexp)") (subject . "Subject") (subject-re . "Subject (regexp)") (recipient . "Recipient") (recipient-no . "Recipient (number)") (recipient-re . "Recipient (regexp)") (text . "Contents") (text-re . "Contents (regexp)"))) (lyskom-language-var local lyskom-filter-actions en '((skip-text . "Skip") (dontshow . "Don't show") (read . "Exclude from filter") (skip-tree . "Skip comments") (obliterate . "Obliterate"))) (defconst lyskom-keybindings-missing nil) (defvar lyskom-en-mode-map nil) (lyskom-language-keymap lyskom-mode-map en lyskom-en-mode-map) (defvar lyskom-en-review-prefix) (defvar lyskom-en-change-prefix) (defvar lyskom-en-next-prefix) (defvar lyskom-en-list-prefix) (defvar lyskom-en-filter-get-prefix) (defvar lyskom-en-S-prefix) (defvar lyskom-en-who-prefix) (defvar lyskom-en-A-prefix) (defvar lyskom-en-B-prefix) (defvar lyskom-en-unread-prefix) (if lyskom-en-mode-map nil (setq lyskom-en-mode-map (make-keymap)) (suppress-keymap lyskom-en-mode-map) (define-prefix-command 'lyskom-en-review-prefix) (define-prefix-command 'lyskom-en-change-prefix) (define-prefix-command 'lyskom-en-next-prefix) (define-prefix-command 'lyskom-en-list-prefix) (define-prefix-command 'lyskom-en-filter-get-prefix) (define-prefix-command 'lyskom-en-S-prefix) (define-prefix-command 'lyskom-en-who-prefix) (define-prefix-command 'lyskom-en-A-prefix) (define-prefix-command 'lyskom-en-B-prefix) (define-prefix-command 'lyskom-en-unread-prefix) (define-key lyskom-en-mode-map (kbd "h") 'lyskom-en-change-prefix) (define-key lyskom-en-mode-map (kbd "r") 'lyskom-en-review-prefix) (define-key lyskom-en-mode-map (kbd "f") 'lyskom-en-filter-get-prefix) (define-key lyskom-en-mode-map (kbd "n") 'lyskom-en-next-prefix) (define-key lyskom-en-mode-map (kbd "l") 'lyskom-en-list-prefix) (define-key lyskom-en-mode-map (kbd "s") 'lyskom-en-S-prefix) (define-key lyskom-en-mode-map (kbd "w") 'lyskom-en-who-prefix) (define-key lyskom-en-mode-map (kbd "a") 'lyskom-en-A-prefix) (define-key lyskom-en-mode-map (kbd "b") 'lyskom-en-B-prefix) (define-key lyskom-en-mode-map (kbd "u") 'lyskom-en-unread-prefix) (define-key lyskom-en-mode-map (kbd "M-m") 'kom-toggle-mark-as-read-prefix) (define-key lyskom-en-mode-map (kbd "M-c") 'kom-toggle-cache-prefix) (define-key lyskom-en-mode-map (kbd (lyskom-keys 'button2)) 'kom-button-click) (define-key lyskom-en-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-en-mode-map (kbd (lyskom-keys 'button2up)) 'kom-mouse-null) (define-key lyskom-en-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-en-mode-map (kbd "*") 'kom-button-press) (define-key lyskom-en-mode-map (kbd "=") 'kom-menu-button-press) (define-key lyskom-en-mode-map (kbd "TAB") 'kom-next-link) (define-key lyskom-en-mode-map (kbd "M-TAB") 'kom-previous-link) (define-key lyskom-en-mode-map (kbd "") 'kom-previous-link) ;; These should be first in order to be last in the menu of alternatives. (define-key lyskom-en-review-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-unread-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-change-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-next-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-list-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-filter-get-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-S-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-who-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-A-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-mode-map (kbd "o") 'kom-set-unread) (define-key lyskom-en-mode-map (kbd "x") 'kom-extended-command) (define-key lyskom-en-mode-map (kbd "") 'kom-next-command) (define-key lyskom-en-mode-map (kbd "") 'kom-page-next-command) (define-key lyskom-en-mode-map (kbd "") 'kom-line-next-command) (define-key lyskom-en-mode-map (kbd "?") 'kom-help) (define-key lyskom-en-mode-map (kbd "e") 'kom-send-letter) (define-key lyskom-en-mode-map (kbd "g") 'kom-go-to-conf) (define-key lyskom-en-mode-map (kbd "t") 'kom-write-text) (define-key lyskom-en-mode-map (kbd "c") 'kom-write-comment) (define-key lyskom-en-mode-map (kbd "C") 'kom-comment-previous) (define-key lyskom-en-mode-map (kbd "F") 'kom-write-footnote) (define-key lyskom-en-mode-map (kbd "p") 'kom-private-answer) (define-key lyskom-en-mode-map (kbd "P") 'kom-private-answer-previous) (define-key lyskom-en-mode-map (kbd "j") 'kom-jump) (define-key lyskom-en-mode-map (kbd "J") 'kom-super-jump) (define-key lyskom-en-mode-map (kbd "I") 'kom-who-am-i) (define-key lyskom-en-mode-map (kbd "W") 'kom-busy-wait) (define-key lyskom-en-mode-map (kbd "m") 'kom-add-self) (define-key lyskom-en-mode-map (kbd "M") 'kom-mark-text) (define-key lyskom-en-mode-map (kbd "U") 'kom-unmark-text) (define-key lyskom-en-mode-map (kbd "q") 'kom-quit) (define-key lyskom-en-mode-map (kbd "z") 'kom-bury) (define-key lyskom-en-mode-map (kbd "R") 'kom-recover) (define-key lyskom-en-mode-map (kbd "T") 'kom-display-time) (define-key lyskom-en-list-prefix (kbd "k") 'kom-list-sessions) (define-key lyskom-en-list-prefix (kbd "m") 'kom-list-marks) (define-key lyskom-en-list-prefix (kbd "c") 'kom-list-conferences) (define-key lyskom-en-list-prefix (kbd "n") 'kom-list-news) (define-key lyskom-en-list-prefix (kbd "u") 'kom-list-persons) (define-key lyskom-en-list-prefix (kbd "r") 'kom-list-re) (define-key lyskom-en-list-prefix (kbd "M") 'kom-membership) (define-key lyskom-en-list-prefix (kbd "s") 'kom-list-summary) (define-key lyskom-en-list-prefix (kbd "f") 'kom-list-filters) (define-key lyskom-en-list-prefix (kbd "q") 'kom-list-faqs) (define-key lyskom-en-list-prefix (kbd "Q") 'kom-list-server-faqs) (define-key lyskom-en-next-prefix (kbd "t") 'kom-view-next-new-text) (define-key lyskom-en-next-prefix (kbd "c") 'kom-go-to-next-conf) (define-key lyskom-en-next-prefix (kbd "l") 'kom-next-kom) (define-key lyskom-en-next-prefix (kbd "u") 'kom-next-unread-kom) (define-key lyskom-en-filter-get-prefix (kbd "p") 'kom-get-appreciation) (define-key lyskom-en-filter-get-prefix (kbd "k") 'kom-get-abuse) (define-key lyskom-en-filter-get-prefix (kbd "s") 'kom-filter-subject) (define-key lyskom-en-filter-get-prefix (kbd "a") 'kom-filter-author) (define-key lyskom-en-filter-get-prefix (kbd "c") 'kom-filter-text) (define-key lyskom-en-filter-get-prefix (kbd "r") 'kom-filter-recipient) (define-key lyskom-en-who-prefix (kbd "w") 'kom-who-is-on) (define-key lyskom-en-who-prefix (kbd "c") 'kom-who-is-on-in-conference) (define-key lyskom-en-who-prefix (kbd "p") 'kom-who-is-present-in-conference) (define-key lyskom-en-who-prefix (kbd "f") 'kom-who-is-on-and-friend) (define-key lyskom-en-change-prefix (kbd "p") 'kom-change-presentation) (define-key lyskom-en-change-prefix (kbd "q") 'kom-change-conf-faq) (define-key lyskom-en-change-prefix (kbd "f") 'kom-filter-edit) (define-key lyskom-en-change-prefix (kbd "m") 'kom-change-auto-reply) (define-key lyskom-en-change-prefix (kbd "t") 'kom-move-text) (define-key lyskom-en-change-prefix (kbd "T") 'kom-move-text-tree) (define-key lyskom-en-unread-prefix (kbd "SPC") 'kom-mark-unread) (define-key lyskom-en-unread-prefix (kbd "0") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "1") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "2") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "3") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "4") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "5") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "6") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "7") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "8") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "9") 'kom-initial-digit-unread) (define-key lyskom-en-unread-prefix (kbd "c") 'kom-unread-commented-text) (define-key lyskom-en-unread-prefix (kbd "C") 'kom-unread-previous-commented-text) (define-key lyskom-en-unread-prefix (kbd "a ?") 'lyskom-help) (define-key lyskom-en-unread-prefix (kbd "a c") 'kom-unread-comments) (define-key lyskom-en-unread-prefix (kbd "a r") 'kom-unread-tree) (define-key lyskom-en-unread-prefix (kbd "g") 'kom-unread-last-normally-read) (define-key lyskom-en-unread-prefix (kbd "o") 'kom-unread-root) (define-key lyskom-en-unread-prefix (kbd "l") 'kom-unread-by-to) (define-key lyskom-en-unread-prefix (kbd "M") 'kom-unread-more) (define-key lyskom-en-unread-prefix (kbd "r") 'kom-unread-root-review) (define-key lyskom-en-unread-prefix (kbd "f") 'kom-unread-first) (define-key lyskom-en-unread-prefix (kbd "A") 'kom-unread-all) (define-key lyskom-en-unread-prefix (kbd "f") 'kom-unread-first) (define-key lyskom-en-unread-prefix (kbd "p") 'kom-unread-presentation) (define-key lyskom-en-unread-prefix (kbd "q") 'kom-unread-faq) (define-key lyskom-en-unread-prefix (kbd "Q") 'kom-unread-server-faq) (define-key lyskom-en-unread-prefix (kbd "m") 'kom-unread-marked-texts) (define-key lyskom-en-unread-prefix (kbd "a m") 'kom-unread-all-marked-texts) (define-key lyskom-en-unread-prefix (kbd "a SPC") 'kom-unread-all) (define-key lyskom-en-review-prefix (kbd "SPC") 'kom-view) (define-key lyskom-en-review-prefix (kbd "0") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "1") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "2") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "3") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "4") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "5") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "6") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "7") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "8") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "9") 'kom-initial-digit-view) (define-key lyskom-en-review-prefix (kbd "b") 'kom-review-backward) (define-key lyskom-en-review-prefix (kbd "c") 'kom-view-commented-text) (define-key lyskom-en-review-prefix (kbd "C") 'kom-view-previous-commented-text) (define-key lyskom-en-review-prefix (kbd "a ?") 'lyskom-help) (define-key lyskom-en-review-prefix (kbd "a c") 'kom-review-comments) (define-key lyskom-en-review-prefix (kbd "a r") 'kom-review-tree) (define-key lyskom-en-review-prefix (kbd "a x") 'kom-review-cross-references) (define-key lyskom-en-review-prefix (kbd "j") 'kom-review-clear) (define-key lyskom-en-review-prefix (kbd "n") 'kom-review-next) (define-key lyskom-en-review-prefix (kbd "u") 'kom-review-noconversion) (define-key lyskom-en-review-prefix (kbd "v") 'kom-review-converted) (define-key lyskom-en-review-prefix (kbd "3") 'kom-review-rot13) (define-key lyskom-en-review-prefix (kbd "o") 'kom-find-root) (define-key lyskom-en-review-prefix (kbd "l") 'kom-review-by-to) (define-key lyskom-en-review-prefix (kbd "f") 'kom-review-first) (define-key lyskom-en-review-prefix (kbd "A") 'kom-review-all) (define-key lyskom-en-review-prefix (kbd "M") 'kom-review-more) (define-key lyskom-en-review-prefix (kbd "g") 'kom-review-last-normally-read) (define-key lyskom-en-review-prefix (kbd "q") 'kom-review-faq) (define-key lyskom-en-review-prefix (kbd "Q") 'kom-review-server-faq) (define-key lyskom-en-review-prefix (kbd "s") 'kom-review-stack) (define-key lyskom-en-review-prefix (kbd "p") 'kom-review-presentation) (define-key lyskom-en-review-prefix (kbd "r") 'kom-find-root-review) (define-key lyskom-en-review-prefix (kbd "m") 'kom-review-marked-texts) (define-key lyskom-en-review-prefix (kbd "a m") 'kom-review-all-marked-texts) (define-key lyskom-en-review-prefix (kbd "a SPC") 'kom-review-all) (define-key lyskom-en-review-prefix (kbd "x a") 'kom-agree) (define-key lyskom-en-review-prefix (kbd "x q") 'kom-fast-reply) (define-key lyskom-en-review-prefix (kbd "h") 'kom-review-mail-headers) (define-key lyskom-en-S-prefix (kbd "c") 'kom-status-conf) (define-key lyskom-en-S-prefix (kbd "p") 'kom-status-person) (define-key lyskom-en-S-prefix (kbd "s") 'kom-status-session) (define-key lyskom-en-S-prefix (kbd "k") 'kom-status-server) (define-key lyskom-en-S-prefix (kbd "m") 'kom-send-message) (define-key lyskom-en-S-prefix (kbd "u m") 'kom-sub-recipient) (define-key lyskom-en-S-prefix (kbd "u k") 'kom-sub-comment) (define-key lyskom-en-S-prefix (kbd "u q") 'kom-del-faq) (define-key lyskom-en-S-prefix (kbd "u f") 'kom-sub-footnote) (define-key lyskom-en-S-prefix (kbd "u ?") 'lyskom-help) (define-key lyskom-en-A-prefix (kbd "?") 'lyskom-help) (define-key lyskom-en-A-prefix (kbd "m") 'kom-add-recipient) (define-key lyskom-en-A-prefix (kbd "e") 'kom-add-copy) (define-key lyskom-en-A-prefix (kbd "d") 'kom-add-bcc) (define-key lyskom-en-A-prefix (kbd "k") 'kom-add-comment) (define-key lyskom-en-A-prefix (kbd "r") 'kom-add-cross-reference) (define-key lyskom-en-A-prefix (kbd "q") 'kom-add-faq) (define-key lyskom-en-A-prefix (kbd "f") 'kom-add-footnote) (define-key lyskom-en-A-prefix (kbd "Q") 'kom-add-server-faq) (define-key lyskom-en-B-prefix (kbd "l") 'kom-previous-kom) ;; Running in) buffer (define-key lyskom-en-mode-map (kbd "M-p") 'backward-text) (define-key lyskom-en-mode-map (kbd "M-n") 'forward-text) (define-key lyskom-en-mode-map (kbd "C-M-p") 'kom-prev-prompt) (define-key lyskom-en-mode-map (kbd "C-M-n") 'kom-next-prompt) (define-key lyskom-en-mode-map (kbd "s a") 'kom-save-text) (define-key lyskom-en-mode-map (kbd "C-?") 'scroll-down) (define-key lyskom-en-mode-map (kbd "") 'scroll-down) (define-key lyskom-en-mode-map (kbd "") 'scroll-down) (define-key lyskom-en-mode-map (kbd "") 'scroll-down) (define-key lyskom-en-mode-map (kbd "<") 'beginning-of-buffer) (define-key lyskom-en-mode-map (kbd ">") 'end-of-buffer) ) ;;; ================================================================ ;;; Prioritization (defvar lyskom-en-prioritize-mode-map nil "Keymap used in lyskom-prioritize-mode") (lyskom-language-keymap lyskom-prioritize-mode-map en lyskom-en-prioritize-mode-map) (if lyskom-en-prioritize-mode-map nil (setq lyskom-en-prioritize-mode-map (make-keymap)) (suppress-keymap lyskom-en-prioritize-mode-map) (define-key lyskom-en-prioritize-mode-map (kbd "SPC") 'lp--toggle-membership-selection) (define-key lyskom-en-prioritize-mode-map (kbd "C-k") 'lp--toggle-membership-selection) (define-key lyskom-en-prioritize-mode-map (kbd "p") 'lp--set-priority) (define-key lyskom-en-prioritize-mode-map (kbd "C-w") 'lp--select-region) (define-key lyskom-en-prioritize-mode-map (kbd "M-w") 'lp--select-region) (define-key lyskom-en-prioritize-mode-map (kbd "C-y") 'lp--yank) (define-key lyskom-en-prioritize-mode-map (kbd "#") 'lp--select-priority) (define-key lyskom-en-prioritize-mode-map (kbd "M-#") 'lp--deselect-priority) (define-key lyskom-en-prioritize-mode-map (kbd "M-DEL") 'lp--deselect-all) (define-key lyskom-en-prioritize-mode-map (kbd "C-p") 'lp--previous-entry) (define-key lyskom-en-prioritize-mode-map (kbd "") 'lp--previous-entry) (define-key lyskom-en-prioritize-mode-map (kbd "C-n") 'lp--next-entry) (define-key lyskom-en-prioritize-mode-map (kbd "") 'lp--next-entry) (define-key lyskom-en-prioritize-mode-map (kbd "") 'lp--first-entry) (define-key lyskom-en-prioritize-mode-map (kbd "") 'lp--last-entry) (define-key lyskom-en-prioritize-mode-map (kbd "M-<") 'lp--first-entry) (define-key lyskom-en-prioritize-mode-map (kbd "M->") 'lp--last-entry) (define-key lyskom-en-prioritize-mode-map (kbd "g") 'lp--goto-priority) (define-key lyskom-en-prioritize-mode-map (kbd "RET") 'lp--toggle-entry-expansion) (define-key lyskom-en-prioritize-mode-map (kbd "+") 'lp--increase-priority) (define-key lyskom-en-prioritize-mode-map (kbd "-") 'lp--decrease-priority) (define-key lyskom-en-prioritize-mode-map (kbd "M-p") 'lp--move-up) (define-key lyskom-en-prioritize-mode-map (kbd "M-n") 'lp--move-down) (define-key lyskom-en-prioritize-mode-map (kbd "M-") 'lp--move-up) (define-key lyskom-en-prioritize-mode-map (kbd "M-") 'lp--move-down) (define-key lyskom-en-prioritize-mode-map (kbd "I") 'lp--toggle-invitation) (define-key lyskom-en-prioritize-mode-map (kbd "H") 'lp--toggle-secret) (define-key lyskom-en-prioritize-mode-map (kbd "P") 'lp--toggle-passive) (define-key lyskom-en-prioritize-mode-map (kbd "M") 'lp--toggle-message-flag) (define-key lyskom-en-prioritize-mode-map (kbd "o") 'lp--set-unread) (define-key lyskom-en-prioritize-mode-map (kbd "P") 'lp--postpone) (define-key lyskom-en-prioritize-mode-map (kbd "C-c C-c") 'lp--quit) (define-key lyskom-en-prioritize-mode-map (kbd "q") 'lp--quit) (define-key lyskom-en-prioritize-mode-map (kbd "(") 'lp--expand-entry) (define-key lyskom-en-prioritize-mode-map (kbd ")") 'lp--contract-entry) (define-key lyskom-en-prioritize-mode-map (kbd (lyskom-keys 'button2up)) 'kom-button-click) (define-key lyskom-en-prioritize-mode-map (kbd (lyskom-keys 'button2)) 'kom-mouse-null) (define-key lyskom-en-prioritize-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-en-prioritize-mode-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-en-prioritize-mode-map (kbd "*") 'kom-button-press) (define-key lyskom-en-prioritize-mode-map (kbd "=") 'kom-menu-button-press) (define-key lyskom-en-prioritize-mode-map (kbd "TAB") 'kom-next-link) (define-key lyskom-en-prioritize-mode-map (kbd "M-TAB") 'kom-previous-link) (define-key lyskom-en-prioritize-mode-map (kbd "C-i") 'kom-next-link) (define-key lyskom-en-prioritize-mode-map (kbd "M-C-i") 'kom-previous-link) ) ;;;============================================================== ;;; Keymap for filter editing ;;; (defvar lyskom-en-filter-edit-map nil) (lyskom-language-keymap lyskom-filter-edit-map en lyskom-en-filter-edit-map) (if lyskom-en-filter-edit-map () (setq lyskom-en-filter-edit-map (make-keymap)) (suppress-keymap lyskom-en-filter-edit-map) (define-prefix-command 'lyskom-en-filter-edit-prefix) (define-key lyskom-en-filter-edit-map (kbd "C-c") 'lyskom-en-filter-edit-prefix) (define-key lyskom-en-filter-edit-map (kbd "p") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-en-filter-edit-map (kbd "P") 'lyskom-filter-edit-prev-entry) (define-key lyskom-en-filter-edit-map (kbd "n") 'lyskom-filter-edit-next-pattern) (define-key lyskom-en-filter-edit-map (kbd "N") 'lyskom-filter-edit-next-entry) (define-key lyskom-en-filter-edit-map (kbd "C-p") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-en-filter-edit-map (kbd "C-n") 'lyskom-filter-edit-next-pattern) (define-key lyskom-en-filter-edit-map (kbd "C-b") 'lyskom-filter-edit-prev-pattern) (define-key lyskom-en-filter-edit-map (kbd "C-f") 'lyskom-filter-edit-next-pattern) (define-key lyskom-en-filter-edit-map (kbd "M-p") 'lyskom-filter-edit-prev-entry) (define-key lyskom-en-filter-edit-map (kbd "M-n") 'lyskom-filter-edit-next-entry) (define-key lyskom-en-filter-edit-map (kbd "d") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-en-filter-edit-map (kbd "M-d") 'lyskom-filter-edit-delete-entry) (define-key lyskom-en-filter-edit-map (kbd "D") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-en-filter-edit-map (kbd "C-d") 'lyskom-filter-edit-delete-pattern) (define-key lyskom-en-filter-edit-map (kbd "i") 'lyskom-filter-edit-insert-pattern) (define-key lyskom-en-filter-edit-map (kbd "I") 'lyskom-filter-edit-insert-pattern) (define-key lyskom-en-filter-edit-map (kbd "M-i") 'lyskom-filter-edit-insert-entry) (define-key lyskom-en-filter-edit-map (kbd "<") 'lyskom-filter-edit-beginning-of-list) (define-key lyskom-en-filter-edit-map (kbd ">") 'lyskom-filter-edit-end-of-list) (define-key lyskom-en-filter-edit-map (kbd "M-<") 'lyskom-filter-edit-beginning-of-list) (define-key lyskom-en-filter-edit-map (kbd "M->") 'lyskom-filter-edit-end-of-list) (define-key lyskom-en-filter-edit-map (kbd "q") 'lyskom-filter-edit-quit) (define-key lyskom-en-filter-edit-map (kbd "C-c C-c") 'lyskom-filter-edit-quit) (define-key lyskom-en-filter-edit-map (kbd "x") 'lyskom-filter-edit-expunge) (define-key lyskom-en-filter-edit-map (kbd "s") 'lyskom-filter-edit-save) (define-key lyskom-en-filter-edit-map (kbd "g") 'lyskom-filter-edit-revert) (define-key lyskom-en-filter-edit-map (kbd "t") 'lyskom-filter-edit-toggle-permanent) (define-key lyskom-en-filter-edit-map (kbd "a") 'lyskom-filter-edit-toggle-action) (define-key lyskom-en-filter-edit-map (kbd "?") 'lyskom-filter-edit-brief-help) (define-key lyskom-en-filter-edit-map (kbd "h") 'lyskom-filter-edit-brief-help) ) ;;;; ============================================================ ;;;; Strings and things for the customize mode ;;;; (defvar lyskom-en-customize-map nil) (lyskom-language-keymap lyskom-customize-map en lyskom-en-customize-map) (if lyskom-en-customize-map nil (setq lyskom-en-customize-map (make-sparse-keymap)) (define-key lyskom-en-customize-map (kbd "TAB") 'widget-forward) (define-key lyskom-en-customize-map (kbd "M-TAB") 'widget-backward) (define-key lyskom-en-customize-map (kbd "") 'widget-backward) (define-key lyskom-en-customize-map (kbd "C-i") 'widget-forward) (define-key lyskom-en-customize-map (kbd "M-C-i") 'widget-backward) (define-key lyskom-en-customize-map (kbd "C-m") 'widget-button-press) (define-key lyskom-en-customize-map (kbd "C-j") 'widget-button-press) (define-key lyskom-en-customize-map (kbd "") 'widget-button-press) (define-key lyskom-en-customize-map (kbd "") 'widget-button-press) (define-key lyskom-en-customize-map (kbd (lyskom-keys 'button2up)) 'kom-mouse-null) (define-key lyskom-en-customize-map (kbd (lyskom-keys 'button3up)) 'kom-mouse-null) (define-key lyskom-en-customize-map (kbd (lyskom-keys 'button2)) 'widget-button-click) (define-key lyskom-en-customize-map (kbd (lyskom-keys 'button3)) 'lyskom-widget-click) (define-key lyskom-en-customize-map (kbd "C-c C-c") 'lyskom-customize-save-and-quit) (define-key lyskom-en-customize-map (kbd "C-c C-k") 'lyskom-customize-quit) (define-key lyskom-en-customize-map (kbd "C-c C-s") 'lyskom-customize-save) (define-key lyskom-en-customize-map (kbd "C-c C-a") 'lyskom-customize-apply) (define-key lyskom-en-customize-map (kbd "?") 'lyskom-customize-help) ) (lyskom-language-strings local lyskom-custom-strings en '( ;; ;; Widget strings ;; (which-person . "Specify person: ") (which-conf . "Specify a conference: ") (which-conf-or-person . "Specify a person or conference: ") (which-name . "Specify a name: ") (some-person . "Person %#1d") (invalid-value . "Invalid value (%#1S)") (unknown-command . "Unknown command (%#1s)") (ding . "Audio cue") ;; ;; Help messages ;; (variable-type-help . "Select to save the setting in the server.") (default-help-echo . "Change the value of %#1s.") (change-this-name . "Change the name in this entry.") (show-doc . "Show documentation.") (hide-doc . "Hide documentation.") (select-command . "Select a command.") (select-what-to-execute . "\ Select whether to execute command or keyboard macro.") (select-url-viewer . "Select a web browser.") (select-number . "Select number of times.") (select-audio-file . "Select an audio file.") (select-priority . "Select a priority.") (select-buffer . "Select a buffer name.") (select-buffer-size . "Select maximum buffer size.") ;; ;; Strings that are used in types and so forth ;; (buffer-name . "%#1s-configure") (other-window . "Some other window ") (other-frame . "Some other frame ") (new-frame . "In a new frame ") (lyskom-window . "The LysKOM buffer's window ") (window-on-buffer . "A window displaying the buffer") (on . "On ") (off . "Off") (yes . "Yes") (no . "No ") (to-file . "To file:") (max-text-length . "For texts shorter than: ") (autowrap-timeout . "Timeout in seconds: ") (no-timeout . "No timeout") (friends . "Friends and other special people") (turned-off . "Turned off ") (number-of-times . "A few times") (specific-spec . "Per recipient/sender") (sound-file . "Audio file") (other-persons . "All others") (selected-mark . "Mark ") (conf-or-person . "Person or conference") (ask . "Ask every time ") (limited-number . "A limited number") (unlimited-number . "Unlimited") (before . "Before the text") (after . "After the text") (depth-first . "In comment order") (time-order . "In time order") (ar-message-type . "Message type") (ar-personal . "Personal") (ar-group . "Group") (ar-alarm . "Alarm") (ar-any-type . "Any message type") (ar-sender . "Sender") (ar-any-sender . "Any sender") (ar-specified-sender . "Specified senders") (ar-pers-or-conf . "Person or conference") (ar-recipient . "Recipient") (ar-any-recipient . "Any recipient") (ar-specified-recipient . "Specified recipients") (ar-person . "Person") (ar-message-text . "Message text") (ar-any-message . "Any message") (ar-matching-regexp . "Matching regexp") (ar-reply . "Reply") (ar-no-reply . "No reply") (ar-reply-text . "Reply text") (express-break . "Immediately upon creation ") (break . "After current comment chain") (no-break . "After current conference ") (express-server-break . "Immediately") (express-server-letters-break . "Immediately if letters arrive") (server-break . "After current comment chain") (letters-server-break . "After current comment chain if letters arrive") (after-conf-server-break . "After current conference") (after-conf-letters-server-break . "After current conference if letters arrive") (when-done-server-break . "After everything has been read") (no-server-break . "Never") (command . "Command") (command-list . "Command list") (some-persons . "For some persons") (name . "Name") (page-none . "Never ") (page-all . "Before every command ") (page-some . "Before the following commands") (ask-every-time . "Ask every time ") (fixed-priority . "Fixed priority") (messages-in-lyskom-buffer . "In the LysKOM buffer") (discard-messages . "Nowhere - discard them") (in-named-buffer . "In a named buffer:") (automatic-session-name . "Automatic") (given-session-name . "Use specified:") (simple-unread-mode-line . "Simple") (explicit-unread-mode-line . "Show all sessions with unread") (everybody-rcpt . "Everybody ") (group-rcpt . "The recipient of the last group message ") (sender-rcpt . "The sender of the most recent message ") (last-recipient-recpt . "The last person I sent a message to") (viewer-program . "Web browser") (no-viewer . "(none selected)") (default-viewer . "Browse-URL (all)") (netscape-viewer . "Netscape/Mozilla (all)") (windows-viewer . "Windows default or Netscape/Mozilla (all)") (emacs-w3-viewer . "Emacs W3 mode (HTTP, Goper, FTP)") (emacs-general-viewer . "Emacs (FTP, Telnet, Mail)") (emacs-dired-viewer . "Emacs Dired (FTP)") (emacs-mail-viewer . "Emacs Mail mode (Mail)") (emacs-telnet-viewer . "Emacs Telnet mode (telnet)") (mosaic-viewer . "NCSA Mosaic (all)") (lynx-viewer . "Lynx (all)") (galeon-viewer . "Galeon (all)") (dont-check . "Don't ask for confirmation") (check-before-open . "Confirm before writing the text") (check-before-send . "Confirm before sending the text") (no-size-limit . "No limit") (max-size-in-bytes . "Fixed limit (in bytes)") (execute . "Execute") (kbd-macro . "Keyboard macro") (command . "Command") (enter-kbd-macro . "Enter a keybard macro. Finish with %#1s") (long-format . "Show help texts") (short-format . "Hide help texts") (truncate-threshold-lines . "Max lines") (first . "First") (last . "Last") (specific-placement . "Specific location") (priority . "Priority") (same-as-conf . "Same as current conference") (custom-format . "Custom format:") (default-format . "Standard format") (a-string . "A string:") (some-string . "A random string") (unspecified . "Unspecified") (symbolic-mark-association . "Association") (symbolic-mark-name . "Symbolic name: ") (mark-type-to-assoc . "Mark type to associate with: ") (prompt-for-text-no . "Prompt for text number") (all-others . "All others") (some-person . "Person") (format-html . "Format HTML:") (url-transform-regexp . "From (regexp):") (url-transform-newtext . " To:") (default-namedays . "Namedays for current language") (specific-namedays . "Specific name list") (several-name-lists . "Several name lists") (link-pattern-for . "Link patterns for") (all-conferences . "All recipients") (link-specific-rcpt . "Specific recipient") (link-pattern . "Link pattern") (link-replace . "Link substitution") (link-highlight-match . "Highlight group") (link-fold-case . "Case insensitive") (generated-face . "Automatic") (predefined-fonts . "Fonts intended for specific uses\n") (other-fonts . "Fonts with no specific uses\n") (other-face . "Other") (ext-simple-command . "Simple command") (ext-complex-command . "Command with arguments") (ext-complex-component . "Command/argument") (lynx-xterm . "Lynx in xterm") (lynx-emacs . "Lynx in emacs terminal-mode") (morons . "Morons and other \"special\" people") (friends . "Friends and other special people") (me . "Mig, myself and I") (i-am-supervisor . "Conferences i supervise") (has-no-presentation . "Conferences without presentations") (highlight-conferences . "Conferences:") (highlight-face . "Face:") (highlight-conflist . "Conference list") (yes-dont-pop . "Yes, but don't uniconify frames") (language . "Language") (specific-extended-info . "Only selected information") (extended-info-show . "Show:") (extended-info-type . "Information type:") (extended-server-info . "All extended server information") (extended-conf-info . "All extended conference information") (extended-pers-info . "All extended person information") (extended-read-faq-info . "Read FAQs") (extended-statistics-info . "Full server statistics") (extended-all-other-info . "Other information") ;; ;; Misc doc strings ;; (lyskom . "Configuration of LysKOM") (lyskom-doc . "\ These commands work outside editable text fields. \\[lyskom-customize-save-and-quit] to save and quit, \\[lyskom-customize-save-and-quit] to save and quit, \\[lyskom-customize-save] to save without quitting, \\[lyskom-customize-quit] to quit without saving. \\[widget-forward] moves to the next setting \\[widget-button-press] changes the value Press C-h m for a complete list of commands. Documentation: [?] Show documentation [!] Hide documentation Lists etc. : [INS] Add a line [DEL] Remove a line [*] Modify If the box before the name of the setting is selected, the setting will be saved in the server. Otherwise it will be saved in your .emacs. Click prompts with the middle mouse button to change values and bring up menus.") (section . "------------------------------------------------------------------------------\n") (look-and-feel-misc . "Look and feel\n") (window-locations . "Windows\n") (windows-where . "How are windows created:\n") (reading . "Reading\n") (writing . "Writing\n") (urls . "URL management\n") (personal-messages . "Personal messages\n") (remote-control . "Remote control of LysKOM\n") (hooks . "Hook functions\n") (audio-cues . "Audio cues\n") (audio-cues-when . "Issue audio cues when:\n") (automatic-replies . "Automatic replies\n") (new-window-netscape . "Open URLs in a new window") (new-tab-netscape . "Open URLs in a new tab") (default-netscape . "Open URLs wherever") (audio-cues-doc . "\ The following group of settings controls how LysKOM issues audio cues in various situations. The following options are available for each setting: Off No audio cue is issued A Few Times Emacs will beep one or more times. You have to specify how many times Emacs is to beep. Audio File Emacs will attempt to play the specified audio file. The program used to play the file is specified by another setting.") (sending-doc . "\ The following settings turn on or off certain checks that can be performed before sending a text to the server. The checks are designed to keep you from doing something stupid. Confirm multiple recipients If a text or comment has more than one recipient, LysKOM can ask which of the recipients are relevant. This can either be done before you start writing the text, in which case LysKOM will post a question for each recipient, or before sending the text to the server, in which case you may confirm all the recipients at once. It is also possible to turn this check off entirely. Check membership of commented author When on, LysKOM will check that the author of the comment you are writing is a member of at least one of the recipients of your comment. If not, LysKOM will offer to add the commented author as a recipient to the comment you are writing. Authors not to check A list of authors not to check even if check membership of commented author is on. Check for unread comments When this is on, LysKOM will check that you have read all the other comments to the text you are commenting before sending your comment to the server. This is supposed to help you avoid duplicating someone else's comment.") (windows-doc . "\ The following settings control how windows are created in LysKOM. The available options are: Some other window In another window, but in the same frame as LysKOM. If there only is one window in the frame, a new window will be created (and will be removed when you are finished). Some other frame In a different frame than the one LysKOM is in. If there only is one frame, a new one will be created (and will be removed when you are finished). In a new frame A new frame is created (and will be removed when you are finished). The LysKOM buffer's window The LysKOM buffer's window will be used. LysKOM will be restored to the window when you're finished. A window displaying the buffer If there is a window anywhere displaying the named buffer, that window will be used. This might be useful if you always have a particular buffer showing, but don't need it when executing some command.") ;; ;; Doc strings for variables ;; (kom-ansaphone-replies-doc . "\ This setting controls automatic replies in detail. You can set replies for specific senders, recipients and even message contents. If the message being replied to does not match any element in this list, the default auto reply message above is sent instead. For each pattern in the list you can set the required message type, sender the message must have, recipient the message must have, a regular expression the message must match and the reply to send. It is advisable to configure the client not to send a message to any group or alarm message.") (kom-bury-buffers-doc . "\ Controls how the LysKOM buffer is handled when moving to another KOM buffer with the Next and Previous LysKOM commands. When turned on the current buffer is buried.") (kom-personal-messages-in-window-doc . "\ Controls which window is used to display the buffer with personal messages. For this setting to have any effect, personal messages must be displayed in a separate buffer, and that buffer must be displayed automatically every time a message is received.") (kom-write-texts-in-window-doc . "\ Controls which window is used to write new texts.") (kom-prioritize-in-window-doc . "\ Controls which window is used to prioritize conferences.") (kom-edit-filters-in-window-doc . "\ Controls which window is used for editing filters.") (kom-customize-in-window-doc . "\ Controls which window is used to configure LysKOM.") (kom-view-commented-in-window-doc . "\ Controls which window is used to show the commented text when commenting.") (kom-list-membership-in-window-doc . "\ Controls in which window your membership list is shown.") (kom-user-prompt-format-doc . "\ The format of the LysKOM prompt. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-user-prompt-format-executing-doc . "\ The format of the LysKOM prompt when the default command is executing. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-anonymous-prompt-format-doc . "\ The format of the LysKOM prompt used when anonymous. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-anonymous-prompt-format-executing-doc . "\ The format of the LysKOM prompt when the default command is executing and the session is anonymous. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-enabled-prompt-format-doc . "\ The format of the LysKOM prompt when in administrator mode. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-enabled-prompt-format-executing-doc . "\ The format of the LysKOM prompt when the default command is executing and the session is in administrator mode. Certain control sequences cause special text to be inserted: %c - Inserts the current default command. %[ - Inserts `[' if the ansaphone is on. %] - Inserts `]' is the ansaphone is on. %m - Inserts information about recorded messages. %s - Inserts the name of the LysKOM system %S - Inserts the server name. %p - Inserts the name of the user currently logged on. %w - Inserts the name of the current conference. %a - Inserts `anonymous' %A - Inserts `Anonymous' %# - Inserts the current session number. % - Inserts a space if it seems necessary. %% - Inserts a percent sign. Here are a few examples: \"%[%c% %m%] - \" The default prompt \"%[%s: %c% %m%] - \" Could display \"LysKOM: Time - \"") (kom-cite-string-doc . "\ A string that is inserted before each line in a cited text. Normally this is set to something like \"> \". Note that it is not customary to cite commented texts the way it is done in e-mail or Usenet News since the commented text is always available in LysKOM.") (kom-created-texts-are-read-doc . "\ When this is on, self-created texts are automatically marked as read. Turned off, those texts are presented as any other texts.") (kom-default-mark-doc . "\ The default mark type used for marking texts. A mark type is an integer between 0 and 255 (inclusive). If no default mark type is selected, LysKOM asks for a mark type every time a text is to be marked. This can be used to separate different types of marks. You can, for example, mark texts which contain valuable information with a certain integer and texts which you should remember to comment some time with another integer.") (kom-symbolic-marks-alist-doc . "\ To avoid having to memorize what the integer mark types are supposed to mean, you can define a list of symbolic mark types. A symbolic mark type is a descriptive string that is associated with an integer mark type.") (kom-reading-puts-comments-in-pointers-last-doc . "\ Controls if comment links are listed before or after the body of a text. Normally comment links are listed after the text. Before: 398331 1996-09-24 13:22 /2 lines/ George Berkeley Recipient: Philosophy <1226> Comment in text 398374 by John Locke Subject: ------------------------------------------------------------ An abstract idea is a contradiction in terms. (398331) ----------------------------------- After: 398331 1996-09-24 13:22 /2 lines/ George Berkeley Recipient: Philosophy <1226> Subject: ------------------------------------------------------------ An abstract idea is a contradiction in terms. (398331) ----------------------------------- Comment in text 398374 by John Locke ") (kom-dashed-lines-doc . "\ When this setting is turned on, dashed lines are displayed before and after the text body. When turned off, blank lines are used instead. On: 892343 1996-09-24 19:21 /2 lines/ Tycho Brahe Recipien: Presentation (of new) Members Subject: Tycho Brahe ------------------------------------------------------------ Astronomer and discoverer of stars resident on the island of Ven. (892343) ----------------------------------- Off: 892343 1996-09-24 19:21 /2 lines/ Tycho Brahe Recipien: Presentation (of new) Members Subject: Tycho Brahe Astronomer and discoverer of stars resident on the island of Ven. (892343) Most people have this turned on.") (kom-autowrap-doc . "\ With this setting turned on, LysKOM will attempt to fill any paragraphs containing lines that are wider than the screen. Paragraphs that appear to have been preformatted by the author are exempted from this treatment. If set to a number, only texts shorter than this number (in characters) will be filled. This may be useful to avoid filling very long texts.") (kom-autowrap-timeout-doc . "\ This setting controls the maximum number of seconds the client may spend attempting to fill paragraphs of a text. This is useful to avoid long waits while the client is breaking lines in a very long text. The actual time spent filling paragraphs may be several seconds longer than this value. Unfortunately there is no way to avoid this. Furthermore, setting a limit slows down all text display slightly. When this is off, it is still possible to cancel paragraph filling by typing C-g.") (kom-show-author-at-end-doc . "\ When this is turned on, the name of the author will be shown at the end of the text. The name is also shown before the text as usual. On (with dashed lines on): 892342 1996-09-24 19:21 /2 lines/ Claude Shannon Mottagare: Presentation (of new) Members Ärende: Claude Shannon ------------------------------------------------------------ Information theoretician (892342) /Claude Shannon/------------------------------ Off: 892342 1996-09-24 19:21 /2 lines/ Claude Shannon Recipient: Presentation (of new) Members Subject: Claude Shannon ------------------------------------------------------------ Information theoretician (892342) ----------------------------------- If dashed lines are off, the author's name will be shown as in this example, but the dashed lines are naturally not displayed.") (kom-truncate-threshold-doc . "\ If this is activated, texts longer than the maximum number of lines will be truncated when you review comments, review marked texts or review the first or last texts in a conference. Texts will not be truncated when you review a text, review a tree or read the next text.") (kom-truncate-show-lines-doc . "\ The number of lines to show of truncated texts.") (kom-print-number-of-unread-on-entrance-doc . "\ Determines whether the number of unread texts is shown when entering a conference: On: Go to next conference... Presentation (of new) Members - 3 unread Read next text - Off: Go to next conference... Presentation (of new) Members Read next text - ") (kom-presence-messages-in-echo-area-doc . "\ If you want messages in the echo area when somebody logs in, logs out or changes name, turn this setting on. Messages are shown in the minibuffer. If you want messages about a limited number of users, specify which ones. To not get any messages at all, just specify an empty list.") (kom-presence-messages-in-buffer-doc . "\ If you want messages in the LysKOM buffer when somebody logs in, logs out or changes name, turn this setting on. Messages are shown in the LysKOM buffer. If you want messages about a limited number of users, specify which ones. To not get any messages at all, just specify an empty list.") (kom-show-where-and-what-doc . "\ If this is on, the list of active users will include the machine and user they are logged in from (if known) and what they are currently doing. On: User Is in conference At Activity -------------------------------------------------------------------------- 6810 George Berkeley Philosophy berkeley@emp1.tcd.ie (Writing a comment.) 7571 John Locke Philosophy eridy@cc.ox.ac.uk (Waiting.) Off: User Is in conference -------------------------------------------------------------------------- 6810 George Berkeley Philosophy 7571 John Locke Philosophy") (kom-show-since-and-when-doc . "\ If this is on, the list of active users will include the connection time and the inactivity period for each user.") (kom-remember-password-doc . "\ When this setting is active the password used to login to LysKOM will be saved in a local variable in the session buffer. This makes it possible to relogin automatically if the session is lost. Note that the password is saved in clear text so it can be read by anyone who gains access to your LysKOM session buffer (even disconnected).") (kom-idle-hide-doc . "\ The listing of active users normally only shows those users who have been active recently. This setting determines how many minutes a user may be inactive without being excluded from the list of active users.") (kom-show-footnotes-immediately-doc . "\ Footnotes can be shown either as comments or immediately when the text they are footnotes to is displayed. This setting controls which behavior is used.") (kom-follow-comments-outside-membership-doc . "\ LysKOM will normally not follow chains of comments into conferences you are not a member of. If you do want to follow comment chains into other conferences, turn this setting on.") (kom-read-depth-first-doc . "\ LysKOM can display texts either in the order they were written or in the order defined by the comment tree. For example, if texts 1003 and 1004 are comments to text 1002, text 1006 is a comment to 1003 and texts 1005 and 1007 are comments to 1004, the comment tree looks something like this: 1002 +-- 1003 --- 1006 | +-- 1004 +-- 1005 | +-- 1007 Reading in order of creation will cause the texts to be displayed in numerical order: 1002, 1003, 1004, 1005, 1006 and finally 1007. Reading in comment order will give the order 1002, 1003, 1006, 1004, 1005 and finally 1007.") (kom-continuous-scrolling-doc . "\ Turned on means that LysKOM will scroll the buffer while new text is being inserted, not just at the end of a command. This works well with faster terminals, but may be worth turning off if the terminal is so slow that scrolling Emacs buffers takes a long time.") (kom-deferred-printing-doc . "\ In order to improve speed, LysKOM will not print certain things, such as the names of users and conferences immediately, but will delay printing to make time for other tasks. This improves response time in the client considerably, and should only be turned off if it causes problems.") (kom-higher-priority-breaks-doc . "\ When texts are created in conferences that have a higher priority than the one currently being read, LysKOM will attempt to break the normal reading order to show these. This setting controls whether the reading order is broken immediately, after the current comment chain is read or when everything in the current conference has been read.") (kom-login-hook-doc . "\ This hook lists commands to be run when logging in, before any input is accepted from the keyboard.") (kom-do-when-done-doc . "\ This hook lists commands and keyboard macros that are to be executed when all texts have been read.") (kom-page-before-command-doc . "\ The LysKOM buffer can be cleared before all commands, so text that is inserted always appears at the top of the buffer's window. This variable controls before which commands the buffer is to be scrolled.") (kom-permissive-completion-doc . "\ When this is on, TAB will only complete to the names of users that are logged on when the command being invoked is only applicable to people that are logged on. When off, TAB will complete to names of everyone.") (kom-membership-default-priority-doc . "\ This specifies how the initial priority of a conference is set when you first become a member. If it is a number between 1 and 255, that is the priority assigned. If it is something else, LysKOM will ask for a priority every time you become a member of a conference.") (kom-membership-default-message-flag-doc . "\ This specifies if group messages are received for conferences you join. `Yes' means group messages are received, `No' that they aren't and `Ask every time' that the client will ask every time you become a member of a conference.") (kom-show-personal-messages-in-buffer-doc . "\ This setting specifies how personal, group and public messages are shown. The messages can be displayed in the LysKOM buffer, simply thrown away or be shown in a named buffer.") (kom-pop-personal-messages-doc . "\ If messages are shown in a named buffer and this setting is also on, then LysKOM will display that buffer whenever a message arrives.") (kom-audio-player-doc . "\ If you want LysKOM to play audio files instead of simply beeping, this setting must specify the name of a program that can play the audio files. The program must take a single argument, the name of the file to play.") (kom-default-message-recipient-doc . "\ This setting controls who will be the default recipient of messages. The default recipient may either be everyone, i.e. a public message; the sender of the most recently received message; the recipient of the most recently received group message; or the sender of the most recently received personal message.") (kom-filter-outgoing-messages-doc . "\ If this is on, messages that are sent automatically, such as automatic replies and replies to remote control commands, will be shown as if you had sent them manually.") (kom-friends-doc . "\ The users named in this list will be displayed using a special face in the LysKOM buffer. These users are also listed with the command Which friends (and may be used in other similar commands).") (kom-morons-doc . "\ The users named in this list will be displayed using a warning face in the LysKOM buffer.") (kom-url-viewer-preferences-doc . "\ This setting controls which WWW browser that will be used to open URLs found in LysKOM. If the first browser in the list cannot handle the type of URL being opened, then the next browser is tried, and so on.") (kom-windows-browser-command-doc . "\ This setting specifies the command to use to start a web browser under Windows. If empty, a couple of commands that are likely to work on Windows will be tried.") (kom-mosaic-command-doc . "\ This setting specifies the command to use to start NCSA Mosaic.") (kom-netscape-command-doc . "\ This setting specifies the command to use to start Netscape or Mozilla.") (kom-galeon-command-doc . "\ This setting specifies the command to use to start Galeon.") (kom-inhibit-typeahead-doc . "\ Key presses are usually buffered while LysKOM is busy, and are executed as soon as possible. With this setting off, LysKOM discards any key presses received while the client was busy.") (kom-max-buffer-size-doc . "\ It is possible to limit the size of the LysKOM buffer by specifying a maximum number of characters in this setting. When the buffer grows beyond this limit, text from the beginning of the buffer is removed.") (kom-ansaphone-record-messages-doc . "\ LysKOM can record messages that arrive when the autoreply feature is on. This setting controls whether messages are recorded or not.") (kom-ansaphone-show-messages-doc . "\ When this setting is on, LysKOM will display incoming messages even if the autoreply feature is turned on.") (kom-ansaphone-default-reply-doc . "\ This is the message sent by the autoreply feature unless a different message has been specified using some other means (and other means are only for careful experts).") (kom-remote-control-doc . "\ When turned on, it is possible to control the session using remote control commands. Only those users listed below may issue the commands.") (kom-remote-controllers-doc . "\ The users listed here are permitted to issue remove control commands to your LysKOM session.") (kom-self-control-doc . "\ When this is on, the user who is logged on may issue remote control commands. This is an alternative to adding yourself to the list of permitted controllers.") (kom-customize-format-doc . "\ The documentation for the various settings can be visible or hidden when you open the settings buffer. No matter if it starts hidden or visible, the documentation for individual settings can be shown and hidden by using the question mark/exclamation mark to the right of the setting.") (kom-default-language-doc . "\ Default language to use in LysKOM. If you change this setting the new language will not be applied to the current setting. Use the Change language command to do that. The first langauge in the list will be used in all clients that support this function.") (kom-ispell-dictionary-doc . "\ This specifies the dictionary ispell is to use for spell checking. If set to ispell-dictionary, then the variable ispell-dictionary will be used instead.") (kom-show-namedays-doc . "\ When this is on, display the name of the day. You can choose to display names from a list appropriate to the currently selected language. You can also choose a specific list of names.") (kom-show-week-number-doc . "\ The Time command shows week numbers if this is on.") (kom-relogin-behaviour-doc . "\ This controls if the client will try to reattach when a command is given in a disconnected session. On means the client tries to reattach automatically, Off that it doesn't even ask.") (kom-relogin-inhibit-commands-doc . "\ Commands for which reattachment is disabled. These commands will never cause the client to reattach.") (kom-membership-default-placement-doc . "\ This controls where new memberships are placed. First means before all existing memberships of the same priority. Last means after all existing memberships of the same priority. A number indicates a fixed placement (although the client will eventually sort the membership list in order of priority).") (kom-show-imported-importer-doc . "\ The importer of an imported e-mail message is shown if this is on. This only works with compliant e-mail importers.") (kom-show-imported-envelope-sender-doc . "\ The actual sender (the envelope sender) of imported e-mails is shown if this is on. This only works with compliant e-mail importers.") (kom-show-imported-external-recipients-doc . "\ Show external recipients and CC recipients of imported e-mails if this is on. This only works with compilant e-mail importers.") (kom-show-imported-message-id-doc . "\ Show Message-Id of imported e-mails if this is on. This only works with compilant e-mail importers.") (kom-agree-text-doc . "\ Default text for the Agree command. It can either be a text or a list of texts. If it is a list, one of the texts will be chosen at random.") (kom-silent-ansaphone-doc . "\ If this is off, the client will not beep when a personal, group or public message is received when the auto reply feature is on.") (kom-default-session-priority-doc . "\ The session priority of new sessions. Conferences with a lower priority will not be read.") (kom-unsubscribe-makes-passive-doc . "\ When this is on, the first time you leave a conference you become a passive member. Leaving the conference again unsubscribes you completely. When this is off, leaving a conference unsubscribes you immediately.") (kom-review-priority-doc . "\ Priority for review commands. This setting can be used to give review commands a higher priority than normal. The default priority is the same as the conference currently being read. Set this to 256 or higher if you want review commands to take precedence over all conferences.") (kom-show-creating-software-doc . "\ Show the name of the client used to create a text if the information is present and this setting is on.") (kom-text-footer-format-doc . "\ Format for the text footer. In the format string, %n is replaced by the text number, %P with the author's name, %p with the author's number, %f with information about the text (HTML, filled, etc), and %- with a suitable dashed line. A number after the percent sign is the minimum number of characters to use. A minus sign before the number causes text to be left justified within the field. An equals sign causes text longer than the indicated width to be truncated.") (kom-long-lines-doc . "\ When this is on, most of the dashed lines are made longer than normal.") (kom-postpone-default-doc . "\ Number of texts to postpone with the Postpone reading command.") (kom-allow-incompleteness-doc . "\ When this is on, the client will not wait for information about all unread texts, even if it is needed. The result is that List news and some other commands do not yield accurate results shortly after logging in. When this is off, the client will wait for information on all unread texts when it is needed.") (kom-smileys-doc . "\ When this is on, Emacs supports it, and the appropriate package (smiley.el, which is part of Gnus) is installed, smileys will be shown graphically.") (kom-ignore-message-senders-doc . "\ Don't show personal, group or alarm messages from these senders.") (kom-ignore-message-recipients-doc . "\ Don't show group messages to these recipients.") (kom-text-footer-dash-length-doc . "\ The total length of the text footer when long dashed lines are not in effect and no custom format is being used.") (kom-text-header-dash-length-doc . "\ The total length of the text header when long dashed lines are not in effect.") (kom-show-personal-message-date-doc . "\ When this is on, the date and time is shown on all personal, group and alarm messages.") (kom-w3-simplify-body-doc . "\ When this is on, the client will ignore colors set in the HTML body when displaying formatted HTML.") (kom-mercial-doc . "\ This text is shown in the list of users when you have finished reading everything.") (kom-session-nickname-doc . "\ How the session name is determined. This is the name displayed in the mode line and by List sessions.") (kom-server-priority-doc . "\ Priority of this LysKOM session. The client can prompt you to go to a session with unread texts when a text arrives in a session with a higher priority than the one currently being read.") (kom-server-priority-breaks-doc . "\ This setting controls when a prompt to go to the next LysKOM session with unread texts is presented. Immediately Present a prompt if any text arrives in a session with a higher priority. Immediately if letters arrive Present a prompt is a letter arrives in a session with a higher priority. After current comment chain Present a prompt after the current chain of comments has been read if a text arrives in a session with a higher priority. After current comment chain if letters arrive Present a prompt after the current chain of comments has been read if a letter arrives in a session with a higher priority. After current conference Present a prompt after all texts in the current conference have been read if a text arrives in a session with a higher priority. After current conference if letters arrive Present a prompt after all texts in the current conference have been read if a letter arrives in a session with a higher priority. After everything has been read Present a prompt to go to the next session with unreads after everything has been read. The prompt is presented regardless of session priorities. Never Never prompt to go to another LysKOM session.") (kom-ding-on-no-subject-doc . "") (kom-ding-on-personal-messages-doc . "") (kom-ding-on-group-messages-doc . "") (kom-ding-on-common-messages-doc . "") (kom-ding-on-no-subject-doc . "") (kom-ding-on-wait-done-doc . "") (kom-ding-on-priority-break-doc . "") (kom-ding-on-new-letter-doc . "") (kom-check-for-new-comments-doc . "") (kom-check-commented-author-membership . "") (kom-confirm-multiple-recipients-doc . "") (kom-check-commented-author-membership-doc . "") (kom-complete-numbers-before-names-doc . "\ When this is on and you enter a text that can be either a conference number or a conference name, the client will accept it as a conference number, if possible. When this is off, the text will be accepted as a conference name first and number second.") (kom-keep-alive-interval-doc . "\ The number of seconds between calls to the server used to keep the network connection to the LysKOM server active. If your network connection shuts down after a period of inactivity, set this to approximately half that period and use the command `Keep connection alive'.") (kom-text-no-prompts-doc . "\ Specifies which commands will always prompt for text numbers and which will not. Commands that are not listed here will use default behavior.") (kom-saved-file-name-doc . "\ Specifies the default file to archive texts in. The client will always prompt for the file name, using this as the default.") (kom-follow-attachments-doc . "\ Specifies whether to read imported e-mail attachments as regular comments. When off, imported attachments are marked as read when the e-mail they are attached to is read.") (kom-show-unread-in-frame-title-doc . "\ When this is on, the indicator \"(Unread)\" is shown in the title bar of all windows whose active buffer belongs to a LysKOM session with unread texts. The title bar may not be updated unless the window is open.") (kom-unread-mode-line-type-doc . "\ This settings controls how unread texts are indicated in the mode line. `Simple' meand there is a single indication for all active sessions that shows if there are any unread texts or letters. `Show all sessions with unread' means all sessions with unread texts will be listed in the mode line. If there are unread letters in a session it will be indicated by uppercasing the session name (e.g. LysLys becomes LYSLYS). If the session name is upper cased already (e.g. LYSLYS) it will be marked with asterisks (e.g. *LYSLYS*). Note that this setting should be the same for all active LysKom sessions. That means it's probably wise to save it in your .emacs.") (kom-created-texts-are-saved-doc . "\ If this variable is set to a file name, all texts you write will be saved to that file. Texts that could not be created are not saved.") (kom-confirm-add-recipients-doc . "\ When this is on and you add a recipient to a text, the client will ask if comments to the text should also be sent to the new recipient. When this is off, comments will always be sent to the new recipient. For most people it is a good idea to leave this on.") (kom-trim-buffer-minimum-doc . "\ If you have limited the LysKOM buffer size, this variable determines how much larger than the limit the buffer has to be before it is trimmed back to the maximum size. The variable must be an integer; the default is 4096.") (kom-dont-check-commented-authors-doc . "") (kom-print-relative-dates-doc . "\ The time fields of texts (and a couple of other things) will be \"today\" or \"yesterday\" if this setting is on and the text was written today or yesterday, respectively. If it is off, absolute dates will always be shown.") (kom-print-seconds-in-time-strings-doc . "\ If this setting is on, some time strings (for example the creation time of texts and sent messages) will include seconds.") (kom-review-uses-cache-doc . "\ If this is turned on, commands that review texts will use saved copies of the text rather than get new copies from the server. This makes the commands run significantly faster, but in some cases the texts may have changed since they were copied, and you will not see those changes.") (kom-review-marks-texts-as-read-doc . "\ If this is turned on, commands that review texts will also mark them as read. Otherwise, the review commands will leave your reading history untouched, as usual.") (kom-auto-review-faqs-doc . "\ If this is turned on, FAQs that are not marked as read will be reviewed automatically when you log on or go to a conference with a new FAQ.") (kom-auto-list-faqs-doc . "\ If this is turned on, new FAQs will be listed automatically when you log on or go to a conference with a new FAQ.") (kom-extended-status-information-doc . "\ When this is on, additional information may be shown by commands that display person, conference and server status.") (kom-highlight-first-line-doc . "\ When this is on, the first line (with text number, date and author) is shown with a different format than normal text.") (kom-highlight-dashed-lines-doc . "\ When this is on, the lines before and after the text body is shown with a different format than normal text.") (kom-highlight-text-body-doc . "\ When this is on, the text body is shown with a different format than normal text.") (kom-async-highlight-dashed-lines-doc . "\ When this is on, the lines before and after personal, group and alarm messages are shown with a different format than normal text.") (kom-async-highlight-text-body-doc . "\ When this is on, the body of personal, group and alarm messages are shown with a different format than normal text.") (kom-edit-hide-add-button-doc . "\ When this is on, an [Add...] button will be shown after the list of recipients and properties when writing a new text.") (kom-format-html-authors-doc . "\ This setting controls which authors' HTML messages that the client will attempt to format.") (kom-format-show-images-doc . "\ This setting controls if texts marked as images are treated specially or handled as normal texts.") (kom-keyboard-menu-immediate-selection-doc . "\ This setting controls whether keyboard shortcuts in text-based context menus require confirmation with return or not. With this on you have to confirm all selections with return.") (kom-max-overlays-doc . "\ Use this setting to limit the number of overlays in the LysKOM buffer \(overlays are used to create the colored backgrounds for texts\). By limiting the number of overlays it is possible to speed up operations such as scrolling significantly. Each text requires 1-4 overlays for highlighting, depending on other settings.") (kom-mark-read-texts-as-read-in-new-recipient-doc . "\ When this is on, texts that have been read will automatically be marked as read in any conferences they are added to. This only works as long as the LysKOM session is logged in. Texts are never automatically marked as read in your mailbox.") (kom-url-transformation-rules-doc . "\ Rules for transformation of URLs before they are sent to a web browser. \"From\" is a regexp that is replaced by \"To\". Regexps are documented in the Emacs manual. The string in \"To\" can contain the following special sequences: \\& means substitute original matched text, \\N means substitute match for (...) number N, \\\\ means insert one \\.") (kom-text-links-doc . "\ Text link definitions. Each line defines one link for texts with a particular recipient. All occurrences of the link pattern will be shown as URL links. The URL pointed to by the link is generated from the text matching the link pattern, by substituting according to the link substitution. The text that is highlighted is determined by the \"Highlight group\" setting: zero means highlight the entire match. A number 1-9 indicated the parenthesized group to highlight (and if that makes no sense to you, stick with zero). If \"Case insensitive\" is on, text will be matched without recard for character case. The link substitution can contain the following special sequences: \\& means substitute original matched text, \\N means substitute match for (...) number N, \\\\ means insert one \\.") (kom-active-face-doc . "\ Face used for clickable areas other than URLs, conference and person names, friends, morons and text numbers.") (kom-active-highlight-face-doc . "\ Face intended for clickable areas that are to be highlighted.") (kom-active-strikethrough-face-doc . "\ Face intended for clickable areas that are to be indicated with strikethrough.") (kom-url-face-doc . "\ Face used for clickable URLs.") (kom-me-face-doc . "\ Face used for my own name.") (kom-highlight-face-doc . "\ Face used for highlighting clickable areas as the mouse is moved over them.") (kom-subject-face-doc . "\ Face used for subject lines.") (kom-text-no-face-doc . "\ Face used for text numbers.") (kom-friends-face-doc . "\ Face used for names of people listed in \"Friends and other special people\".") (kom-morons-face-doc . "\ Face used for names of people listed in \"Morons and other \"special\" people.") (kom-presence-face-doc . "\ Face used for presence messages.") (kom-first-line-face-doc . "\ Face used for first header line. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-warning-face-doc . "\ Face used for important warnings.") (kom-mark-face-doc . "\ Face used for various marks, including the indicator shown when the client scrolls less than a full page. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-dim-face-doc . "\ Face used for various discreet texts.") (kom-text-body-face-doc . "\ Face used for text bodies. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-dashed-lines-face-doc . "\ Face used for dashed lines around texts. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-async-text-body-face-doc . "\ Face used for messages. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-async-dashed-lines-face-doc . "\ Face used for dashed lines around messages. This face is overlayed on other text. Properties not defined by this face will be retained. For example, if you only set the weight property, the colors normally used will not be changed.") (kom-lynx-terminal-doc . "\ Lynx can run inside emacs or in an xterm (or similar). This setting decides which.") (kom-lynx-terminal-command-doc . "\ This is the command to use to start Lynx in emacs terminal-mode. It should be something simple, like \"lynx\".") (kom-lynx-xterm-command-doc . "\ This is the command to use to start Lynx in an xterm. The command neets to start both the terminal emulator and lynx.") (kom-show-sync-messages-doc . "\ When this is on, the client will display a message when the LysKOM server signals that it is saving the database.") (kom-highlight-conferences-doc . "\ This setting controls display of conference names. For each choice it is possible to select a face. The value must be either a face or the name of a variable that contains a face.") (kom-netscape-variant-doc . "\ This setting controls where the client opens URLs. How well the settings work depends on which variant of Netscape or Mozilla you are using, and even on which operating system you are on.") (kom-auto-confirm-new-conferences-doc . "\ If this setting is on, the commands \"List new conferences\" and \"List new users\" will automatically mark new conferences and users as known.") (kom-text-properties-doc . "\ If this setting is on, the client will display different types of things using different fonts and colors. For example, text numbers and other clickable things will be displayed using a special color.") (kom-fontify-text-doc . "\ If this setting is on, words and phrases that are delimited by special characters will be shown in bold or italics. For example, words delimited by asterisks will be shown bold.") ;; ;; Tags for variables ;; (kom-ansaphone-replies-tag . "Automatic replies") (kom-bury-buffers-tag . "Bury buffers when changing LysKOM:") (kom-personal-messages-in-window-tag . "Personal messages: ") (kom-customize-in-window-tag . "LysKOM customization: ") (kom-write-texts-in-window-tag . "Author new texts: ") (kom-prioritize-in-window-tag . "Prioritize conferences: ") (kom-edit-filters-in-window-tag . "Modify filters: ") (kom-view-commented-in-window-tag . "Review comments: ") (kom-list-membership-in-window-tag . "List membership: ") (kom-user-prompt-format-tag . "Prompt format:") (kom-user-prompt-format-executing-tag . "Prompt format when executing:") (kom-anonymous-prompt-format-tag . "Prompt format (anonymous):") (kom-anonymous-prompt-format-executing-tag . "Prompt format when executing (anonymous):") (kom-enabled-prompt-format-tag . "Prompt format (admin):") (kom-enabled-prompt-format-executing-tag . "Prompt format when executing (admin):") (kom-higher-priority-breaks-tag . "Read prioritized texts: ") (kom-created-texts-are-read-tag . "Automatically read created texts: ") (kom-default-mark-tag . "Default mark: ") (kom-print-number-of-unread-on-entrance-tag . "Show number of unread when entering a conference: ") (kom-follow-comments-outside-membership-tag . "Follow comment chains outside membership: ") (kom-show-footnotes-immediately-tag . "Show footnotes immediately: ") (kom-membership-default-priority-tag . "Default priority for new memberships: ") (kom-membership-default-message-flag-tag . "Receive group messages for new memberships: ") (kom-dashed-lines-tag . "Dashed lines around the text body: ") (kom-autowrap-tag . "Fill wide paragraphs before displaying: ") (kom-autowrap-timeout-tag . "Maximum time spend filling paragraphs: ") (kom-show-author-at-end-tag . "Show the name of the author after the body: ") (kom-truncate-threshold-tag . "Truncate long texts: ") (kom-truncate-show-lines-tag . "Lines to show of truncated texts: ") (kom-reading-puts-comments-in-pointers-last-tag . "Comment links are shown:") (kom-read-depth-first-tag . "Read order:") (kom-deferred-printing-tag . "Delayed display:") (kom-continuous-scrolling-tag . "Continuous scrolling:") (kom-presence-messages-in-echo-area-tag . "Presence messages in echo area: ") (kom-presence-messages-in-buffer-tag . "Presence messages in the LysKOM buffer:") (kom-page-before-command-tag . "Clear the screen:") (kom-remember-password-tag . "Remember LysKOM session password:") (kom-idle-hide-tag . "Number of minutes of inactivity before session is hidden: ") (kom-show-where-and-what-tag . "Show where sessions are logged on from and what they are doing: ") (kom-show-since-and-when-tag . "Show when sessions connected and how long they have been inactive: ") (kom-login-hook-tag . "Commands executed after logging on:") (kom-do-when-done-tag . "Commands to execute after reading everything:") (kom-permissive-completion-tag . "Fussy name completion:") (kom-show-personal-messages-in-buffer-tag . "Where are messages shown: ") (kom-pop-personal-messages-tag . "Pop up message buffer: ") (kom-default-message-recipient-tag . "Default message recipient:") (kom-audio-player-tag . "Audio player program:") (kom-ding-on-new-letter-tag . "When a letter arrives: ") (kom-ding-on-priority-break-tag . "When a prioritized text arrives: ") (kom-ding-on-wait-done-tag . "When done waiting: ") (kom-ding-on-common-messages-tag . "When a public message arrives: ") (kom-ding-on-group-messages-tag . "When a group message arrives: ") (kom-ding-on-personal-messages-tag . "When a personal message arrives: ") (kom-ding-on-no-subject-tag . "When you forget the subject line: ") (kom-filter-outgoing-messages-tag . "Show automatic messages:") (kom-friends-tag . "Friends and other special people:") (kom-morons-tag . "Morons and other \"special\" people:") (kom-url-viewer-preferences-tag . "Open URLs using the following program:") (kom-windows-browser-command-tag . "Command to start a web browser on Windows:") (kom-mosaic-command-tag . "Command to start NCSA Mosaic:") (kom-netscape-command-tag . "Command to start Netscape/Mozilla:") (kom-galeon-command-tag . "Command to start Galeon:") (kom-symbolic-marks-alist-tag . "Symbolic mark types:") (kom-cite-string-tag . "Quotation indicator:") (kom-confirm-multiple-recipients-tag . "Confirm multiple recipients: ") (kom-check-commented-author-membership-tag . "Check membership of commented author:") (kom-check-for-new-comments-tag . "Check for unread comments: ") (kom-ansaphone-record-messages-tag . "Save messages when auto reply is on: ") (kom-ansaphone-show-messages-tag . "Display messages when auto reply is on: ") (kom-ansaphone-default-reply-tag . "Auto reply message:") (kom-inhibit-typeahead-tag . "Buffer keypresses:") (kom-max-buffer-size-tag . "Maximum buffer size:") (kom-remote-control-tag . "Remote commands on or off: ") (kom-self-control-tag . "Allow me to use remote commands: ") (kom-remote-controllers-tag . "People allowed to use remove commands:") (kom-customize-format-tag . "Show documentation for all settings:") (kom-default-language-tag . "Language list:") (kom-show-namedays-tag . "Show today's names:") (kom-ispell-dictionary-tag . "Spelling dictionary:") (kom-show-week-number-tag . "Show week number:") (kom-relogin-behaviour-tag . "Reattach automatically:") (kom-relogin-inhibit-commands-tag . "Commands for which reattachment is inhibited:") (kom-membership-default-placement-tag . "Placement of new memberships:") (kom-show-imported-importer-tag . "Show importer of imported messages:") (kom-show-imported-envelope-sender-tag . "Show sender of imported messages:") (kom-show-imported-external-recipients-tag . "Show external recipients of imported messages:") (kom-show-imported-message-id-tag . "Show message-id of imported messages:") (kom-agree-text-tag . "Default text for Agree:") (kom-silent-ansaphone-tag . "Beep when auto reply is on:") (kom-default-session-priority-tag . "Default session priority:") (kom-unsubscribe-makes-passive-tag . "Leaving a conference converts membership to passive:") (kom-review-priority-tag . "Priority for review commands:") (kom-show-creating-software-tag . "Show creating software:") (kom-text-footer-format-tag . "Text footer format:") (kom-long-lines-tag . "Long dashed lines:") (kom-postpone-default-tag . "Default number of texts to postpone:") (kom-allow-incompleteness-tag . "Allow incomplete information about unread texts:") (kom-smileys-tag . "Show smileys graphically:") (kom-ignore-message-senders-tag . "Don't show messages from:") (kom-ignore-message-recipients-tag . "Don't show messages to:") (kom-text-footer-dash-length-tag . "Text footer length:") (kom-text-header-dash-length-tag . "Length of dashed line before text:") (kom-show-personal-message-date-tag . "Show date and time of messages:") (kom-w3-simplify-body-tag . "Display HTML without document colors:") (kom-mercial-tag . "Text to display when all is read:") (kom-session-nickname-tag . "How session name is determined:") (kom-server-priority-tag . "Session priority:") (kom-server-priority-breaks-tag . "Prompt to go to next LysKOM:") (kom-complete-numbers-before-names-tag . "Read conference numbers before names:") (kom-keep-alive-interval-tag . "Keep connection alive interval:") (kom-text-no-prompts-tag . "How commands prompt for text numbers:") (kom-saved-file-name-tag . "File to archive texts in:") (kom-follow-attachments-tag . "Read imported attachments as texts:") (kom-show-unread-in-frame-title-tag . "Show unread indicator in title bar:") (kom-unread-mode-line-type-tag . "How unread texts are indicated in the mode line:") (kom-created-texts-are-saved-tag . "Save created texts:") (kom-confirm-add-recipients-tag . "Ask if comments should be sent to new recipients:") (kom-trim-buffer-minimum-tag . "How small parts of the LysKOM buffer are trimmed:") (kom-dont-check-commented-authors-tag . "Authors not to check:") (kom-print-relative-dates-tag . "Show relative dates:") (kom-print-seconds-in-time-strings-tag . "Include seconds in time strings:") (kom-review-uses-cache-tag . "Review commands use cached texts:") (kom-review-marks-texts-as-read-tag . "Review commands mark texts as read:") (kom-auto-review-faqs-tag . "Review new FAQs automatically:") (kom-auto-list-faqs-tag . "List new FAQs automatically:") (kom-extended-status-information-tag . "Extended status information:") (kom-highlight-first-line-tag . "Color first line:") (kom-highlight-dashed-lines-tag . "Color dashed lines:") (kom-highlight-text-body-tag . "Color text backgrounds:") (kom-async-highlight-dashed-lines-tag . "Color dashed lines around messages:") (kom-async-highlight-text-body-tag . "Color message backgrounds:") (kom-edit-hide-add-button-tag . "Show add button when writing texts:") (kom-format-html-authors-tag . "Format HTML-messages per author:") (kom-format-show-images-tag . "Show texts with images as images:") (kom-keyboard-menu-immediate-selection-tag . "Shortcuts in text menus require confirmation:") (kom-max-overlays-tag . "Maximum number of overlays:") (kom-mark-read-texts-as-read-in-new-recipient-tag . "Mark read texts read when added to new recipients:") (kom-url-transformation-rules-tag . "Transformation of URLs:") (kom-text-links-tag . "Text links:") (kom-active-face-tag . "Other clickable areas:") (kom-active-highlight-face-tag . "Highlighted clickable areas:") (kom-active-strikethrough-face-tag . "Struck-through clickable areas:") (kom-url-face-tag . "Clickable URLs:") (kom-me-face-tag . "My own name:") (kom-highlight-face-tag . "Mouseover highlight:") (kom-subject-face-tag . "Subject lines:") (kom-text-no-face-tag . "Text numbers:") (kom-friends-face-tag . "Friends and other special people:") (kom-morons-face-tag . "Morons and other \"special\" people:") (kom-presence-face-tag . "Presence messages:") (kom-first-line-face-tag . "First header line:") (kom-warning-face-tag . "Important warnings:") (kom-mark-face-tag . "Various marks:") (kom-dim-face-tag . "Various discreet texts:") (kom-text-body-face-tag . "Text bodies:") (kom-dashed-lines-face-tag . "Dashed lines around texts:") (kom-async-text-body-face-tag . "Messages:") (kom-async-dashed-lines-face-tag . "Dashed lines around messages:") (kom-lynx-terminal-command-tag . "Command to run lynx in emacs:") (kom-lynx-terminal-tag . "Where to run lynx:") (kom-lynx-xterm-command-tag . "Command to run lynx in xterm:") (kom-show-sync-messages-tag . "Show database-saving message:") (kom-highlight-conferences-tag . "Display of names::") (kom-netscape-variant-tag . "Where Netscape/Mozilla opens URLs:") (kom-auto-confirm-new-conferences-tag . "Always mark new conferences as known:") (kom-text-properties-tag . "Use fonts and colors:") (kom-fontify-text-tag . "Bold and italic fonts in texts:") ) ) ;;;; ============================================================ ;;;; The default Ansaphone message goes here. The more complex ;;;; message specification probably should too, but it's not here ;;;; yet. People who know how to use it are smart enough to do it ;;;; right. (lyskom-language-var local kom-ansaphone-default-reply en "I am not reading LysKOM right now. Please write a letter instead.") ;;;; ============================================================ ;;;; Other language-dependent variables ;;;; (lyskom-language-var local kom-ispell-dictionary en "english") ;;;; ================================================================ ;;;; Tell phrases should be configured with the default language used ;;;; at the server and not for person reading if they happens to ;;;; differ. This is of course because they are sent to the server for ;;;; everybody else to see. ;;;; Aronsson was here 4 DEC 1990, thus creating version 0.18 ; Created *-tell-* ;;; To coders of the elisp-client: ;;; You not only have to change the text here, you also have to modify ;;; kom-tell-phrases-validation-list in vars.el if you add or remove ;;; one of these. (eval-when-compile (defvar kom-tell-phrases)) (lyskom-language-strings local kom-tell-phrases en '((kom-tell-silence . "") ; Why ? (kom-tell-send . "Is trying to post a text.") (kom-tell-login . "Is entering LysKOM.") (kom-tell-read . "Is reading.") (kom-tell-1st-pres . "Is writing the first presentation.") (kom-tell-write-comment . "Is writing a comment.") (kom-tell-write-footnote . "Is writing a footnote.") (kom-tell-write-letter . "Is writing a letter.") (kom-tell-write-reply . "Is writing a personal reply.") (kom-tell-write-text . "Is writing a text.") (kom-tell-conf-pres . "Is writing the presentation for a new conference.") (kom-tell-recover . "Is restarting KOM. Sigh.") (kom-tell-wait . "Is waiting.") (kom-tell-regret . "Decides to throw away the text.") (kom-tell-review . "Is reviewing.") (kom-tell-change-name . "Takes on a new name.") (kom-tell-change-supervisor . "Changes the supervisor of something.") (kom-tell-next-lyskom . "Moves to a different LysKOM."))) (if (and (boundp 'kom-tell-phrases) kom-tell-phrases) (lyskom-language-strings local kom-tell-phrases en (mapcar (function (lambda (x) (cond ((and (consp x) (symbolp (car x)) (stringp (cdr x))) x) ((and (consp x) (symbolp (car x)) (consp (cdr x)) (stringp (car (cdr x)))) (cons (car x) (car (cdr x)))) (t nil)))) kom-tell-phrases))) ;; Placed here because this must NOT be evaluated before ;; kom-tell-phrases is defined: (lyskom-language-var local kom-mercial en (lyskom-get-string 'kom-tell-wait 'kom-tell-phrases)) (lyskom-language-strings local lyskom-error-texts en '((error-0 . "No error") (error-2 . "Not yet implemented by the server") (error-3 . "No longer implemented by the server") (error-4 . "Wrong password") (error-5 . "String too long") (error-6 . "You have not logged on") (error-7 . "Nobody may enter LysKOM at this time") (error-8 . "You attempted to use conference number 0") (error-9 . "Undefined or secret conference") (error-10 . "Undefined or secret user") (error-11 . "No read or write permission") (error-12 . "Illegal operation") (error-13 . "You are not a member of that conference") (error-14 . "There is no text with that number") (error-15 . "You cannot use global text number 0") (error-16 . "There is no text with that local number") (error-17 . "You cannot use local text number 0") (error-18 . "Name too short, too long or containing illegal characters") (error-19 . "Index out of bounds") (error-20 . "The conference already exists") (error-21 . "The user already exists") (error-22 . "Secret but not read-protected") (error-23 . "You are not allowed to change the person/conference flag") (error-24 . "Error in the database. Tough luck.") (error-25 . "Invalid recipient or comment type") (error-26 . "Illegal info type. (Bug in the client)") (error-27 . "Already recipient of this text") (error-28 . "Already comment to this text") (error-29 . "Already footnote to this text") (error-30 . "Not a recipient of this text") (error-31 . "Not a comment to this text") (error-32 . "Not a footnote to this text") (error-33 . "Too many recipients") (error-34 . "Too many commentsp") (error-35 . "Too many footnotes") (error-36 . "Too many marks") (error-37 . "You are not the author of that text") (error-38 . "You cannot connect to the server") (error-39 . "Out of memory") (error-40 . "The server is gone crazy") (error-41 . "The client thinks that the server says that it does not understand the client") (error-42 . "No such session") (error-43 . "Invalid regular expression") (error-44 . "Can't unmark a text that was not marked") (error-45 . "Temorary lossage. Please try again later") (error-46 . "Sending huge messages to the server is not a nice thing to do") (error-47 . "Anonymous texts are not accepted by all recipients") (error-48 . "Invalid property") (error-49 . "Change of property not permitted") (error-50 . "Unknown asynchronous message") (error-51 . "Internal server error") (error-52 . "Feature disabled in the server") (error-53 . "Unable to send message") (error-54 . "Invalid membership type") (error-55 . "Invalid range") (error-56 . "Invalidrange list") (error-57 . "Undefined measurement") (error-58 . "Priority denied") (error-59 . "Weight denied") (error-60 . "Zero weight") (error-61 . "Invalid boolean value") (error--1 . "You are not a member of any recipient") )) (lyskom-language-var global lyskom-unread-mode-line en (lyskom-make-lyskom-unread-mode-line)) (lyskom-language-var global lyskom-unread-title-format en (lyskom-make-lyskom-unread-title-format)) (lyskom-language-var local lyskom-help-data en lyskom-en-help-data) (provide 'lyskom-strings) ;;; english-strings ends here (defvar lyskom-sv-help-data (quote ((language-help "" (section ((id . "language-help") (prompt . "")) ((h2 nil ((TEXT . "Language Settings"))) (p nil ((TEXT . " You can switch the language in this session by using the command ") (cref ((id . "kom-change-language")) nil) (TEXT . " or the Emacs command ") (i nil ((TEXT . "M-x kom-change-language"))) (TEXT . ". To also change the key bindings (this will affect all sessions), type C-u before the command (e.g. C-u x") (cref ((id . "kom-change-language")) nil) (TEXT . "). "))) (p nil ((TEXT . " For full information, including how to change the default language, see ") (refer ((id . "language")) nil) (TEXT . " (this information will be presented using the current language selection). ")))))) (language "Språk i elispklienten" (section ((id . "language") (prompt . "Språk i elispklienten")) ((h1 nil ((TEXT . "Stöd för flera språk"))) (p nil ((TEXT . " Elispklienten kan byggas med stöd för flera språk. Standard är att bygga med svenska och engelska, med engelska förvalt. "))) (h2 nil ((TEXT . "Tillfälligt språkbyte"))) (p nil ((TEXT . " Använd ") (cref ((id . "kom-change-language")) nil) (TEXT . " för att byta språk tillfälligt. Notera att det krävs ett prefixargument till ") (cref ((id . "kom-change-language")) nil) (TEXT . " för att byta tangentbindningar. Dessa byts då i ") (i nil ((TEXT . "alla"))) (TEXT . " sessioner, inte bara i den där man ger kommandot. "))) (h2 nil ((TEXT . "Permanent språkbyte"))) (p nil ((TEXT . " Använd ") (cref ((id . "kom-customize")) nil) (TEXT . " för att byta språk permanent. Genom att spara språkinställningen i .emacs kommer det att bli standardspråk i klienten. "))) (h2 nil ((TEXT . "Ändra standardspråk"))) (p nil ((TEXT . " Det finns många sätt att ändra standardspråk i klienten. Klienten tittar i tur och ordning på följande: "))) (list nil ((item nil ((TEXT . "Variabeln kom-default-language (ändra med ") (cref ((id . "kom-customize")) nil) (TEXT . ")"))) (item nil ((TEXT . "Omgivningsvariabeln KOMLANGUAGE"))) (item nil ((TEXT . "Omgivningsvariabeln LC_ALL"))) (item nil ((TEXT . "Omgivningsvariabeln LC_MESSAGES"))) (item nil ((TEXT . "Omgivningsvariabeln LANG"))))) (p nil ((TEXT . " Variabeln kom-default-language kan sättas till en lista av symboler, där varje symbol motsvarar ett språk. Se nedan för en lista av språk som elispklienten kan ha stöd för. Det första språk på listan som elispklienten klarar kommer att användas. "))) (p nil ((TEXT . " Omgivningvariablerna skall vara satta till en språk-kod. Till exempel innebär värdet \"sv\" att elispklientn skall använda svenska som standardspråk. "))) (h2 nil ((TEXT . "Kända språk"))) (list nil ((item nil ((TEXT . "sv - Svenska"))) (item nil ((TEXT . "en - Engelska")))))))) (conferences "Veta mer om möten" (section ((id . "conferences") (prompt . "Veta mer om möten")) ((h1 nil ((TEXT . "Möten"))) (p nil ((TEXT . " Varje LysKOM-system är uppdelat i ett antal olika möten som alla behandlar olika ämnen. Vem som helst kan skapa möten, men man ska tänka efter ordenligt innan man skapar ett möte. I ett gammalt LysKOM-system så finns det ofta redan möten som handlar om det man är intresserad av. "))) (p nil ((TEXT . " Möten kan vara öppna, slutna och hemliga. Vem som helst kan gå med i och läsa inlägg i alla öppna möten. För att gå med i slutna möten måste mötesorganisatören lägga till medlemskapet. Hemliga möten går inte ens att se, och servern gör sitt bästa för att inte läcka någon information om dessa. De flesta möten brukar vara öppna. Slutna och hemliga möten är mycket ovanligare. "))) (p nil ((TEXT . " Följande kommandon kan vara av intresse för att komma igång: "))) (inline ((id . "kom-list-conferences")) nil) (inline ((id . "kom-list-re")) nil) (inline ((id . "kom-review-presentation")) nil) (inline ((id . "kom-add-self")) nil) (inline ((id . "kom-go-to-conf")) nil) (h2 nil ((TEXT . "Prioriteter"))) (p nil ((TEXT . " Dina medlemskap i möten har prioriteter. Möten med högre prioritet kommer att presenteras före möten med lägre prioritet när du loggar in. Använd ") (cref ((id . "kom-prioritize")) nil) (TEXT . " för att prioritera möten. ")))))) (persons "Veta mer om personer" (section ((id . "persons") (prompt . "Veta mer om personer")) ((h1 nil ((TEXT . "Personer"))) (p nil ((TEXT . " Varje användare i LysKOM har en person. En person innehåller en del statistik om vad användaren har gjort (skapade inlägg, lästa inlägg, närvarotid och en del annat). Varje person är dessutom kopplad till en brevlåda med samma namn som personen. Brevlådan är i princip ett vanligt möte, men från början är det slutet. ")))))) (texts "Veta mer om inlägg" (section ((id . "texts") (prompt . "Veta mer om inlägg")) ((h1 nil ((TEXT . "Inlägg"))) (p nil ((TEXT . " Inlägg är LysKOMs syfte. Inlägg är helt enkelt texter skrivna av någon medlen i LysKOM. "))) (h2 nil ((TEXT . "Mottagare"))) (p nil ((TEXT . " Varje inlägg har en eller flera mottagare; möten som inlägget är skickat till. Mottagare finns i tre olika smaker: vanlig mottagare, extra-kopiemottagare och dold mottagare. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "Vanlig mottagare"))) (TEXT . " är det normala. En vanlig mottagare betyder att inlägget hör hemma i det angivna mötet (eller i alla angivna möten). Kommentarer till inlägget kommer automatiskt att skickas till samma mottagare. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "Extra-kopiemottagare"))) (TEXT . " används när man vill skicka en kopia av ett inlägg till ett möte utan att kommentarer till inlägget skall hamna i mötet. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "Dold mottagare"))) (TEXT . " är ganska ovanligt. Bara den som har rätt att vara medlem i mötet som är dold mottagare kan överhuvudtaget se den dolda mottagaren. Detta kan alltså användas för att skicka inlägg till någons brevlåda eller till ett slutet möte utan att andra kan se det. "))) (h2 nil ((TEXT . "Kommentarer"))) (p nil ((TEXT . " Ett inlägg kan ha kommentarer. Kommentarer till kommentarer till kommentarer bildar trådar, kommentarskedjor, kommentarsträd och inläggsträd. Vem som helst kan skriva kommentarer till vilket inlägg som helst. Det finns inget krav på att kommentarer ska skickas till samma möten som det som kommenteras. Det är till exempel rätt vanligt med kommentarer som bara skickas till författaren för det kommenterade inlägget. "))) (h2 nil ((TEXT . "Speciella inlägg"))) (p nil ((TEXT . " Det finns tre speciella inläggstyper: presentationer, FAQer och Lappar. En presentation är ett inlägg kopplat till ett möte eller en brevlåda som innehåller en presentation av mötet eller personen. Dessa ligger normalt i speciella möten. En FAQ är ett inlägg som svarar på frågor som ofta ställs i mötet. Varje FAQ är kopplad till ett eller flera möten, och man erbjuds att läsa nya FAQer så fort elispklienten ser att de har skapats. Lappar är inlägg som är kopplade till möten, brevlådor eller till hela servern som innehåller viktig information. Till exempel är det vanligt att tala om att man reser bort och inte kan läsa LysKOM genom att sätta en lapp på sin brevlåda. ")))))) (settings "Veta mer om inställningar" (section ((id . "settings") (prompt . "Veta mer om inställningar")) ((h1 nil ((TEXT . "Inställningar"))) (p nil ((TEXT . " Elispklienten har ett stort antal inställningar. Med några få undantag kan man ändra alla via kommandot ") (cref ((id . "kom-customize")) nil) (TEXT . ". "))) (p nil ((TEXT . " Inställningar kan sparas antingen i servern eller i din .emacs. Inställningar som sparas i servern gäller per användare och endast för en session. Inställningar som sparas i .emacs gäller i alla sessioner, oavsett om samma inställningar även har sparats i servern. ")))))) (reading "Läsa inlägg" (section ((id . "reading") (prompt . "Läsa inlägg")) ((h1 nil ((TEXT . "Att läsa inlägg"))) (p nil ((TEXT . " För att bara läsa inlägg i den ordning de presenteras i LysKOM räcker det att trycka på SPC. Ett inlägg i taget kommer att visas tills det inte finns några kvar. Det finns även ett antal mer avancerade kommandon. Använd kommandot ") (cref ((id . "kom-list-summary")) nil) (TEXT . " för att se vilka inlägg som ligger på kö för att läsas. "))) (list ((header . "Se även:")) ((item nil ((refer ((id . "filter")) nil))) (item nil ((refer ((id . "review")) nil))) (item nil ((refer ((id . "mark")) nil)))))))) (filter "Slippa läsa inlägg" (section ((id . "filter") (prompt . "Slippa läsa inlägg")) ((h1 nil ((TEXT . "Kommandon för att slippa läsa inlägg"))) (p nil ((TEXT . " Ibland vill man inte läsa en del inlägg. Då kan följande kommandon komma väl till pass. Förutom dessa finns ett antal kommandon för att filtrera inlägg, om det är någon typ av inlägg som man aldrig vill se. "))) (inline ((id . "kom-set-unread")) nil) (inline ((id . "kom-jump")) nil) (inline ((id . "kom-super-jump")) nil)))) (mark "Komma ihåg inlägg" (section ((id . "mark") (prompt . "Komma ihåg inlägg")) ((h1 nil ((TEXT . "Kommandon för att komma ihåg inlägg"))) (p nil ((TEXT . " Ibland hittar man ett inlägg som man vill komma ihåg. Då kan man markera inlägget. I grund och botten är varje markering ett heltal mellan 0 och 255, men med elispklienten kan man ge ett namn till varje typ av markering. "))) (inline ((id . "kom-mark-text")) nil) (inline ((id . "kom-unmark-text")) nil) (inline ((id . "kom-review-all-marked-texts")) nil) (inline ((id . "kom-review-marked-texts")) nil) (inline ((id . "kom-list-marks")) nil)))) (review "Hitta gamla inlägg" (section ((id . "review") (prompt . "Hitta gamla inlägg")) ((h1 nil ((TEXT . "Kommandon för att hitta gamla inlägg"))) (p nil ((TEXT . " Ibland vill man hitta gamla inlägg. Det finns ett stort antal kommadon för att göra detta, och alla har namn som börjar med \"Återse\". "))) (inline ((id . "kom-review-by-to")) nil) (inline ((id . "kom-review-first")) nil) (inline ((id . "kom-review-more")) nil) (inline ((id . "kom-review-clear")) nil) (inline ((id . "kom-view-commented-text")) nil) (inline ((id . "kom-review-comments")) nil) (inline ((id . "kom-find-root-review")) nil) (inline ((id . "kom-find-root")) nil) (inline ((id . "kom-review-tree")) nil)))) (writing "Skriva eller ändra inlägg" (section ((id . "writing") (prompt . "Skriva eller ändra inlägg")) ((h1 nil ((TEXT . "Att skriva eller ändra inlägg"))) (p nil ((TEXT . " Det finns i grund och botten tre sorters inlägg: urinlägg, kommentarer och fotnoter. Alla är inlägg, men de hänger ihop med andra inlägg på olika sätt. "))) (h2 nil ((TEXT . "Urinlägg"))) (p nil ((TEXT . " Urinlägg är inlägg som inte är kommentarer till något annat inlägg. Dessa inleder i allmänhet nya diskussioner. Kom ihåg att skriva en vettig ärenderad när du skriver nya urinlägg. Brev är vanliga inlägg som skickas till någons brevlåda. "))) (inline ((id . "kom-write-text")) nil) (inline ((id . "kom-send-letter")) nil) (h2 nil ((TEXT . "Kommentarer"))) (p nil ((TEXT . " Kommentarer är, som det låter, kommentarer till andra inlägg. När du skriver en kommentar, kolla att ärenderaden fortfarande är vettig, och kolla att mottagarna till inlägget är vettiga. Ändra det som inte är vettigt. Personliga svar är kommentarer som skickas till författarens brevlåda. Det är egentligen bara vanliga kommentarer där man har bytt mottagare. "))) (inline ((id . "kom-write-comment")) nil) (inline ((id . "kom-private-answer")) nil) (h2 nil ((TEXT . "Fotnoter"))) (p nil ((TEXT . " Fotnoter är speciella kommentarer som bara författaren till ett inlägg kan skriva. De visas före vanliga kommentarer och är bra när man vill klargöra något man har skrivit i ett inlägg så att det visas innan folk börjar kommentera inlägget. "))) (inline ((id . "kom-write-footnote")) nil) (h2 nil ((TEXT . "Prefixargument"))) (p nil ((TEXT . " Det finns flera sätt att ange vilket inlägg man vill kommentera eller skriva en fotnot till. När man ger något av ovanstående kommando utan extra argument så gäller kommandot det senaste inlägg som man läste (för fotnoter det senaste man skrev eller läste som man var författare till). "))) (p nil ((TEXT . " Ibland vill man ha en annan text. Dels finns kommandon som kommenterar den näst sista text man läste (") (cref ((id . "kom-comment-previous")) nil) (TEXT . ", ") (cref ((id . "kom-private-answer-previous")) nil) (TEXT . "). Dessutom finns möjligheter att ge prefixargument till alla kommandon som hanterar inlägg. Ange prefixargument som vanligt i Emacs genom C-u följt av argumentets värde, eller genom att bara skriva in argumentets värde direkt. "))) (p nil ((TEXT . " Ange ett textnummer ") (i nil ((TEXT . "N"))) (TEXT . " genom att ge inläggsnumret som prefixargument. Ange inlägget som markören står i genom att ge prefixargument 0. Ange inlägget ") (i nil ((TEXT . "N"))) (TEXT . " inlägg bakåt i bufferten från där markören står genom att ge argument -") (i nil ((TEXT . "N"))) (TEXT . ". Få en prompt att mata in inläggsnumret vid genom att skriva C-u före kommandot. "))) (h2 nil ((TEXT . "Hantera mottagare"))) (p nil ((TEXT . " Ibland vill man ändra mottagare på ett inlägg. Till det finns kommandona ") (cref ((id . "kom-add-recipient")) nil) (TEXT . " för att lägga till och ") (cref ((id . "kom-sub-recipient")) nil) (TEXT . " för att ta bort mottagare. "))) (h2 nil ((TEXT . "Meddelanden och anmärkningar"))) (p nil ((TEXT . " Använd aldrig meddelanden eller anmärkningar istället för vanliga inlägg. Det fungerar inte och folk blir sura. ")))))) (kom-list-conferences "" (section ((id . "kom-list-conferences") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-conferences")) nil))) (p nil ((TEXT . " Lista möten som finns i systemet. Använd detta kommando med fantasifulla sökbegrepp för att hitta möten som du är intresserad av. ")))))) (kom-list-re "" (section ((id . "kom-list-re") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-re")) nil))) (p nil ((TEXT . " Lista möten som finns i systemet. Använd detta kommando med fantasifulla sökbegrepp för att hitta möten som du är intresserad av. ")))))) (kom-review-presentation "" (section ((id . "kom-review-presentation") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-presentation")) nil))) (p nil ((TEXT . " Visa presentationen för ett möte eller en person. Använd detta för att få mer information om ett möte. ")))))) (kom-add-self "" (section ((id . "kom-add-self") (prompt . "")) ((h3 nil ((cref ((id . "kom-add-self")) nil))) (p nil ((TEXT . " Gå med i ett möte så att du kan läsa inläggen i mötet och så du får veta när det kommer nya inlägg. ")))))) (kom-go-to-conf "" (section ((id . "kom-go-to-conf") (prompt . "")) ((h3 nil ((cref ((id . "kom-go-to-conf")) nil))) (p nil ((TEXT . " Gå till ett möte som du vill läsa inlägg i. Om du inte redan är medlem i mötet så kommer du att erbjudas att bli medlem. ")))))) (kom-write-footnote "" (section ((id . "kom-write-footnote") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-footnote")) nil))) (p nil ((TEXT . " Skapar en ny fotnot till ett befintligt inlägg. ")))))) (kom-private-answer "" (section ((id . "kom-private-answer") (prompt . "")) ((h3 nil ((cref ((id . "kom-private-answer")) nil))) (p nil ((TEXT . " Skapar ett personligt svar till ett befintligt inlägg. ")))))) (kom-write-comment "" (section ((id . "kom-write-comment") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-comment")) nil))) (p nil ((TEXT . " Skapar en ny kommentar till ett befintligt inlägg. ")))))) (kom-send-letter "" (section ((id . "kom-send-letter") (prompt . "")) ((h3 nil ((cref ((id . "kom-send-letter")) nil))) (p nil ((TEXT . " Skapar ett nytt brev. ")))))) (kom-write-text "" (section ((id . "kom-write-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-text")) nil))) (p nil ((TEXT . " Skapar ett nytt urinlägg. ")))))) (kom-review-tree "" (section ((id . "kom-review-tree") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-tree")) nil))) (p nil ((TEXT . " Återser hela kommentarsträdet under det angivna inlägget. ")))))) (kom-find-root "" (section ((id . "kom-find-root") (prompt . "")) ((h3 nil ((cref ((id . "kom-find-root")) nil))) (p nil ((TEXT . " Återser urinlägget till det angivna inlägget. ")))))) (kom-find-root-review "" (section ((id . "kom-find-root-review") (prompt . "")) ((h3 nil ((cref ((id . "kom-find-root-review")) nil))) (p nil ((TEXT . " Återser hela kommentarsträdet som det angivna inlägget är en del av. Ungefär samma sak som att göra ") (cref ((id . "kom-find-root")) nil) (TEXT . " följt av ") (cref ((id . "kom-review-tree")) nil) (TEXT . ". ")))))) (kom-review-comments "" (section ((id . "kom-review-comments") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-comments")) nil))) (p nil ((TEXT . " Återser alla kommentarer till det angivna inlägget, men inte kommentarer till kommentarerna. ")))))) (kom-view-commented-text "" (section ((id . "kom-view-commented-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-view-commented-text")) nil))) (p nil ((TEXT . " Återser inlägget som det angivna inlägget är en kommentar till. ")))))) (kom-review-clear "" (section ((id . "kom-review-clear") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-clear")) nil))) (p nil ((TEXT . " Avbryter alla återsekommandon som är aktiva. ")))))) (kom-review-more "" (section ((id . "kom-review-more") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-more")) nil))) (p nil ((TEXT . " Återser fler inlägg med samma kriterier som senaste ") (cref ((id . "kom-review-by-to")) nil) (TEXT . ", eller ") (cref ((id . "kom-review-first")) nil) (TEXT . ". ")))))) (kom-review-first "" (section ((id . "kom-review-first") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-first")) nil))) (p nil ((TEXT . " Återser de första inläggen skrivna av en viss person till ett visst möte. Om du inte anger en viss parameter (eller sätter antal till noll) så tas ingen hänsyn till den parametern, så man kan återse allt av en viss person, fösta 5 av en viss person till alla möten och så vidare. ")))))) (kom-review-by-to "" (section ((id . "kom-review-by-to") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-by-to")) nil))) (p nil ((TEXT . " Återser de senaste inläggen skrivna av en viss person till ett visst möte. Om du inte anger en viss parameter (eller sätter antal till noll) så tas ingen hänsyn till den parametern, så man kan återse allt av en viss person, fösta 5 av en viss person till alla möten och så vidare. ")))))) (kom-list-marks "" (section ((id . "kom-list-marks") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-marks")) nil))) (p nil ((TEXT . " Listar alla inlägg markerade med en viss markeringstyp. ")))))) (kom-review-marked-texts "" (section ((id . "kom-review-marked-texts") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-marked-texts")) nil))) (p nil ((TEXT . " Återser inlägg markerade med en viss markeringstyp. ")))))) (kom-review-all-marked-texts "" (section ((id . "kom-review-all-marked-texts") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-all-marked-texts")) nil))) (p nil ((TEXT . " Återser alla markerade inlägg. ")))))) (kom-unmark-text "" (section ((id . "kom-unmark-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-unmark-text")) nil))) (p nil ((TEXT . " Avmarkerar ett inlägg. ")))))) (kom-mark-text "" (section ((id . "kom-mark-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-mark-text")) nil))) (p nil ((TEXT . " Markerar ett inlägg. Frågar normalt efter inläggstyp. ")))))) (kom-super-jump "" (section ((id . "kom-super-jump") (prompt . "")) ((h3 nil ((cref ((id . "kom-super-jump")) nil))) (p nil ((TEXT . " Skapar ett filter som hoppar över inlägg som har samma ärenderad som det angivna inlägget och som har aktuellt möte som mottagare. ")))))) (kom-jump "" (section ((id . "kom-jump") (prompt . "")) ((h3 nil ((cref ((id . "kom-jump")) nil))) (p nil ((TEXT . " Hoppar över kommentarsträdet rotat i det senast lästa inlägget. Praktiskt när man ser att ett inlägg inleder en diskussion som man inte är intresserad av. ")))))) (kom-set-unread "" (section ((id . "kom-set-unread") (prompt . "")) ((h3 nil ((cref ((id . "kom-set-unread")) nil))) (p nil ((TEXT . " Sätter antalet olästa i aktuellt möte. Kan vara bra om man har många gamla inlägg att läsa ikapp eller helt enkelt inte är intresserad av någonting i mötet. ")))))) (kom-prioritize "" (section ((id . "kom-prioritize") (prompt . "")) ((h3 nil ((cref ((id . "kom-prioritize")) nil))) (p nil ((TEXT . " Ändra interaktivt prioriteter och placeringar på dina medlemskap i olika möen. Tryck C-h m eller ? när du har gett kommandot för mer information. "))))))))) (defvar lyskom-en-help-data (quote ((language-help "" (section ((id . "language-help") (prompt . "")) ((h2 nil ((TEXT . "Language Settings"))) (p nil ((TEXT . " You can switch the language in this session by using the command ") (cref ((id . "kom-change-language")) nil) (TEXT . " or the Emacs command ") (i nil ((TEXT . "M-x kom-change-language"))) (TEXT . ". To also change the key bindings (this will affect all sessions), type C-u before the command (e.g. C-u x") (cref ((id . "kom-change-language")) nil) (TEXT . "). "))) (p nil ((TEXT . " For full information, including how to change the default language, see ") (refer ((id . "language")) nil) (TEXT . " (this information will be presented using the current language selection). ")))))) (language "Language" (section ((id . "language") (prompt . "Language")) ((h1 nil ((TEXT . "Multiple language support"))) (p nil ((TEXT . " The elisp client can be built to support multiple languages. The default is to build with support for english and swedish, with english as the default language selection. "))) (h2 nil ((TEXT . "Temporary Language Change"))) (p nil ((TEXT . " Use ") (cref ((id . "kom-change-language")) nil) (TEXT . " to temporarily switch languages. Please note that you must give a prefix argument to ") (cref ((id . "kom-change-language")) nil) (TEXT . " to change the key binding. Key bindings are changed in ") (i nil ((TEXT . "all"))) (TEXT . " sessions, not just the one where the command is given. "))) (h2 nil ((TEXT . "Permanent Language Change"))) (p nil ((TEXT . " Use ") (cref ((id . "kom-customize")) nil) (TEXT . " to change languages permanently. By saving the language selection in .emacs, that language will be the default the next time you start Emacs and load the elisp client. "))) (h2 nil ((TEXT . "Changing the default language"))) (p nil ((TEXT . " There are a number of ways to change the default language in the elisp client. The client looks at the following, in order, until it finds a useful setting: "))) (list nil ((item nil ((TEXT . "The variable kom-default-language (change it with ") (cref ((id . "kom-customize")) nil) (TEXT . ")"))) (item nil ((TEXT . "The environment variable KOMLANGUAGE"))) (item nil ((TEXT . "The environment variable LC_ALL"))) (item nil ((TEXT . "The environment variable LC_MESSAGES"))) (item nil ((TEXT . "The environment variable LANG"))))) (p nil ((TEXT . " The variable kom-default-language can be set to a list of symbols, where each symbol corresponds to a language. Se the list below for available languages. The first language on the list that is supported by the client will be used. "))) (p nil ((TEXT . " The environment variables should be set to a language code. For example, the value \"sv\" will cause the client to use Swedish. "))) (h2 nil ((TEXT . "Known languages"))) (list nil ((item nil ((TEXT . "sv - Swedish"))) (item nil ((TEXT . "en - English")))))))) (conferences "Conferences" (section ((id . "conferences") (prompt . "Conferences")) ((h1 nil ((TEXT . "Conferences"))) (p nil ((TEXT . " Every LysKOM system is organized as a set of conferences, each covering a separate topic. Anybody can create a conference, but you should think twice before doing so. In a mature LysKOM system the conference you want to create probably already exists. "))) (p nil ((TEXT . " Conferences can be open, closed and secret. Anyone can join and read texts in all open conferences. To join a closed conference, the conference administractor has to grant membership. Secret conferences are secret: you can't even see them unless you're a member. Most conferences are open. Closed and secret conferences are much less common. "))) (p nil ((TEXT . " The following commands might be useful to get started: "))) (inline ((id . "kom-list-conferences")) nil) (inline ((id . "kom-review-presentation")) nil) (inline ((id . "kom-add-self")) nil) (inline ((id . "kom-go-to-conf")) nil) (h2 nil ((TEXT . "Priorities"))) (p nil ((TEXT . " Your memberships have priorities. When you log on, conferences with higher priority will be presented before conferences with lower priority. Use ") (cref ((id . "kom-prioritize")) nil) (TEXT . " to change your priorities. ")))))) (persons "Persons" (section ((id . "persons") (prompt . "Persons")) ((h1 nil ((TEXT . "Persons"))) (p nil ((TEXT . " Every LysKOM user has a person. A person contains some statistics about what the user has done (texts created, texts read, logon time, and some other stuff). Every person is also associated with a letterbox with the same name of the person. The letterbox is essentially a regular closed conference. ")))))) (texts "Texts" (section ((id . "texts") (prompt . "Texts")) ((h1 nil ((TEXT . "Texts"))) (p nil ((TEXT . " The purpose of LysKOM is to communicate, and communication is done through texts. Texts are simply texts written by a LysKOM member. "))) (h2 nil ((TEXT . "Recipients"))) (p nil ((TEXT . " Every text has one or more recipients: conferences to which the text has been sent. There are three kinds of recipients: regular recipients, cc-recipients and bcc-recipients. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "Regular recipients"))) (TEXT . " are the most common. A regular recipient means that the text belongs in the specified conference (or conferences). Comments to the text will automatically be sent to the same set of recipients. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "CC recipients"))) (TEXT . " are used when you want to send a copy of a text to a conference, but don't want followups sent to that conference. "))) (p nil ((TEXT . " ") (b nil ((TEXT . "BCC recipients"))) (TEXT . " are fairly unusual. To even ") (i nil ((TEXT . "see"))) (TEXT . " a BCC recipient you have to have permission to be a member in the recipient conference. This kind of recipient can be used when you want to send a copy of a text to somebody's letterbox, but don't want other readers to know. "))) (h2 nil ((TEXT . "Comments"))) (p nil ((TEXT . " A text can have comments. A thread of comments to comments to comments is often called comment thread, comment chain or comment tree (strictly speaking a comment thread is a path down the comment tree). Anyone can write comments to any text. There is not requirement that comments be sent to the same conferences as the commented texts. "))) (h2 nil ((TEXT . "Special texts"))) (p nil ((TEXT . " There are three kinds of special texts: presentations, FAQs and notices. A presentation is a text associated with a conference or letterbox, that contains a presentation of that conference or person. These are normally sent to special conferences. A FAQ is a text with frequently asked questions (and answers) in a particular conference. Normally, new FAQs will be displayed when entering the associated conference. Notices are texts that contain urgent information about a person or conference. You can use a notice when you will be away from LysKOM for a while, and similar occasions. ")))))) (settings "Settings" (section ((id . "settings") (prompt . "Settings")) ((h1 nil ((TEXT . "Settings"))) (p nil ((TEXT . " The elisp client has a large number of user-configurable settings. With a few exceptions you can change these by using the command ") (cref ((id . "kom-customize")) nil) (TEXT . ". "))) (p nil ((TEXT . " Settings can be saved in the server or in your .emacs. Settings that are saved in the server will apply only for a particular user on a particular server. Settings saved in .emacs take precedence over settings stored in the server. ")))))) (reading "Reading texts" (section ((id . "reading") (prompt . "Reading texts")) ((h1 nil ((TEXT . "Reading texts"))) (p nil ((TEXT . " To just read texts in the default order, simply press SPC until all texts have been displayed. The elisp client will display one text at a time until you have read all texts in all conferences you are a member of. Use the command ") (cref ((id . "kom-list-summary")) nil) (TEXT . " to see which texts will be shown. There are a large number of more advanced commands, some of which are listed in the sections mentioned below. "))) (list ((header . "See also:")) ((item nil ((refer ((id . "filter")) nil))) (item nil ((refer ((id . "review")) nil))) (item nil ((refer ((id . "mark")) nil)))))))) (filter "Avoiding certain texts" (section ((id . "filter") (prompt . "Avoiding certain texts")) ((h1 nil ((TEXT . "Avoiding certain texts"))) (p nil ((TEXT . " Sometimes you don't want to read certain texts. In those cases the following commands may be useful. Besides these, there are a number of commands for filtering texts, if there is a certain type of text you never want to see. "))) (inline ((id . "kom-set-unread")) nil) (inline ((id . "kom-jump")) nil) (inline ((id . "kom-super-jump")) nil)))) (mark "Remembering texts" (section ((id . "mark") (prompt . "Remembering texts")) ((h1 nil ((TEXT . "Remembering texts"))) (p nil ((TEXT . " Sometimes you might find a text that you want to remember. In these cases, mark the text. A mark is really just a number from 0 to 255, but the elisp client supports assigning easy-to-remember names to marks. "))) (inline ((id . "kom-mark-text")) nil) (inline ((id . "kom-unmark-text")) nil) (inline ((id . "kom-review-all-marked-texts")) nil) (inline ((id . "kom-review-marked-texts")) nil) (inline ((id . "kom-list-marks")) nil)))) (review "Finding old texts" (section ((id . "review") (prompt . "Finding old texts")) ((h1 nil ((TEXT . "Finding old texts"))) (p nil ((TEXT . " There are a large number of commands for finding old texts. All of these start with the word \"Review\". This is just a small sampling: "))) (inline ((id . "kom-review-by-to")) nil) (inline ((id . "kom-review-first")) nil) (inline ((id . "kom-review-more")) nil) (inline ((id . "kom-review-clear")) nil) (inline ((id . "kom-view-commented-text")) nil) (inline ((id . "kom-review-comments")) nil) (inline ((id . "kom-find-root-review")) nil) (inline ((id . "kom-find-root")) nil) (inline ((id . "kom-review-tree")) nil)))) (writing "Writing or changing texts" (section ((id . "writing") (prompt . "Writing or changing texts")) ((h1 nil ((TEXT . "Writing or changing texts"))) (p nil ((TEXT . " There are three basic types of texts: texts, comments and footnotes. All of them are texts, but they are associated to ") (i nil ((TEXT . "other"))) (TEXT . " texts in different ways. "))) (h2 nil ((TEXT . "Texts"))) (p nil ((TEXT . " These are texts that aren't comments to other texts. They start a new thread of discussion. Remember to choose a good subject line when you create new texts. "))) (inline ((id . "kom-write-text")) nil) (inline ((id . "kom-send-letter")) nil) (h2 nil ((TEXT . "Comments"))) (p nil ((TEXT . " Comments are texts that are comments to other texts. When you write a comment, check that the subject line and recipients are still suitable. Personal replies are simply comments sent to somebody's letterbox. "))) (inline ((id . "kom-write-comment")) nil) (inline ((id . "kom-private-answer")) nil) (h2 nil ((TEXT . "Footnotes"))) (p nil ((TEXT . " Footnotes are special comments that only the author of a text can create. Since they are presented before regular comments, they are useful when you want to clarify something you've written before people start writing comments to the text. "))) (inline ((id . "kom-write-footnote")) nil) (h2 nil ((TEXT . "Prefix argument"))) (p nil ((TEXT . " There are several ways to specify which text you want to comment or write a footnote to. When you give any of the comments listed above without an argument, they will apply to the most recenty read text. "))) (p nil ((TEXT . " Sometimes you want a different text. There are a few commands that apply to the next-to-most-recently read (") (cref ((id . "kom-comment-previous")) nil) (TEXT . ", ") (cref ((id . "kom-private-answer-previous")) nil) (TEXT . "), and by using prefix arguments you can specify any text to any command. Supply a prefix argument as usual in Emacs by C-u followed by the argument, or simply type the argument directly. "))) (p nil ((TEXT . " Specify text ") (i nil ((TEXT . "N"))) (TEXT . " by giving the text number as the prefix argument. Specify the text where the cursor is by giving prefix argument 0. Specify the text ") (i nil ((TEXT . "N"))) (TEXT . " texts back in the buffer from the point where the cursor is by giving the prefix argument -") (i nil ((TEXT . "N"))) (TEXT . ". To get a prompt at which you can type the text number, simply hit C-u before giving the command. "))) (h2 nil ((TEXT . "Manage recipients"))) (p nil ((TEXT . " To change the recipients on a text you have to be the author of the text or administrator of the recipient you want to change. Use the commands ") (cref ((id . "kom-add-recipient")) nil) (TEXT . " to add and ") (cref ((id . "kom-sub-recipient")) nil) (TEXT . " to remove recipients. "))) (h2 nil ((TEXT . "Messages and remarks"))) (p nil ((TEXT . " Never use messages (personal, group or alarm messages) or remarks in place of regular texts. It won't work and people will get upset. ")))))) (kom-list-conferences "" (section ((id . "kom-list-conferences") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-conferences")) nil))) (p nil ((TEXT . " List conferences in LysKOM. Use this command with creative arguments to find conferences that you're interested in. ")))))) (kom-list-re "" (section ((id . "kom-list-re") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-re")) nil))) (p nil ((TEXT . " List conferences in LysKOM. Use this command with creative arguments to find conferences that you're interested in. ")))))) (kom-review-presentation "" (section ((id . "kom-review-presentation") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-presentation")) nil))) (p nil ((TEXT . " Show the presentation for a conference or person. Use this command to get more information about a conference. ")))))) (kom-add-self "" (section ((id . "kom-add-self") (prompt . "")) ((h3 nil ((cref ((id . "kom-add-self")) nil))) (p nil ((TEXT . " Join a conference so you can read the texts in the conference and so you'll find out when new texts are created. ")))))) (kom-go-to-conf "" (section ((id . "kom-go-to-conf") (prompt . "")) ((h3 nil ((cref ((id . "kom-go-to-conf")) nil))) (p nil ((TEXT . " Go to a conference you want to read texts in. If you aren't already a member of the conference, you will be asked if you want to join the conference. ")))))) (kom-write-footnote "" (section ((id . "kom-write-footnote") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-footnote")) nil))) (p nil ((TEXT . " Creates a new footnote to an existing text. ")))))) (kom-private-answer "" (section ((id . "kom-private-answer") (prompt . "")) ((h3 nil ((cref ((id . "kom-private-answer")) nil))) (p nil ((TEXT . " Creates a private reply to the author of an existing text. ")))))) (kom-write-comment "" (section ((id . "kom-write-comment") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-comment")) nil))) (p nil ((TEXT . " Creates a new comment to an existing text. ")))))) (kom-send-letter "" (section ((id . "kom-send-letter") (prompt . "")) ((h3 nil ((cref ((id . "kom-send-letter")) nil))) (p nil ((TEXT . " Creates a new letter. ")))))) (kom-write-text "" (section ((id . "kom-write-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-write-text")) nil))) (p nil ((TEXT . " Creates a new text that is not a comment to any other text. ")))))) (kom-review-tree "" (section ((id . "kom-review-tree") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-tree")) nil))) (p nil ((TEXT . " Reviews the entire tree of comments under the specified text. ")))))) (kom-find-root "" (section ((id . "kom-find-root") (prompt . "")) ((h3 nil ((cref ((id . "kom-find-root")) nil))) (p nil ((TEXT . " Finds the text that started the discussion that the specified text is part of. ")))))) (kom-find-root-review "" (section ((id . "kom-find-root-review") (prompt . "")) ((h3 nil ((cref ((id . "kom-find-root-review")) nil))) (p nil ((TEXT . " Reviews the entire tree of comments that the specified text is part of. Essentially the same as doing ") (cref ((id . "kom-find-root")) nil) (TEXT . " followed by ") (cref ((id . "kom-review-tree")) nil) (TEXT . ". ")))))) (kom-review-comments "" (section ((id . "kom-review-comments") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-comments")) nil))) (p nil ((TEXT . " Reviews all comments to the specified text, but not the comments to the comments. ")))))) (kom-view-commented-text "" (section ((id . "kom-view-commented-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-view-commented-text")) nil))) (p nil ((TEXT . " Reviews the text to which the specified text is a comment. ")))))) (kom-review-clear "" (section ((id . "kom-review-clear") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-clear")) nil))) (p nil ((TEXT . " Aborts all review commands that are active. ")))))) (kom-review-more "" (section ((id . "kom-review-more") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-more")) nil))) (p nil ((TEXT . " Reviews more texts using the same criteria as the most recent ") (cref ((id . "kom-review-by-to")) nil) (TEXT . ", or ") (cref ((id . "kom-review-first")) nil) (TEXT . " command. ")))))) (kom-review-first "" (section ((id . "kom-review-first") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-first")) nil))) (p nil ((TEXT . " Reviews the first text(s) created by a particular person sent to a particular conference. Any parameter can be ignored by simply not supplying a value (use zero for the number of texts) in order to do things like review all texts to a particular conference, the first five texts written by a particular person and so forth. ")))))) (kom-review-by-to "" (section ((id . "kom-review-by-to") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-by-to")) nil))) (p nil ((TEXT . " Reviews the text(s) most recently created by a particular person sent to a particular conference. Any parameter can be ignored by simply not supplying a value (use zero for the number of texts) in order to do things like review all texts to a particular conference, the last five texts written by a particular person and so forth. ")))))) (kom-list-marks "" (section ((id . "kom-list-marks") (prompt . "")) ((h3 nil ((cref ((id . "kom-list-marks")) nil))) (p nil ((TEXT . " Lists all texts marked with a particular mark. ")))))) (kom-review-marked-texts "" (section ((id . "kom-review-marked-texts") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-marked-texts")) nil))) (p nil ((TEXT . " Reviews all texts marked with a particular mark. ")))))) (kom-review-all-marked-texts "" (section ((id . "kom-review-all-marked-texts") (prompt . "")) ((h3 nil ((cref ((id . "kom-review-all-marked-texts")) nil))) (p nil ((TEXT . " Reviews all marked texts. ")))))) (kom-unmark-text "" (section ((id . "kom-unmark-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-unmark-text")) nil))) (p nil ((TEXT . " Removes your marks from a texts. ")))))) (kom-mark-text "" (section ((id . "kom-mark-text") (prompt . "")) ((h3 nil ((cref ((id . "kom-mark-text")) nil))) (p nil ((TEXT . " Marks a texts. Normally this command will ask for the mark to use. ")))))) (kom-super-jump "" (section ((id . "kom-super-jump") (prompt . "")) ((h3 nil ((cref ((id . "kom-super-jump")) nil))) (p nil ((TEXT . " Creates a filter that will skip texts that have the same subject line as the specified text and are sent to the current conference. ")))))) (kom-jump "" (section ((id . "kom-jump") (prompt . "")) ((h3 nil ((cref ((id . "kom-jump")) nil))) (p nil ((TEXT . " Skips all texts in the comment tree below the most recently read text. This is useful when you see a text that starts a discussion that you aren't interested in. ")))))) (kom-set-unread "" (section ((id . "kom-set-unread") (prompt . "")) ((h3 nil ((cref ((id . "kom-set-unread")) nil))) (p nil ((TEXT . " Set the number of unread texts in a particular conference. Can be useful when you have lots of old texts to catch up with. ")))))) (kom-prioritize "" (section ((id . "kom-prioritize") (prompt . "")) ((h3 nil ((cref ((id . "kom-prioritize")) nil))) (p nil ((TEXT . " Interactively change priorities and placements of your memberships. For more information, press C-h m or ? when you have given the command. "))))))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: komtypes.el,v 44.42 2004/07/20 19:28:10 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; This file contains primitives for the different data types ;;;; in the lyskom system. All types here have their origin in ;;;; the server. Compare the file clienttypes.el. ;;;; ;;;; Author: ceder ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: komtypes.el,v 44.42 2004/07/20 19:28:10 byers Exp $\n")) ;;; ============================================================ ;;; Black magic... (defmacro def-komtype (type args &rest flags) "Define a new type named TYPE with fields ARGS and documentation DOC. TYPE is the name of the new type; a symbol. ARGS is a list of arguments. Each element can be a symbol or a cons whose car is the name of the field and the cdr is a property list for the field. The special symbol &optional indicates start of fields that will be optional in the constructor argument list. Legal fiels properties are: :default val In the constructor, if the value supplied for the field is nil, use VAL instead. :read-only t Do not create a mutator. Note that t must be specified. :automatic val Do not include field in constructor. Use VAL for the initial field value. :filter code Use CODE as a filter for the field value supplied to the constructor. Only one of :automatic, :filter or :default may be supplied. Optional FLAGS are additional modifiers. If :nil-safe is included, then calling accessors on nil object will return nil and not signal an error. If :create-hook HOOK is included, HOOK will be inserted into the constructor function. When HOOK is evaluated, OBJECT (uppercase) is bound to the newly created object. It may be modified. " (let ((accessors nil) (mutators nil) (predicate nil) (constructor nil) (access-method 'aref) (type-sym (intern (upcase (symbol-name type)))) (constructor-body nil) (create-hook nil)) (while flags (cond ((eq (car flags) ':nil-safe) (setq access-method 'elt)) ((eq (car flags) ':create-hook) (setq flags (cdr flags)) (setq create-hook (car flags)))) (setq flags (cdr flags))) ;; Create constructor (setq constructor-body `(cons ',type-sym (vector ,@(delq '&optional (mapcar (lambda (arg) (cond ((plist-member (cdr-safe arg) ':automatic) (plist-get (cdr-safe arg) ':automatic)) ((plist-member (cdr-safe arg) ':filter) (plist-get (cdr-safe arg) ':filter)) ((plist-get (cdr-safe arg) ':default) `(or ,(car arg) ,(plist-get (cdr arg) :default))) (t (or (car-safe arg) arg)) )) args))))) (when create-hook (setq constructor-body `(let ((OBJECT ,constructor-body)) ,create-hook OBJECT))) (setq constructor `(defsubst ,(intern (format "lyskom-create-%S" type)) ,(delq nil (mapcar (lambda (arg) (unless (plist-member (cdr-safe arg) ':automatic) (or (car-safe arg) arg))) args)) ,(format "Create a `%S' from arguments. Automatically created with def-komtype." type) ,constructor-body)) ;; Create predicate (setq predicate `(defsubst ,(intern (format "lyskom-%S-p" type)) (obj) ,(format "Return non-nil if OBJ is a %S Automatically created with def-komtype" type) (and (consp obj) (eq (car obj) ',type-sym)))) ;; Create accessors and mutators (let ((field-index 0)) (mapcar (lambda (arg) (unless (eq arg '&optional) (let ((field (or (car-safe arg) arg))) (setq accessors (cons `(defsubst ,(intern (format "%S->%S" type field)) (obj) (lyskom-assert (or (null obj) (,(intern (format "lyskom-%S-p" type)) obj)) "Assertion failed in %s: got %S" ,(format "%S->%S" type field) obj) ,(format "Return field `%s' from OBJ." field) (,access-method (cdr obj) ,field-index)) accessors)) (unless (plist-get (cdr-safe arg) ':read-only) (setq mutators (cons `(defsubst ,(intern (format "set-%S->%S" type field)) (obj val) (lyskom-assert (or (null obj) (,(intern (format "lyskom-%S-p" type)) obj)) "Assertion failed in %s: got %S" ,(format "%S->%S" type field) obj) ,(format "Set field `%s' of OBJ to VAL." field) (aset (cdr obj) ,field-index val)) mutators)))) (setq field-index (1+ field-index)))) args)) ;; Return the forms `(progn ,constructor ,predicate ,@accessors ,@mutators))) ;;; ================================================================ ;;; conf-no-list ;;; Constructor: (def-komtype conf-no-list ((conf-nos :filter (cond ((vectorp conf-nos) (append conf-nos nil)) (t conf-nos)) :read-only t)) :nil-safe) ;;; ================================================================ ;;; uconf-stat (def-komtype uconf-stat ((conf-no :read-only t) name (conf-type :read-only t) (highest-local-no :read-only t) (nice :read-only t)) :nil-safe) ;;; ================================================================ ;;; conf-stat ;;; Constructor: (def-komtype conf-stat ((conf-no :read-only t) name (conf-type :read-only t) (creation-time :read-only t) (last-written :read-only t) (creator :read-only t) (presentation) (supervisor :read-only t) (permitted-submitters :read-only t) (super-conf :read-only t) (msg-of-day) (garb-nice :read-only t) (keep-commented :read-only t) (no-of-members :read-only t) (first-local-no :read-only t) no-of-texts &optional (expire :read-only t :default 0) (aux-items :read-only t)) :nil-safe) ;;; ================================================================ ;;; conf-type. (def-komtype conf-type ((rd_prot :read-only t) (original :read-only t) (secret :read-only t) (letterbox :read-only t) &optional (anarchy :read-only t) (forbid-secret :read-only t) (rsv2 :read-only t) (rsv3 :read-only t)) :nil-safe) ;;;; This field is just simulation of a field in the conf-stat ;;;; that not yet exist. (defsubst conf-stat->comm-conf (conf-stat) (if (and (conf-type->original (conf-stat->conf-type conf-stat)) (not (zerop (conf-stat->super-conf conf-stat)))) (conf-stat->super-conf conf-stat) (conf-stat->conf-no conf-stat))) ;;; ================================================================ ;;; Conf-list (def-komtype conf-list ((conf-nos :read-only t) (conf-types :read-only t)) :nil-safe) ;;; ================================================================ ;;; pers-stat ;;; Constructor: (def-komtype pers-stat ((pers-no :read-only t) (username :read-only t) privileges (flags :read-only t) (last-login :read-only t) user-area (total-time-present :read-only t) (sessions :read-only t) (created-lines :read-only t) (created-bytes :read-only t) (read-texts :read-only t) (no-of-text-fetches :read-only t) (created-persons :read-only t) (created-confs :read-only t) (first-created-text :read-only t) (no-of-created-texts :read-only t) (no-of-marks :read-only t) (no-of-confs :read-only t)) :nil-safe) ;;; ================================================================ ;;; text-stat ;;; Constructor: (def-komtype text-stat ((text-no :read-only t) (creation-time :read-only t) (author :read-only t) (no-of-lines :read-only t) (no-of-chars :read-only t) (no-of-marks :read-only t) (misc-info-list :read-only t) &optional (aux-items)) :nil-safe) ;;; ================================================================ ;;; aux-item (def-komtype aux-item-flags ((deleted :read-only t) inherit secret anonymous dont-garb (reserved2 :read-only t) (reserved3 :read-only t) (reserved4 :read-only t)) :nil-safe) (def-komtype aux-item ((aux-no :read-only t) (tag :read-only t) (creator :read-only t) (sent-at :read-only t) (flags :read-only t) (inherit-limit :read-only t) data) :nil-safe) ;;; ================================================================ ;;; text (def-komtype text ((text-no :read-only t) text-mass) :nil-safe) ;;; Utilities (defun text->decoded-text-mass (text text-stat) "Get the text mass of a text after decoding according to its content type" (save-match-data (let* ((str (text->text-mass text)) (item (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)) (content-type (and (car item) (lyskom-mime-decode-content-type (aux-item->data (car item)))))) (if (lyskom-mime-content-type-get content-type 'charset) (lyskom-mime-decode-string str (lyskom-mime-content-type-get content-type 'charset)) str)))) ;;; ================================================================ ;;; misc-info (def-komtype misc-info (type recipient-no local-no rec-time comm-to comm-in footn-to footn-in sender sent-at) :nil-safe) (defsubst lyskom-create-empty-misc-info () "Create an empty misc-info." (lyskom-create-misc-info nil nil nil nil nil nil nil nil nil nil)) ;;; ================================================================ ;;; time (def-komtype time ((sec :read-only t) (min :read-only t) (hour :read-only t) (mday :read-only t) (mon :read-only t) (year :read-only t) (wday :read-only t) (yday :read-only t) (isdst :read-only t) &optional (tzhr :read-only t) (tzmin :read-only t)) :nil-safe) (defun lyskom-create-time-from-utc (sec min hour mday mon year wday yday isdst &optional tzhr tzmin) (if lyskom-server-uses-utc (let* ((date (decode-time (encode-time sec min hour mday mon year 0)))) (unless (eq mday (elt date 3)) (setq yday (if (< (or (car (current-time-zone)) 0) 0) (- yday 1) (+ yday 1))) (cond ((< yday 1) (setq yday (lyskom-days-in-year (elt date 5)))) ((> yday (lyskom-days-in-year year)) (setq yday 1)))) (lyskom-create-time (elt date 0) ; sec (elt date 1) ; min (elt date 2) ; hour (elt date 3) ; mday (elt date 4) ; mon (elt date 5) ; year (elt date 6) ; dow yday ; yday (elt date 7) ; dst nil nil) ) (lyskom-create-time sec min hour mday mon year wday yday isdst tzhr tzmin))) ;;; ================================================================ ;;; privs (def-komtype privs ((wheel :read-only t) (admin :read-only t) (statistic :read-only t) (create_pers :read-only t) (create_conf :read-only t) (change_name :read-only t) (flg7 :read-only t) (flg8 :read-only t) (flg9 :read-only t) (flg10 :read-only t) (flg11 :read-only t) (flg12 :read-only t) (flg13 :read-only t) (flg14 :read-only t) (flg15 :read-only t) (flg16 :read-only t)) :nil-safe) ;;; ================================================================ ;;; flags (def-komtype session-flags ((invisible :read-only t) (user_active_used :read-only t) (user_absent :read-only t) (reserved3 :read-only t) (reserved4 :read-only t) (reserved5 :read-only t) (reserved6 :read-only t) (reserved7 :read-only t)) :nil-safe) (def-komtype dynamic-session-info ((session :read-only t) (person :read-only t) (working-conference :read-only t) (idle-time :read-only t) (flags :read-only t) (what-am-i-doing :read-only t)) :nil-safe) (def-komtype static-session-info ((username :read-only t) (hostname :read-only t) (ident-user :read-only t) (connection-time :read-only t)) :nil-safe) ;;; ================================================================ ;;; flags (def-komtype flags ((unread_is_secret :read-only t) (flg2 :read-only t) (flg3 :read-only t) (flg4 :read-only t) (flg5 :read-only t) (flg6 :read-only t) (flg7 :read-only t) (flg8 :read-only t)) :nil-safe) ;;; ================================================================ ;;; membership ;;; Constructor: (def-komtype member-list ((members :read-only t)) :nil-safe) (def-komtype member ((pers-no :read-only t) (created-by :read-only t) (created-at :read-only t) (membership-type :read-only t)) :nil-safe) ;;; ;;; Note that message-flag here is *not* the same as in the ;;; protocol. The value of message-flag is computed from ;;; message-invert in the protocol when received and when ;;; sent. ;;; (def-komtype membership-type (invitation passive secret message-flag (rsv2 :read-only t) (rsv3 :read-only t) (rsv4 :read-only t) (rsv5 :read-only t)) :nil-safe) (def-komtype membership (position (last-time-read) (conf-no :read-only t) priority (last-text-read :read-only t) read-texts (created-by :read-only t) (created-at :read-only t) (type :read-only t)) :nil-safe) ;;; Special stuff (defun lyskom-member-list-find-member (person members) (when members (lyskom-traverse member (member-list->members members) (when (eq person (member->pers-no member)) (lyskom-traverse-break member))))) ;;; ================================================================ ;;; map (def-komtype map ((first-local :read-only t) (text-nos :read-only t)) :nil-safe) ;;; Concat: (defsubst lyskom-map-concat (&rest maps) "Take any number of MAPS and return a new map which is the sum of the maps. Args: &rest MAPS. The MAPS must be consecutive. No gaps or overlaps are currently allowed." (if (null maps) (lyskom-create-map 1 []) (let* ((first (map->first-local (car maps))) (high (+ first (length (map->text-nos (car maps))))) (maplist (list (map->text-nos (car maps)))) (maps (cdr maps))) (while maps (if (/= (map->first-local (car maps)) high) (signal 'lyskom-internal-error '("lyskom-map-concat"))) (setq maplist (nconc maplist (list (map->text-nos (car maps))))) (setq high (+ high (length (map->text-nos (car maps))))) (setq maps (cdr maps))) (lyskom-create-map first (apply 'vconcat maplist))))) ;;; ================================================================ ;;; Text-Mapping support (def-komtype text-mapping ((range-begin :read-only t) (range-end :read-only t) (size :read-only t) (later-texts-exist :read-only t) (type :read-only t) (block :read-only nil))) (defsubst lyskom-create-text-pair (local global) (cons local global)) ;;UNUSED: text-pair->local-number (defsubst text-pair->local-number (pair) (car pair)) ;;UNUSED: text-pair->global-number (defsubst text-pair->global-number (pair) (cdr pair)) (defsubst text-mapping->block-size (map) (if (eq (text-mapping->type map) 'dense) (length (map->text-nos (text-mapping->block map))) (length (text-mapping->block map)))) ;;UNUSED: text-mapping->local-to-global (defun text-mapping->local-to-global (map local) (cond ((or (< local (text-mapping->range-begin map)) (> local (text-mapping->range-end map))) nil) ((eq (text-mapping->type map) 'sparse) (cdr (assq local (text-mapping->block map)))) ((eq (text-mapping->type map) 'dense) (let ((result (aref (text-mapping->block map) (- local (text-mapping->range-begin map))))) (and (not (zerop result)) result))))) (defun text-mapping->global-numbers (map) (cond ((eq (text-mapping->type map) 'sparse) (mapcar 'cdr (text-mapping->block map))) ((eq (text-mapping->type map) 'dense) (let ((result nil)) (lyskom-traverse el (map->text-nos (text-mapping->block map)) (unless (zerop el) (setq result (cons el result)))) (nreverse result))))) (defun text-mapping->global-to-local (map global) (cond ((eq (text-mapping->type map) 'sparse) (cdr (rassq global (text-mapping->block map)))) ((eq (text-mapping->type map) 'dense) (let ((i (text-mapping->range-begin map)) (result nil)) (while (< i (text-mapping->range-end map)) (if (eq (aref (map->text-nos (text-mapping->block map)) (- i (text-mapping->range-begin map))) global) (setq result i i (text-mapping->range-end map)) (setq i (1+ i)))) result)))) (defun text-mapping->remove-local (map local) (cond ((eq (text-mapping->type map) 'dense) (setq local (- local (text-mapping->range-begin map))) (when (and (>= local 0) (< local (text-mapping->block-size map))) (aset (map->text-nos (text-mapping->block map)) local 0))) ((eq (text-mapping->type map) 'sparse) (let ((el (assq local (text-mapping->block map)))) (when el (set-text-mapping->block map (delq el (text-mapping->block map)))))))) (def-komtype text-mapping-iterator ((map :read-only t) (next-value :automatic nil) (state :automatic nil)) :create-hook (text-mapping-iterator->init OBJECT)) (defun text-mapping->iterator (map) (lyskom-create-text-mapping-iterator map)) (defun text-mapping-iterator->init (iter) (if (eq (text-mapping->type (text-mapping-iterator->map iter)) 'dense) (set-text-mapping-iterator->state iter 0) (set-text-mapping-iterator->state iter (text-mapping->block (text-mapping-iterator->map iter))))) (defun text-mapping-iterator->next (iter) (when (text-mapping-iterator->state iter) (let ((map (text-mapping-iterator->map iter))) (prog1 (if (eq (text-mapping->type map) 'dense) (lyskom-create-text-pair (+ (text-mapping-iterator->state iter) (text-mapping->range-begin map)) (aref (map->text-nos (text-mapping->block map)) (text-mapping-iterator->state iter))) (car (text-mapping-iterator->state iter))) (text-mapping-iterator->step iter))))) (defun text-mapping-iterator->step (iter) (let ((map (text-mapping-iterator->map iter)) (state (text-mapping-iterator->state iter))) (cond ((eq (text-mapping->type map) 'dense) (setq state (1+ state)) (while (and (< state (text-mapping->block-size map)) (eq 0 (aref (map->text-nos (text-mapping->block map)) state))) (setq state (1+ state))) (set-text-mapping-iterator->state iter (and (< state (text-mapping->block-size map)) state))) ((eq (text-mapping->type map) 'sparse) (set-text-mapping-iterator->state iter (cdr state)))))) ;;; ================================================================ ;;; mark (def-komtype mark ((text-no :read-only t) (mark-type :read-only t)) :nil-safe) ;;; Utilities (defun mark->symbolic-mark-type (mark) (lyskom-symbolic-mark-type-string (mark->mark-type mark))) ;;; ================================================================ ;;; who-info (def-komtype who-info ((pers-no :read-only t) (working-conf :read-only t) (connection :read-only t) (doing-what :read-only t) (username :read-only t) &optional (hostname :read-only t) (ident-user :read-only t)) :nil-safe) ;;; ================================================================ ;;; session-info (def-komtype session-info ((pers-no :read-only t) (working-conf :read-only t) (connection :read-only t) (doing :read-only t) (username :read-only t) (hostname :read-only t) (ident-user :read-only t) (idletime :read-only t) (connect-time :read-only t)) :nil-safe) ;;; ================================================================ ;;; text-list ;;; Constructor: (def-komtype text-list (texts-internal (tail :automatic (last texts-internal)) (length-internal :automatic (length texts-internal))) :nil-safe) (defsubst text-list->texts (text-list) (text-list->texts-internal text-list)) (defsubst set-text-list->texts (text-list texts) (set-text-list->texts-internal text-list texts) (set-text-list->tail text-list (last texts)) (set-text-list->length-internal text-list (length texts))) (defsubst text-list->empty (text-list) "Return t if TEXT-LIST is empty." (null (text-list->texts text-list))) (defsubst text-list->length (text-list) "Return the length of TEXT-LIST." (unless (text-list->length-internal text-list) (set-text-list->length-internal text-list (length (text-list->texts text-list)))) (text-list->length-internal text-list)) (defsubst text-list->memq (text-list no) "Return non-nil if TEXT-LIST contains TEXT-NO." (memq no (text-list->texts text-list))) (defsubst text-list->delq (text-list no) "Remove text NO from TEXT-LIST." (set-text-list->texts-internal text-list (delq no (text-list->texts text-list))) (when (eq no (car (text-list->tail text-list))) (set-text-list->tail text-list (last (text-list->texts text-list)))) (set-text-list->length-internal text-list nil)) ;;; FIXME: It would be useful if text-list->append would only append ;;; FIXME: unique numbers and not blindnly concatenate the two lists. ;;; FIXME: That would probably take care of any remaining problems ;;; FIXME: where some texts are listed twice in the to do list. (defsubst text-list->append (text-list texts) "Destructively append TEXTS to the end of TEXT-LIST." (if (text-list->texts text-list) (progn (nconc (or (text-list->tail text-list) (text-list->texts-internal text-list)) texts) (when (text-list->length-internal text-list) (set-text-list->length-internal text-list (+ (text-list->length-internal text-list) (length texts))))) (set-text-list->texts-internal text-list texts) (set-text-list->length-internal text-list nil)) (set-text-list->tail text-list (last texts))) (defun text-list->trim-head (tlist n) "Destructively remove all but the N last elements from TLIST. Do nothing if the TLIST is less than N elements long." (set-text-list->texts-internal tlist (nthcdr (max (- (text-list->length tlist) n) 0) (text-list->texts tlist))) (when (text-list->length-internal tlist) (set-text-list->length-internal tlist n)) (unless (text-list->texts tlist) (set-text-list->length-internal tlist 0) (set-text-list->tail tlist nil))) ;;; ================================================================ ;;; version-info ;;; Constructor: (def-komtype version-info ((protocol-version :read-only t) (server-software :read-only t) (software-version :read-only t)) :nil-safe) ;;; ================================================================ ;;; server-info (def-komtype server-info ((version :read-only t) (conf-pres-conf :read-only t) (pers-pres-conf :read-only t) (motd-conf :read-only t) (kom-news-conf :read-only t) motd-of-lyskom &optional (aux-item-list :read-only t)) :nil-safe) ;;; ================================================================ ;;; conf-z-info-list (def-komtype conf-z-info-list ((conf-z-infos :read-only t)) :nil-safe) ;;; ================================================================ ;;; conf-z-info ;;; Constructor: (def-komtype conf-z-info ((name :read-only t) (conf-type :read-only t) (conf-no :read-only t)) :nil-safe) (def-komtype stats-description ((what :read-only t) (when :read-only t)) :nil-safe) (def-komtype stats ((average :read-only t) (ascent-rate :read-only t) (descent-rate :read-only t)) :nil-safe) (def-komtype server-stats (&optional (what :default nil) (when :default nil) (values :default nil)) :nil-safe) (def-komtype static-server-info ((boot-time :read-only t) (save-time :read-only t) (db-status :read-only t) (existing-texts :read-only t) (highest-text-no :read-only t) (existing-confs :read-only t) (existing-persons :read-only t) (highest-conf-no :read-only t)) :nil-safe) (def-komtype scheduling-info ((priority :read-only t) (weight :read-only t)) :nil-safe) ;;; ================================================================ ;;; Utilities (defun text-stat-find-aux (text-stat tag &optional person) "Return a list containing the aux items in TEXT-STAT with tag TAG. If PERSON is non-nil return only those items created by person. Args: TEXT-STAT TAG PERSON" (let ((result nil) (items (text-stat->aux-items text-stat))) (while items (when (and (eq tag (aux-item->tag (car items))) (not (aux-item-flags->deleted (aux-item->flags (car items)))) (or (null person) (eq person (aux-item->creator (car items))))) (setq result (cons (car items) result))) (setq items (cdr items))) (nreverse result))) (defun conf-stat-find-aux (conf-stat tag &optional person) "Return a list containing the aux items in CONF-STAT with tag TAG. If PERSON is non-nil return only those items created by person. Args: CONF-STAT TAG PERSON" (let ((result nil) (items (conf-stat->aux-items conf-stat))) (while items (when (and (eq tag (aux-item->tag (car items))) (not (aux-item-flags->deleted (aux-item->flags (car items)))) (or (null person) (eq person (aux-item->creator (car items))))) (setq result (cons (car items) result))) (setq items (cdr items))) (nreverse result))) (defun lyskom-is-recipient (text-stat conf-no) "Return non-nil if TEXT-STAT has CONF-NO as a recipient." (let ((result nil)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (when (and (memq (misc-info->type misc) lyskom-recpt-types-list) (eq (misc-info->recipient-no misc) conf-no)) (setq result t))) result)) (provide 'lyskom-types) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: clienttypes.el,v 44.27 2004/07/21 11:14:38 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: clienttypes.el ;;;; ;;;; This file contains primitives for the different data types ;;;; in the lyskom elisp client. The types in here are only used ;;;; within this lyskom client. ;;;; ;;;; Authors: Linus Tolke and Inge Wallin ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: clienttypes.el,v 44.27 2004/07/21 11:14:38 byers Exp $\n")) ;;; ================================================================ ;;; read-info ;;; A read-info is used by to tell the client which text to ;;; show next and in which order to step through the conferences ;;; with unread texts. New read-infos are created and deleted ;;; all the time within a session. ;;; ;;; The type is one of the following: ;;; REVIEW - Default review type, created by the kom-review-by-to ;;; and the kom-review-comments ;;; REVIEW-TREE - List of texts created by one of the tree-reading ;;; commands: kom-find-root-review, kom-review-tree ;;; REVIEW-MARK - List of texts created by the review-mark command ;;; REVIEW-FAQ - List of texts created by kom-review-faq or similar ;;; REVIEW-FAQ-TREE - Like REVIEW-TREE but for FAQs ;;; COMM-IN - Type containing the list of comments to a text ;;; FOOTN-IN - Type containing the list of footnotes to a text ;;; CONF - Basic type of unread in a conf. ;;; RE-EDIT-TEXT - Re-edit a failed submission. Buffer is in misc. ;;; PRI-SESSION - Go to prioritized session. ;;; ;;; The types REVIEW-TREE, COMM-IN and FOOTN-IN are created for new for ;;; every text read (recursively) when appropriate. ;;; ;;; The difference between REVIEW, REVIEW-MARK and REVIEW-FAQ is just ;;; that there generate different prompts and different text from ;;; kom-review-stack. ;;; ;;; read-info (def-komtype read-info ((type :read-only t) (conf-stat :read-only t) priority (text-list :read-only t) &optional (comm-to :read-only t) forward (unfetched-texts :read-only t :automatic nil) (misc :read-only t)) :nil-safe) (defsubst read-info-append-text-list (read-info texts) (text-list->append (read-info->text-list read-info) texts)) (defsubst read-info-enter-text-last (read-info text-no) (read-info-append-text-list read-info (list text-no))) ;;; ================================================================ ;;; read-list ;;; ;;; We don't use def-komtype here because the code below relies on ;;; read-lists being a cons of READ-LIST and the data. ;;; ;;; Constructor: (defsubst lyskom-create-read-list () "Create an empty read-list." (cons 'READ-LIST nil)) ;;; Predicates: (defsubst read-list-isempty (read-list) "Return t if READ-LIST is empty, otherwise return nil." (null (cdr read-list))) ;;; Selectors: (defsubst read-list->first (read-list) "Return the first entry in READ-LIST, or nil if empty." (car-safe (cdr read-list))) (defsubst read-list->nth (read-list n) "Args: READ-LIST N Return element N in READ-LIST or nil if outside the range. The range of valid values for N is [0, num-entries - 1]." (elt (cdr read-list) n)) (defsubst read-list->all-entries (read-list) "Return a list of all entries in READ-LIST." (cdr read-list)) ;;; Other functions: (defsubst read-list-length (read-list) "Return the number of entries in READ-LIST." (length (read-list->all-entries read-list))) ;;; Modifiers: (defsubst set-read-list-empty (read-list) "Empty READ-LIST destructively." (let ((tmp (cdr read-list))) (setcdr read-list nil) (lyskom-traverse read-info tmp (when (eq 'CONF (read-info->type read-info)) (lp--maybe-update-unreads (conf-stat->conf-no (read-info->conf-stat read-info))))))) (defsubst set-read-list-del-first (read-list) "Delete the first entry of READ-LIST if there is one." (let ((el (car (cdr read-list)))) (if (cdr read-list) (setcdr read-list (cdr (cdr read-list)))) (when (and el (eq (read-info->type el) 'CONF)) (lp--maybe-update-unreads (conf-stat->conf-no (read-info->conf-stat el)))))) (defsubst read-list-enter-first (read-info read-list) "Enter READ-INFO first into READ-LIST." (setcdr read-list (cons read-info (cdr read-list))) (when (eq 'CONF (read-info->type read-info)) (lp--maybe-update-unreads (conf-stat->conf-no (read-info->conf-stat read-info)))) ) (defun read-list-enter-text (text-no recipient rlist) "Args: TEXT-NO RECIPIENT RLIST. Add the new text TEXT-NO to any RECIPIENT found in RLIST. RECIPIENT is a conf-stat. Returns t if there was a conference to insert this text into." (let ((inserted nil)) (lyskom-traverse read-info (cdr rlist) (cond ((and (eq 'CONF (read-info->type read-info)) (= (conf-stat->conf-no recipient) (conf-stat->conf-no (read-info->conf-stat read-info)))) (read-info-enter-text-last read-info text-no) (setq inserted t)))) (when inserted (lp--maybe-update-unreads (conf-stat->conf-no recipient))) inserted)) (defun read-list-delete-text (text-no rlist) "Destructively delete all occurances of TEXT-NO from RLIST. RLIST is a list of read-info. Entries of the type REVIEW, REVIEW-FAQ, REVIEW-TREE or REVIEW-MARK are not changed except if they were empty in which case they are removed. Returns the modified RLIST. TEXT-NO may be nil, in which case only empty read-infos on RLIST are removed." (let* ((prev rlist) ;"Previous" cons-celll (curr (cdr rlist))) ;Current cons-cell (while curr (when text-no (cond ((let ((type (read-info->type (car curr)))) ; Don't change REVIEW et c. (memq type lyskom-review-types-list))) (t ; Do change all other entries. (let ((tl (read-info->text-list (car curr)))) (when (text-list->memq tl text-no) (text-list->delq tl text-no) (lp--maybe-update-unreads (conf-stat->conf-no (read-info->conf-stat (car curr))))))))) ;; Delete this element from RLIST if the text-list became or was empty. (if (text-list->empty (read-info->text-list (car curr))) (setcdr prev (cdr curr)) (setq prev curr)) (setq curr (cdr curr)))) rlist) (defun read-list-enter-read-info (read-info rlist &optional before) "Destructively insert READ-INFO in RLIST, sorted by priority. RLIST is a list of read-info. Args: READ-INFO RLIST &optional BEFORE. A new item with the same priority as an item that is alreay on the list will nomally be inserted after the old one, but if BEFORE is non-nil it will be inserted before it." (let ((pri (+ (if before 0 -1) (read-info->priority read-info))) (continue t) (conf-stat (read-info->conf-stat read-info)) (type (read-info->type read-info))) (while continue (cond ((and (eq type 'CONF) (eq (read-info->type (car (cdr rlist))) 'CONF) (eq (conf-stat->conf-no conf-stat) (conf-stat->conf-no (read-info->conf-stat (car (cdr rlist)))))) (read-info-append-text-list (car (cdr rlist)) (text-list->texts (read-info->text-list read-info))) (lp--maybe-update-unreads (conf-stat->conf-no conf-stat)) (setq continue nil)) ((null (cdr rlist)) (setcdr rlist (list read-info)) (setq continue nil)) ((>= pri (read-info->priority (car (cdr rlist)))) (setcdr rlist (cons read-info (cdr rlist))) (setq continue nil)) (t (setq rlist (cdr rlist))))) (when (eq type 'CONF) (lp--maybe-update-unreads (conf-stat->conf-no conf-stat)) ))) (defun read-list-delete-read-info (conf-no rlist) "Destructively removes all the entries for the conf CONF-NO in RLIST. RLIST is a list of read-info." (while (cdr rlist) (if (eq (conf-stat->conf-no (read-info->conf-stat (car (cdr rlist)))) conf-no) (setcdr rlist (cdr (cdr rlist))) (setq rlist (cdr rlist)))) (lp--maybe-update-unreads conf-no)) (defun read-list-rotate (read-list) "Put the first element of READ-LIST last in the same list. The second element will be the new first element." (if (> (length read-list) 2) (let ((first (cdr read-list)) (last (cdr read-list))) (while (cdr last) (setq last (cdr last))) (setcdr last first) (setcdr read-list (cdr first)) (setcdr first nil))) read-list) ;;; ================================================================ ;;; A simple queue ;;; ;;; This is a simple implementation of a queue. The only thing you ;;; can do with it is stuff things at the back of it and remove ;;; things from the front of it. (...and of course do a few tests) ;;; ;;; Author: Inge Wallin (defun lyskom-queue-create () "Create an empty queue." (cons 'QUEUE (cons nil nil))) (defsubst lyskom-queue-enter (queue element) "Enter last into the queue QUEUE the ELEMENT." (let ((elementcell (cons element nil))) (if (null (car (cdr queue))) ; QUEUE is empty (setcar (cdr queue) (setcdr (cdr queue) elementcell)) (setcdr (cdr (cdr queue)) elementcell) (setcdr (cdr queue) elementcell)))) (defsubst lyskom-queue-p (queue) "Return t if QUEUE is a queue, otherwise return nil." (eq (car-safe queue) 'QUEUE)) (defsubst lyskom-queue-isempty (queue) "Return t if QUEUE is empty, otherwise return nil." (null (car (cdr queue)))) (defsubst lyskom-queue->first (queue) "Return the first element of QUEUE or nil if it is empty." (car-safe (car (cdr queue)))) (defsubst lyskom-queue->all-entries (queue) "Return all elements of QUEUE (nil if it is empty)." (car-safe (cdr queue))) ;;UNUSED: lyskom-queue->last (defsubst lyskom-queue->last (queue) "Return the lastelement of QUEUE or nil if it is empty." (car-safe (cdr (cdr queue)))) (defun lyskom-queue-remove-matching (queue pred) "Remove all elements from QUEUE that satisfy PRED." (let ((prev nil) (ptr (car (cdr queue)))) (while ptr (if (funcall pred (car ptr)) (progn (if prev (setcdr prev (cdr ptr)) (setcar (cdr queue) (cdr ptr))) (unless (cdr ptr) (setcdr (cdr queue) prev))) (setq prev ptr)) (setq ptr (cdr ptr))))) (defsubst lyskom-queue-make-empty (queue) "Make the queue QUEUE empty." (setcdr queue (cons nil nil))) ;;UNUSED: lyskom-queue-set-data (defsubst lyskom-queue-set-data (queue data) (lyskom-queue-make-empty queue) (setcdr queue (cons data (last data)))) (defsubst lyskom-queue-delete-first (queue) "Delete the first element of QUEUE and return it. If QUEUE is empty return nil and do nothing." (if (lyskom-queue-isempty queue) nil (prog1 (lyskom-queue->first queue) (setcar (cdr queue) (cdr (car (cdr queue)))) (if (null (car (cdr queue))) (setcdr (cdr queue) nil))))) ;;; ================================================================ ;;; A simple stack ;;; ;;; This is an implementation of a simple stack. ;;; ;;; Author: Inge Wallin (defun lyskom-stack-create () "Create an empty stack" (cons 'STACK nil)) (defun lyskom-stack-p (stack) "Return t if STACK is a lyskom-stack, otherwise return nil." (eq (car-safe stack) 'STACK)) (defun lyskom-stack-push (stack element) "Push the second arg ELEMENT onto the first arg STACK" (setcdr stack (cons element (cdr stack)))) (defun lyskom-stack-pop (stack) "Remove the topmost element from STACK and return it. If the stack is empty, return nil" (prog1 (car-safe (cdr stack)) (setcdr stack (cdr-safe (cdr stack))))) (defun lyskom-stack->top (stack) "Return the topmost element of STACK or nil if it is empty." (car-safe (cdr stack))) ;;UNUSED: lyskom-stack->length (defun lyskom-stack->length (stack) "Return the number of elements on STACK." (length (cdr stack))) ;;UNUSED: lyskom-stack->nth (defun lyskom-stack->nth (stack n) "Return element no (second arg) N of the stack (first arg) STACK. N counts from zero. If the length of STACK is less than N, nil is returned." (nth n (cdr stack))) (defun lyskom-stack->all-entries (stack) "Return a list of all entries in STACK. The element last pushed is first in the list." (cdr stack)) (defsubst lyskom-stack-isempty (stack) "Returns non-nil if the STACK is empty." (not (cdr stack))) ;;; ================================================================ ;;; format-state (def-komtype format-state (format-string start argl length result delayed-propl delayed-overlays delayed-content depth) :nil-safe) ;;; ================================================================ ;;; ====================================================================== ;;; ;;; collector ;;; ;;; A collector is used when a handler needs to pass information ;;; back to a function using asynchronous calls. You could use ;;; dynamically scoped variables, but that causes problems when ;;; the user quits before all handlers have been called since the ;;; result variable will be out of scope for the remaining handlers. ;;; The best-case scenario will be a crash. The worst-case scenario ;;; is when the handler clobbers another variable with the same name ;;; that has come into scope. ;;; ;;; So, so collect a number of results, do the following: ;;; ;;; (setq (make-collector)) ;;; ( ;;; (initiate- ' )) ;;; (lyskom-wait-queue ') ;;; ( (collector->value )) ;;; ;;; where function is something like this: ;;; ;;; (defun (data-från-servern collector) ;;; (set-collector->value collector ;;; (cons ( data-från-servern) ;;; (collector->value collector)))) ;;; ;;; or shorter, ;;; ;;; (defun (data-från-servern collector) ;;; (collector-push ( data-från-servern))) ;;; ;;; This sidestepping protects the handler from scope changes. ;;; (defun make-collector () "Create a data type for collecting asynchronous results safely" (cons 'COLLECTOR nil)) (defsubst collector->value (collector) "Get the current value of a collector" (cdr collector)) (defsubst set-collector->value (collector value) "Set the calue of a collector" (setcdr collector value)) (defun collector-push (value collector) "Push VALUE onto the front of COLLECTOR's value" (setcdr collector (cons value (cdr collector)))) ;;; ================================================================ ;;; Specification for text links (cached) ;;; ;;; We don't use def-komtype since the accessors should be able to ;;; work on user settings too. (defun lyskom-create-lyskom-text-link (pattern replacement highlight ignore-case) (cons 'LYSKOM-TEXT-LINK (vector pattern replacement highlight ignore-case))) (defsubst lyskom-text-link->pattern (link) (if (symbolp (car link)) (elt (cdr link) 0) (elt link 0))) (defsubst lyskom-text-link->replacement (link) (if (symbolp (car link)) (elt (cdr link) 1) (elt link 1))) (defsubst lyskom-text-link->highlight (link) (if (symbolp (car link)) (elt (cdr link) 2) (elt link 2))) (defsubst lyskom-text-link->ignore-case (link) (if (symbolp (car link)) (elt (cdr link) 3) (elt link 3))) (eval-and-compile (provide 'lyskom-clienttypes)) ;;; clienttypes.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: faces.el,v 44.8 2004/10/28 18:51:55 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: faces.el ;;;; ;;;; Code to handle faces in LysKOM ;;;; ;;;; ================================================================ ;;;; Faces in LysKOM ;;;; ;;;; There are a bunch of face variables that define witch face to use ;;;; in various roles. By using variables as a secnod level of ;;;; indirection it is possible to have divveret faces in different ;;;; buffers. ;;;; ;;;; The concept of face schemes that was used in versions up to ;;;; and including 0.47.1 is completely out the door. ;;;; ================================================================ ;;;; TODO: ;;;; ;;;; Setup faces from resources? Do we need that any more? Or will ;;;; defface take care of it for us? ;;;; ;;;; Remove old code. ;;;; ;;;; In the customization buffer we need a new widget type that ;;;; can open customization of a face. ;;;; ;;;; The customization buffer should provide a choice for the ;;;; user of nil, the "factory default" and a specific face. ;;;; ;;;; Other than that, it's more or less done. (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: faces.el,v 44.8 2004/10/28 18:51:55 byers Exp $\n")) ;;; ================================================================ ;;; Face variables ;;; ;;; Here's a list of all face variables. Seems to be useful on occasion. ;;; ;;; kom-active-face ;;; kom-url-face ;;; kom-me-face ;;; kom-highlight-face ;;; kom-text-face ;;; kom-subject-face ;;; kom-text-no-face ;;; kom-friends-face ;;; kom-morons-face ;;; kom-presence-face ;;; kom-first-line-face ;;; kom-warning-face ;;; kom-mark-face ;;; kom-dim-face ;;; kom-text-body-face ;;; kom-dashed-lines-face ;;; kom-async-text-body-face ;;; kom-async-dashed-lines-face (def-kom-var kom-active-face 'kom-face--default--active-face "*Face used for most \"clickable\" areas. The value should be either a symbol naming a face or nil. The default value is kom-face--default--active-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-active-strikethrough-face 'kom-face--default--active-strikethrough-face "*Face used for some \"clickable\" areas. The value should be either a symbol naming a face or nil. The default value is kom-face--default--active-strikethrough-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-active-highlight-face 'kom-face--default--active-highlight-face "*Face used for some \"clickable\" areas. The value should be either a symbol naming a face or nil. The default value is kom-face--default--active-highlight-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-url-face 'kom-face--default--url-face "*Face used for URLs. The value should be either a symbol naming a face or nil. The default value is kom-face--default--url-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-me-face 'kom-face--default--me-face "*Face used to show your own name. The value should be either a symbol naming a face or nil. The default value is kom-face--default--me-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-highlight-face 'kom-face--default--highlight-face "*Face used for various highlights. The value should be either a symbol naming a face or nil. The default value is kom-face--default--highlight. This is a LysKOM face variable." server inherited) (def-kom-var kom-subject-face 'kom-face--default--subject-face "*Face used for subject lines. The value should be either a symbol naming a face or nil. The default value is kom-face--default--subject-fac. This is a LysKOM face variable." server inherited) (def-kom-var kom-text-no-face 'kom-face--default--text-no-face "*Face used for text numbers. The value should be either a symbol naming a face or nil. The default value is kom-face--default--text-no-fac. This is a LysKOM face variable." server inherited) (def-kom-var kom-friends-face 'kom-face--default--friends-face "*Face used for people in kom-friends. The value should be either a symbol naming a face or nil. The default value is kom-face--default--friends-fac. This is a LysKOM face variable." server inherited) (def-kom-var kom-morons-face 'kom-face--default--morons-face "*Face used for people in kom-morons. The value should be either a symbol naming a face or nil. The default value is kom-face--default--morons-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-presence-face 'kom-face--default--presence-face "*Face used for presence messages. The value should be either a symbol naming a face or nil. The default value is kom-face--default--presence-f. This is a LysKOM face variable." server inherited) (def-kom-var kom-first-line-face 'kom-face--default--first-line-face "*Face used for the first line header of each text. The value should be either a symbol naming a face or nil. The default value is kom-face--default--first-li. This is a LysKOM face variable." server inherited) (def-kom-var kom-warning-face 'kom-face--default--warning-face "*Face used to display important warnings. The value should be either a symbol naming a face or nil. The default value is kom-face--default--warning-fac. This is a LysKOM face variable." server inherited) (def-kom-var kom-mark-face 'kom-face--default--mark-face "*Face used for temporary marks. The value should be either a symbol naming a face or nil. The default value is kom-face--default--mark-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-dim-face 'kom-face--default--dim-face "*Face used to display dimmed items, such as passive memberships. The value should be either a symbol naming a face or nil. The default value is kom-face--default--dim-face. This is a LysKOM face variable." server inherited) (def-kom-var kom-text-body-face nil "*Face to use to modify text bodies. The value should be either a symbol naming a face or nil. If this is set to nil, a face with a background that differs ever so slightly from the default background will be created. The default value is nil. This is a LysKOM face variable." server inherited) (def-kom-var kom-dashed-lines-face nil "*Face to use to modify the dashed lines before and after texts. The value should be either a symbol naming a face or nil. If this is set to nil, a face with a background that differs slightly from the default background will be created. The default value is nil. This is a LysKOM face variable." server inherited) (def-kom-var kom-async-text-body-face nil "*Face to use to modify asynchronos message bodies. The value should be either a symbol naming a face or nil. If this is set to nil, a face with a background that differs ever so slightly from the default background will be created. The default value is nil. This is a LysKOM face variable." server inherited) (def-kom-var kom-async-dashed-lines-face nil "*Face to use to modify dashed lines around asynchronous messsages. The value should be either a symbol naming a face or nil. If this is set to nil, a face with a background that differs slightly from the default background will be created. The default value is nil. This is a LysKOM face variable." server inherited) (def-kom-var lyskom-default-text-body-face nil "Default text body face." inherited) (def-kom-var lyskom-default-async-text-body-face nil "Default text body face." inherited) (def-kom-var lyskom-default-dashed-lines-face nil "Default text body face." inherited) (def-kom-var lyskom-default-async-dashed-lines-face nil "Default text body face." inherited) ;;; ================================================================ ;;; Main entry points (defun lyskom-setup-faces-for-buffer () "Set up faces for the current buffer." (setq lyskom-default-text-body-face nil) (setq lyskom-default-dashed-lines-face nil) (setq lyskom-default-async-text-body-face nil) (setq lyskom-default-async-dashed-lines-face nil) (condition-case nil (let ((faces (lyskom-generate-faces-for-background (or (face-background 'default) (lyskom-frame-property (selected-frame) 'background-color) "#ffffff")))) (setq lyskom-default-text-body-face (cdr (assq 'text-body faces)) lyskom-default-dashed-lines-face (cdr (assq 'dashed-lines faces)) lyskom-default-async-text-body-face (cdr (assq 'async-text-body faces)) lyskom-default-async-dashed-lines-face (cdr (assq 'async-dashed-lines faces)))) (error nil))) ;;; ================================================================ ;;; Background faces ;;; ;;; The faces for text backgrounds cannot be hard-coded. It's OK ;;; to hard-code some known alternatives, but in the general case ;;; we're better off calculating the colors. ;;; ;;; The user can specify faces for these properties, but can also ;;; specify "default", which means calculate the face. ;;; (defvar lyskom-background-faces nil "Pool of background faces. This is an alist of `(COLOR . FACES)' elements, where COLOR is a canonical representation of a background color and FACES is an alist of automatically generated faces to use in that background. Each element of FACES is of the form `(KEY . FACE-NAME)', where KEY is one of `text-body', `dashed-lines', `async-text-body' or `async-dashed-lines', and FACE-NAME is the name of the face to use for the feature specified by KEY. When the faces for a buffer are set, the client will look in this pool for the appropriate faces. If none are found, new faces will be generated and stored in the pool. This list is not consulted at any other time. See `lyskom-background-colors' for additional information.") (defvar lyskom-background-colors '(("#ffffff" (text-body . "#f8f8ff") (dashed-lines . "#e8e8ff") (async-text-body . "#f8fff8") (async-dashed-lines . "#e8ffe8")) ("#000000" (text-body . "#080808") (dashed-lines . "#101010") (async-text-body . "#000020") (async-dashed-lines . "#101030"))) "Specification for special background faces. This is an alist of `(COLOR . SPEC)' elements, where COLOR is a color name and SPEC is an alist specifying background colors to use when the main background is COLOR. Elements in SPEC are `(KEY . COLOR)' where KEY is one of `text-body', `dashed-lines', `async-text-body' or `async-dashed-lines' and COLOR is the name of the background color to use for the feature indicated by KEY. This list is consulted only when generating new faces for a particular background color. Changes to it after starting the client may have no effect. See `lyskom-background-faces' for additional information." ) (defun lyskom-canonicalize-color (color) "Create a canonical string name for color COLOR. COLOR must be a string (a color name)" (apply 'format "#%02x%02x%02x" (mapcar (lambda (x) (lsh x -8)) (lyskom-color-values color)))) (defun lyskom-generate-faces-for-background (background) "Generate highlight faces for background BACKGROUND. BACKGROUND must be a color name. This function updates `lyskom-background-colors' and returns a list that has the same structure as the value of an element in that list. See the documentation for `lyskom-background-colors' for more information." (let* ((color (lyskom-canonicalize-color background)) (cached (cdr (assoc color lyskom-background-faces)))) (unless cached (let* ((text-body-face-name (intern (format "lyskom-generated-text-body-face-%s" color))) (dashed-lines-face-name (intern (format "lyskom-generated-dashed-lines-face-%s" color))) (async-text-body-face-name (intern (format "lyskom-generated-async-text-body-face-%s" color))) (async-dashed-lines-face-name (intern (format "lyskom-generated-async-dashed-lines-face-%s" color))) (predefined (cdr (assoc color lyskom-background-colors))) (weak (lyskom-get-color-highlight (lyskom-color-values background) 0.025)) (strong (lyskom-get-color-highlight (lyskom-color-values background) 0.05)) (text-body-color (or (cdr (assq 'text-body predefined)) weak)) (dashed-lines-color (or (cdr (assq 'dashed-lines predefined)) strong)) (async-text-body-color (or (cdr (assq 'async-text-body predefined)) weak)) (async-dashed-lines-color (or (cdr (assq 'async-dashed-lines predefined)) strong)) ) (make-face text-body-face-name) (set-face-background text-body-face-name text-body-color) (make-face dashed-lines-face-name) (set-face-background dashed-lines-face-name dashed-lines-color) (make-face async-text-body-face-name) (set-face-background async-text-body-face-name async-text-body-color) (make-face async-dashed-lines-face-name) (set-face-background async-dashed-lines-face-name async-dashed-lines-color) (setq cached `((text-body ,text-body-face-name) (dashed-lines ,dashed-lines-face-name) (async-text-body ,async-text-body-face-name) (async-dashed-lines ,async-dashed-lines-face-name))) (setq lyskom-background-faces (cons (cons color cached) lyskom-background-faces)))) cached)) ;;; ================================================================ ;;; Predefined faces ;;; ;;; There are two sets of predefined faces: the defaults and the ;;; user-defined faces. Users should not muck with the defaults. (defface kom-face--default--active-face '((((background light)) (:foreground "blue4") ) (((background dark)) (:foreground "lightblue") ) ) "Face suitable for most \"clickable\" areas. Do not alter this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--active-strikethrough-face '((((background light)) (:foreground "blue4" :strike-through t) ) (((background dark)) (:foreground "lightblue" :strike-through t) ) ) "Face suitable for some \"clickable\" areas. Do not alter this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--active-highlight-face '((((background light)) (:foreground "blue4" :weight bold) ) (((background dark)) (:foreground "lightblue" :weight bold) ) ) "Face suitable for some \"clickable\" areas. Do not alter this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--url-face '((((background light)) (:foreground "blueviolet") ) (((background dark)) (:foreground "moccasin") ) ) "Face suitable for URLs. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--me-face '((((background light)) (:foreground "blue3" :background "lavender" :weight bold) ) (((background dark)) (:foreground "gold" :background "black" :weight bold) ) ) "Face suitable for showing your own name. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--highlight-face '((((background light)) (:background "darkseagreen2") ) (((background dark)) (:background "darkblue") ) ) "Face suitable for various highlights. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--subject-face '((t nil)) "Face suitable for subject lines. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--text-no-face '((((background light)) (:foreground "blue4") ) (((background dark)) (:foreground "lightblue") ) ) "Face suitable for text numbers. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--friends-face '((((background light)) (:foreground "blue3" :background "lavender") ) (((background dark)) (:foreground "red") ) ) "Face suitable for people in kom-friends. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--morons-face '((((background light)) (:foreground "blue3" :background "#ffff60") ) (((background dark)) (:foreground "yellow") ) ) "Face suitable for people in kom-morons. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--presence-face '((((background light)) (:foreground "dim gray" :slant italic) ) (((background dark)) (:foreground "gray" :slant italic) ) ) "Face suitable for presence messages. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--mark-face '((((background light)) (:foreground "blue3" :background "lavender") ) (((background dark)) (:foreground "gold" :background "black") ) ) "Face suitable for temporary marks. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--first-line-face '((t (:weight bold))) "Face suitable for the first line header of each text. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--warning-face '((t (:weight bold :foreground "red"))) "Face suitable for displaying important warnings. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) (defface kom-face--default--dim-face '((t (:foreground "gray"))) "Face suitable for dimmed items, such as passive memberships. Do not change this face unless you know what you're doing." :group 'lyskom-faces ) ;;; ---------------------------------------------------------------- ;;; Dummy faces (copies of the default faces for uses to muck with. ;;; (defface kom-face--user-defined--active-face '((((background light)) (:foreground "blue4") ) (((background dark)) (:foreground "lightblue") ) ) "Face suitable for most \"clickable\" areas." :group 'lyskom-faces ) (defface kom-face--user-defined--active-strikethrough-face '((((background light)) (:foreground "blue4" :strike-through t) ) (((background dark)) (:foreground "lightblue" :strike-through t) ) ) "Face suitable for some \"clickable\" areas." :group 'lyskom-faces ) (defface kom-face--user-defined--active-highlight-face '((((background light)) (:foreground "blue4" :weight bold) ) (((background dark)) (:foreground "lightblue" :weight bold) ) ) "Face suitable for some \"clickable\" areas." :group 'lyskom-faces ) (defface kom-face--user-defined--url-face '((((background light)) (:foreground "blueviolet") ) (((background dark)) (:foreground "moccasin") ) ) "Face suitable for URLs." :group 'lyskom-faces ) (defface kom-face--user-defined--me-face '((((background light)) (:foreground "blue3" :background "lavender" :weight bold) ) (((background dark)) (:foreground "gold" :background "black" :weight bold) ) ) "Face suitable for showing your own name." :group 'lyskom-faces ) (defface kom-face--user-defined--highlight-face '((((background light)) (:background "darkseagreen2") ) (((background dark)) (:background "darkblue") ) ) "Face suitable for various highlights." :group 'lyskom-faces ) (defface kom-face--user-defined--subject-face '((t nil)) "Face suitable for subject lines." :group 'lyskom-faces ) (defface kom-face--user-defined--text-no-face '((((background light)) (:foreground "blue4") ) (((background dark)) (:foreground "lightblue") ) ) "Face suitable for text numbers." :group 'lyskom-faces ) (defface kom-face--user-defined--friends-face '((((background light)) (:foreground "blue3" :background "lavender") ) (((background dark)) (:foreground "red") ) ) "Face suitable for people in kom-friends." :group 'lyskom-faces ) (defface kom-face--user-defined--morons-face '((((background light)) (:foreground "blue3" :background "yellow") ) (((background dark)) (:foreground "yellow") ) ) "Face suitable for people in kom-morons." :group 'lyskom-faces ) (defface kom-face--user-defined--presence-face '((((background light)) (:foreground "dim gray" :slant italic) ) (((background dark)) (:foreground "gray" :slant italic) ) ) "Face suitable for presence messages." :group 'lyskom-faces ) (defface kom-face--user-defined--mark-face '((((background light)) (:foreground "blue3" :background "lavender") ) (((background dark)) (:foreground "gold" :background "black") ) ) "Face suitable for temporary marks." :group 'lyskom-faces ) (defface kom-face--user-defined--first-line-face '((t (:weight bold))) "Face suitable for the first line header of each text." :group 'lyskom-faces ) (defface kom-face--user-defined--warning-face '((t (:weight bold :foreground "red"))) "Face suitable for displaying important warnings." :group 'lyskom-faces ) (defface kom-face--user-defined--dim-face '((t (:foreground "gray"))) "Face suitable for dimmed items, such as passive memberships." :group 'lyskom-faces ) (defvar lyskom-predefined-faces '((kom-active-face . (kom-face--default--active-face kom-face--user-defined--active-face)) (kom-url-face . (kom-face--default--url-face kom-face--user-defined--url-face)) (kom-me-face . (kom-face--default--me-face kom-face--user-defined--me-face)) (kom-highlight-face . (kom-face--default--highlight-face kom-face--user-defined--highlight-face)) (kom-text-face . (kom-face--default--text-face kom-face--user-defined--text-face)) (kom-subject-face . (kom-face--default--subject-face kom-face--user-defined--subject-face)) (kom-text-no-face . (kom-face--default--text-no-face kom-face--user-defined--text-no-face)) (kom-friends-face . (kom-face--default--friends-face kom-face--user-defined--friends-face)) (kom-morons-face . (kom-face--default--morons-face kom-face--user-defined--morons-face)) (kom-presence-face . (kom-face--default--presence-face kom-face--user-defined--presence-face)) (kom-first-line-face . (kom-face--default--first-line-face kom-face--user-defined--first-line-face)) (kom-warning-face . (kom-face--default--warning-face kom-face--user-defined--warning-face)) (kom-mark-face . (kom-face--default--mark-face kom-face--user-defined--mark-face)) (kom-dim-face . (kom-face--default--dim-face kom-face--user-defined--dim-face)) (kom-text-body-face . (kom-face--default--text-body-face kom-face--user-defined--text-body-face)) (kom-dashed-lines-face . (kom-face--default--dashed-lines-face kom-face--user-defined--dashed-lines-face)) (kom-async-text-body-face . (kom-face--default--async-text-body-face kom-face--user-defined--async-text-body-face)) (kom-async-dashed-lines-face . (kom-face--default--async-dashed-lines-face kom-face--user-defined--async-dashed-lines-face)) (kom-active-highlight-face . (kom-face--default--active-highlight-face kom-face--user-defined--active-highlight-face)) (kom-active-strikethrough-face . (kom-face--default--active-strikethrough-face kom-face--user-defined--active-strikethrough-face)) ) "Alist of predefined faces suitable for each face variable. Used for customization and nothing else." ) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: deferred-insert.el,v 44.6 2003/04/05 18:14:25 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: deferred-insert.el ;;;; ;;;; This file includes functions for deffering insertion of ;;;; information into the LysKOM buffer. ;;;; ;;; ;;; How to defer a peice of text: ;;; ============================= ;;; ;;; 1. Insert some temporary text. Use the variable ;;; `lyskom-defer-indicator' as a placeholder. ;;; ;;; 2. Create a defer-info-structure by calling ;;; `lyskom-create-defer-info' with the following parameters ;;; ;;; SERVER-CALL - the call to get the data (initate-get-*) ;;; CALL-ARG - the argument for the server call. This is ;;; limited to a single argument, which is enough ;;; for get-conf-stat and friends. ;;; HANDLER - the function to be called to insert the ;;; "real" data. ;;; POS - a marker indicating where the insertion ;;; should be placed. ;;; DEL-CHARS - an integer indicating how many characters ;;; from POS on should be replaced by the "real" ;;; text. ;;; FORMAT - a format string for inserting the real ;;; data. This should normally only contain a ;;; single format atom using argument 1 ;;; (i.e. "%#1P"). ;;; DATA - any data that you might want to use in ;;; HANDLER. ;;; ;;; 3. Call `lyskom-defer-insertion' with the defer-info as argument. ;;; ;;; 4. Write a handler function that takes two arguments, the server ;;; reply and the defer-info. This function should replace the ;;; temporary text. A convenient way to do this is to use ;;; `lyskom-replace-deferred'. ;;; ;;; 5. Sit back and watch it work. ;;; ;;; Notes: ;;; ;;; POS must be located before the temporary text. DEL-CHARS should ;;; usually be set to (length lyskom-defer-indicator). Don't count on ;;; it to be 5. ;;; ;;; Steps 1 and 2 are often implemented the other way around, or at ;;; least the POS parameter is determined before any text is ;;; inserted. ;;; ;;; You should only defer text if kom-deferred-printing is non-nil. ;;; ;;; Type: defer-info (def-komtype defer-info (server-call call-par handler pos del-chars format &optional data (last-viewed :automatic lyskom-last-viewed))) (defun lyskom-defer-insertion (defer-info) "Defer insertion of something. The insertion will be at (point)." (set-defer-info->last-viewed defer-info lyskom-last-viewed) ;; (goto-char (defer-info->pos defer-info)) (if (and (defer-info->call-par defer-info) (listp (defer-info->call-par defer-info))) (apply (intern-soft (concat "initiate-" (symbol-name (defer-info->server-call defer-info)))) 'deferred (defer-info->handler defer-info) (append (defer-info->call-par defer-info) (list defer-info))) (funcall (intern-soft (concat "initiate-" (symbol-name (defer-info->server-call defer-info)))) 'deferred (defer-info->handler defer-info) (defer-info->call-par defer-info) defer-info))) (defun lyskom-replace-deferred (defer-info &rest replacement-data) "Replace some defered text." (save-excursion (when (marker-buffer (defer-info->pos defer-info)) (set-buffer (marker-buffer (defer-info->pos defer-info)))) (goto-char (defer-info->pos defer-info)) (apply 'lyskom-format-insert-at-point (defer-info->format defer-info) replacement-data) (let ((inhibit-read-only t)) (delete-char (defer-info->del-chars defer-info))) (set-marker (defer-info->pos defer-info) nil)) (if lyskom-executing-command nil (let ((window (get-buffer-window lyskom-buffer))) (if window (if (pos-visible-in-window-p (point-max) window) nil ;; This means that this insertion moved point out of the ;; window. The scrolling becomes tricky. One big problem is ;; that we can't use lyskom-last-viewed, because it has been ;; updated to the new prompt. Until that is solved we make ;; sure that we never scroll. ;; ;; The solution is to save lyskom-last-viewed in the defer-info (save-selected-window (select-window window) (lyskom-scroll)) ))))) (defun lyskom-deferred-insert-conf (conf-stat defer-info) "Insert the name of a conference at a previously reserved place." (lyskom-replace-deferred defer-info (if (null conf-stat) (lyskom-format (or (defer-info->data defer-info) (if (= (aref (defer-info->format defer-info) (1- (length (defer-info->format defer-info)))) ?P) (if (= (defer-info->call-par defer-info) 0) 'person-is-anonymous 'person-does-not-exist) 'conference-does-not-exist)) (defer-info->call-par defer-info)) conf-stat) (text-properties-at (defer-info->pos defer-info)))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: utilities.el,v 44.160 2005/01/23 16:25:31 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: utilities.el ;;;; ;;;; This file contains general lisp utility functions and ;;;; lyskom-specific utility functions (such as date formatting and ;;;; minibuffer reading) ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: utilities.el,v 44.160 2005/01/23 16:25:31 byers Exp $\n")) (defvar coding-category-list) (defun lyskom-check-configuration () ;; Excuse my paranoia. This code is hardly tested at all, so I ;; really want it wrapped to prevent errors from breaking the ;; client. Plus it lets me check how to do stuff in Gnu Emacs 21 ;; without worrying about compatibility with other versions. (when kom-check-configuration-on-startup (condition-case nil (progn ;; Check that we have MULE (when (and (>= emacs-major-version 20) (boundp 'enable-multibyte-characters) (not enable-multibyte-characters)) (lyskom-format-insert 'no-mule-warning `(face ,kom-warning-face) )) ;; Check coding system (when (and enable-multibyte-characters (not (memq 'utf-8 (lyskom-coding-system-get (symbol-value (car coding-category-list)) 'alias-coding-systems))) (not (memq lyskom-server-coding-system (lyskom-coding-system-get (symbol-value (car coding-category-list)) 'alias-coding-systems)))) (lyskom-format-insert 'coding-system-mismatch-warning (symbol-value (car coding-category-list)) lyskom-server-coding-system `(face ,kom-warning-face) )) ) (error nil) ))) ;;; ;;; Lisp utility functions ;;; (defsubst listify-vector (vector) "Turn VECTOR into a list" (append vector nil)) (defun nfirst (n list) "Return a list of the N first elements of LIST." (let ((result nil)) (while (and (> n 0) list) (setq result (cons (car list) result) list (cdr list) n (1- n))) (nreverse result))) (defun lyskom-rotate-list (list el) "Destructively rotate LIST so EL becomes the first element. If EL occurs more than one, the first occurrence is used." (let ((tail (memq el list))) (if (or (null tail) (eq el (car list))) list (setcdr (nthcdr (- (length list) (length tail) 1) list) nil) (setcdr (nthcdr (1- (length tail)) tail) list) tail))) (defun lyskom-preceding-cons (list el) "Return the cons cell of LIST preceding the first cons cell whose car is EL. Return nil if TAIL is the same as LIST or not a member of LIST." (unless (or (eq (car list) el) (not (memq el list))) (nthcdr (- (length list) (length (memq el list)) 1) list))) (defun lyskom-insert-in-list (el list before) "Destructively insert EL in LIST before element BEFORE. If BEFORE is not in the list, then insert EL at the end of the list." (cond ((eq before (car list)) (cons el list)) (t (setcdr (nthcdr (- (length list) (length (memq before list)) 1) list) (cons el (memq before list))) list))) (defun lyskom-move-in-list (el list pos) "Destructively move EL within LIST so it appears at position POS." (when (memq el list) (setq list (delq el list)) (cond ((eq 0 pos) (setq list (cons el list))) (t (setcdr (nthcdr (1- pos) list) (cons el (nthcdr pos list)))))) list) ;;; ;;; +++ FIXME: If cl.el can be guaranteed, this is pointless. ;;; (defun lyskom-butlast (x &optional n) "Returns a copy of LIST with the last N elements removed." (if (and n (<= n 0)) x (lyskom-nbutlast (copy-sequence x) n))) (defun lyskom-nbutlast (x &optional n) "Modifies LIST to remove the last N elements." (let ((m (length x))) (or n (setq n 1)) (and (< n m) (progn (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil)) x)))) (defun filter-list (test list) (let ((result nil)) (lyskom-traverse el list (when (funcall test el) (setq result (cons el result)))) (nreverse result))) ;;;============================================================ ;;; ;;; Utility functions. ;;; ;;; These should be shared in LysKOM ;;; (defun lyskom-ignore (&rest args) "Ignore all arguments" ) (defun lyskom-mapcar2 (fn seq1 seq2) (let (result) (while (and seq1 seq2) (setq result (cons (funcall fn (car seq1) (car seq2)) result)) (setq seq1 (cdr seq1) seq2 (cdr seq2))) (nreverse result))) (defun lyskom-maxint () (let ((n 1) (l nil) (i 31)) (while (and (> n 0) (> i 0)) (setq l (cons n l)) (setq n (* 2 n)) (setq i (1- i))) (apply '+ l))) ;; Set lyskom-maxint correctly (setq lyskom-max-int (lyskom-maxint)) (defun lyskom-try-require (feature &optional message &rest args) "Load the feature FEATURE using require. If optional MESSAGE is non-nil, use it as a LysKOM format string taking one string argument to print an error message. Remaining arguments are used as arguments for the format string. Returns t if the feature is loaded or can be loaded, and nil otherwise." (or (featurep 'feature) (condition-case nil (progn (require feature) t) (error (when message (apply 'lyskom-format-insert-before-prompt message (symbol-name feature) args)) nil)))) (defvar lyskom-apo-timeout 0 "Current millisecond timeout value for accept-process-output") (defvar lyskom-apo-timeout-index 0 "Index in lyskom-apo-timeout-vector-max where last timeout is") (defconst lyskom-apo-timeout-vector [0 1000 1000 2000 3000 5000 8000 13000 21000 34000 55000 89000 144000 233000 377000 610000] "Vector of timeout values (usecs) for accept-process-output") (defconst lyskom-apo-timeout-vector-max (1- (length lyskom-apo-timeout-vector)) "Maximum index in lyskom-apo-timeout-vector") (defun lyskom-next-apo-timeout () (if (< lyskom-apo-timeout-index lyskom-apo-timeout-vector-max) (setq lyskom-apo-timeout (aref lyskom-apo-timeout-vector (setq lyskom-apo-timeout-index (1+ lyskom-apo-timeout-index)))))) (defun lyskom-reset-apo-timeout () (setq lyskom-apo-timeout-index -1) (setq lyskom-apo-timeout 0)) (defun lyskom-accept-process-output () "Call accept-process-output with the correct timeout values." (lyskom-next-apo-timeout) (accept-process-output nil 0 lyskom-apo-timeout)) (defun lyskom-set-alist (alist item value) "Modifies (non-destructively) an alist ALIST to set item ITEM to the value VALUE." (let ((pair (assq item alist))) (if pair (progn (setcdr pair value) alist) (cons (cons item value) alist)))) ;;; ;;; WARNING! ;;; ;;; The following variable is *important* if you fuck it up in any ;;; way, the functions used to read conference names won't work. So if ;;; you change it, try to work one character at a time, and when ;;; you're done, run through the mappings of all 256 characters to ;;; make sure they look OK. ;;; ;;; Make sure your MULE Emacs doesnt fuck it up for you. It did for me. ;;; (defvar lyskom-default-collate-table "\000\001\002\003\004\005\006\007\010 \012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]~\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237 !¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿AAAA[]ACEEEEIIIIÐNOOOO\\×OUUUYYÞßAAAA[]ACEEEEIIIIðNOOOO\\÷OUUUYYþÿ" "String mapping characters to their collate class. Lowercase, uppercase and other equivalents are mapped to the same class. The class number defines a proper sorting order.") (defsubst lyskom-maybe-recode-string (s &optional coding force) "Change the encoding of S for when multibyte characters are not supported. Optional second argument CODING is the coding system to use. If optional third argument FORCE is non-nil, always encode multibyte strings, otherwise only encode when multibyte strings are not supported." (if (and (lyskom-multibyte-string-p s) (or force (not enable-multibyte-characters))) (lyskom-encode-coding-string s (or coding (and lyskom-language (lyskom-language-coding lyskom-language)) 'raw-text)) s)) (defun lyskom-recode-string-for-title (s coding) "Encode S with CODING for use in frame titles. Attempts to encode the string only in Emacs versions that do not require MULE coding for frame titles" (cond ((memq window-system '(win32 mswindows w32)) (lyskom-maybe-recode-string s coding t)) ((> emacs-major-version 20) s) (t (lyskom-maybe-recode-string s coding t)))) (defun lyskom-maybe-frob-completion-table (table &optional copy) "Recode the cars of alist TABLE to default coding system unless multibyte characters are enabled. This function is destructive unless optional copy is non-nil." (cond (enable-multibyte-characters table) (copy (mapcar (lambda (el) (cons (lyskom-maybe-recode-string (car el) nil t) (cdr el))) table)) (t (lyskom-traverse el table (setcar el (lyskom-maybe-recode-string (car el) nil t))) table))) (defsubst lyskom-unicase-char (c) "Smash case and diacritical marks on c." (if (< (lyskom-char-to-int c) (length lyskom-collate-table)) (aref lyskom-collate-table (lyskom-char-to-int c)) (setq c (lyskom-encode-coding-char c lyskom-server-coding-system)) (if (and c (< (lyskom-char-to-int c) (length lyskom-collate-table))) (aref lyskom-collate-table (lyskom-char-to-int c)) c))) (defun lyskom-unicase (s) "Smash case and diacritical marks of all chars in s." (lyskom-save-excursion (and lyskom-buffer (set-buffer lyskom-buffer)) (let* ((s2 (string-to-vector (lyskom-encode-coding-string s lyskom-server-coding-system))) (l (length s2))) (while (> l 0) (setq l (1- l)) (aset s2 l (lyskom-unicase-char (aref s2 l)))) (concat s2)))) (defun lyskom-looking-at (s) "Version of looking-at that will work in Gnu Emacs 20.3" (save-excursion (let ((start (point))) (and (re-search-forward s nil t) (eq (match-beginning 0) start))))) ;; Don't slow things down with our own looking-at unless we have to (eval-and-compile (condition-case nil (if (and (eq emacs-major-version 20) (eq emacs-minor-version 3)) nil (fset 'lyskom-looking-at (symbol-function 'looking-at))) (error nil))) (defun lyskom-compute-char-classes (map) "Find out which characters that are equivalent according to MAP. MAP should be a collate table. The return value is an assoc list, which characters as keys, and a list of single-character strings as values. Only characters that are equivalent to at least one more character is returned in the assoc list. Example: if this function returns ((97 \"A\" \"a\") (65 \"A\" \"a\") (48 \"O\" \"o\" \"0\") (111 \"O\" \"o\" \"0\") (79 \"O\" \"o\" \"0\")) it means that a and A are equivalent, and o, O and 0 are equivalent. All other characters are unique." (lyskom-save-excursion (and lyskom-buffer (set-buffer lyskom-buffer)) (let ((ix (length map)) (cls-to-strings nil)) ;assoc-list from equivalence class to ;list of chars (while (> ix 0) (setq ix (1- ix)) (let* ((cls (aref map ix)) (str (lyskom-decode-coding-string (concat (vector ix)) lyskom-server-coding-system)) (elem (assoc cls cls-to-strings))) (if elem (rplacd elem (cons str (cdr elem))) (setq cls-to-strings (cons (list cls str) cls-to-strings))))) (let ((res nil)) (while cls-to-strings (let ((lst (cdr (car cls-to-strings)))) (if (> (length lst) 1) (while lst (setq res (cons (cons (string-to-char (car lst)) (cdr (car cls-to-strings))) res)) (setq lst (cdr lst))))) (setq cls-to-strings (cdr cls-to-strings))) res)))) ;; Stolen from thingatpt.el ;; FIXME: We may not really need this function. Check the callers. (defun lyskom-thing-at-point-looking-at (regexp) "Return non-nil if point is in or just after a match for REGEXP. Set the match data from the earliest such match ending at or after point." (save-excursion (let ((old-point (point)) match) (and (looking-at regexp) (>= (match-end 0) old-point) (setq match (point))) ;; Search back repeatedly from end of next match. ;; This may fail if next match ends before this match does. (re-search-forward regexp nil 'limit) (while (and (re-search-backward regexp nil t) (or (> (match-beginning 0) old-point) (and (looking-at regexp) ; Extend match-end past search start (>= (match-end 0) old-point) (setq match (point)))))) (if (not match) nil (goto-char match) ;; Back up a char at a time in case search skipped ;; intermediate match straddling search start pos. (while (and (not (bobp)) (progn (backward-char 1) (looking-at regexp)) (>= (match-end 0) old-point) (setq match (point)))) (goto-char match) (looking-at regexp))))) ;; Stolen from Gnu Emacs (defun lyskom-truncate-string-to-width (str end-column &optional trailer) "Truncate string STR to end at column END-COLUMN. If optional TRAILER is non-nil, it is a string to append if STR is truncated. The total width will still be at most END-COLUMN." (when (and trailer (>= (lyskom-string-width trailer) end-column)) (setq trailer nil)) (cond ((< (lyskom-string-width str) end-column) str) (t (when trailer (setq end-column (- end-column (lyskom-string-width trailer)))) (let ((idx 0) (column 0) (len (length str)) ch last-column last-idx) (condition-case nil (while (< column end-column) (setq last-column column last-idx idx ch (aref str idx) column (+ column (lyskom-char-width ch)) idx (1+ idx))) (args-out-of-range (setq idx len))) (if (> column end-column) (setq column last-column idx last-idx)) (setq str (substring str 0 idx)) (when trailer (setq str (concat str trailer))) str)))) (defun lyskom-buffer-display-message (string &optional buffer) (let* ((inhibit-read-only t) (buffer (or buffer (current-buffer))) (window (cdr (assoc (selected-frame) (mapcar (lambda (x) (cons (window-frame x) x)) (get-buffer-window-list buffer)))))) (erase-buffer) (unless window (setq window (display-buffer buffer))) (select-window window) (delete-other-windows window) (insert (make-string (/ (window-height window) 3) ?\n)) (insert string) (center-region (point-min) (point-max)) (goto-char (point-min)) (fundamental-mode) (toggle-read-only t))) (eval-and-compile (lyskom-xemacs-or-gnu (fset 'lyskom-string= (symbol-function 'string=)) (if (< emacs-major-version 20) (fset 'lyskom-string= (symbol-function 'string=)) (defun lyskom-string= (s1 s2) (string= (and s1 (if (lyskom-multibyte-string-p s1) s1 (lyskom-decode-coding-string s1 (lyskom-language-coding lyskom-language)))) (and s2 (if (lyskom-multibyte-string-p s2) s2 (lyskom-decode-coding-string s2 (lyskom-language-coding lyskom-language))))))))) (defun lyskom-string-assoc (key list) "Return non-nil if KEY is the same string as the car of an element of LIST. The value is actually the element of LIST whose car equals KEY." (let ((s (and key (downcase key))) (result nil)) (while list (when (lyskom-string= s (downcase (car (car list)))) (setq result (car list)) (setq list nil)) (setq list (cdr list))) result)) (defun lyskom-string-member (key list) "Return non-nil if KEY is the same string as the car of an element of LIST. The value is actually the element of LIST whose car equals KEY." (let ((s (and key (downcase key))) (result nil)) (while list (when (lyskom-string= s (downcase (car list))) (setq result (car list)) (setq list nil)) (setq list (cdr list))) result)) (defun lyskom-string-rassoc (key list) "Return non-nil if KEY is the same string as the cdr of an element of LIST. The value is actually the element of LIST whose car equals KEY." (let ((s (and key (downcase key))) (result nil)) (while list (when (lyskom-string= s (downcase (cdr (car list)))) (setq result (car list)) (setq list nil)) (setq list (cdr list))) result)) (defun lyskom-set-default (sym val) "Set the value of SYM in the LysKOM buffer to VAL." (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) (bufferp lyskom-buffer) (buffer-live-p lyskom-buffer) lyskom-buffer) (current-buffer))) (set sym val))) (defun lyskom-default-value (sym) "Get the value of SYM in the LysKOM buffer" (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) (bufferp lyskom-buffer) (buffer-live-p lyskom-buffer) lyskom-buffer) (current-buffer))) (symbol-value sym))) (defun lyskom-default-value-safe (sym) "Get the value of SYM in the LysKOM buffer" (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) (bufferp lyskom-buffer) (buffer-live-p lyskom-buffer) lyskom-buffer) (current-buffer))) (and (boundp sym) (symbol-value sym)))) ;;; ============================================================ ;;; Prefix arguments (defun lyskom-get-ancestors-of-text (text-no level) "Returns a list of all ancestors of TEXT-NO that are LEVEL comment/foot-note levels up the comment tree. LEVEL is a non-negative integer and 0 means the given text-no." (if (< level 1) (list text-no) (let* ((text-stat (blocking-do 'get-text-stat text-no)) (ancestors (and text-stat (lyskom-text-stat-commented-texts text-stat))) (level (1- level)) (result '())) (while ancestors (setq result (lyskom-union (lyskom-get-ancestors-of-text (car ancestors) level) result )) (setq ancestors (cdr ancestors))) result))) (defun lyskom-maybe-get-commented-text () (let* ((text-no (lyskom-text-at-point)) (text-stat (and text-no (blocking-do 'get-text-stat text-no)))) (when text-no (if (lyskom-misc-infos-from-list 'COMM-IN (text-stat->misc-info-list text-stat)) text-no (lyskom-get-text-at-point-ancestor 1))))) (defun lyskom-maybe-get-footnoted-text () (let* ((text-no (lyskom-text-at-point)) (text-stat (and text-no (blocking-do 'get-text-stat text-no)))) (when text-no (if (lyskom-misc-infos-from-list 'FOOTN-IN (text-stat->misc-info-list text-stat)) text-no (lyskom-get-text-at-point-ancestor 1))))) (defun lyskom-get-last-read-text () (lyskom-default-value 'lyskom-current-text)) (defun lyskom-get-previous-text () (lyskom-default-value 'lyskom-previous-text)) (defun lyskom-get-text-at-point () (lyskom-text-at-point)) (defun lyskom-get-text-at-point-ancestor (arg) (let* ((text (lyskom-text-at-point)) (cnos (and text (lyskom-get-ancestors-of-text text arg))) (txts (length cnos))) (cond ((not text) (lyskom-error (lyskom-get-string 'no-text-at-point))) ((eq txts 0) (lyskom-error (lyskom-get-string 'no-comment-to))) ((eq txts 1) (car cnos)) (t (lyskom-read-number (lyskom-get-string 'what-ancestor) (car cnos) nil nil cnos))))) (defun lyskom-get-last-text-written-by-me () (lyskom-default-value 'lyskom-last-written)) (defun lyskom-get-last-written-or-read-by-me () (lyskom-default-value 'lyskom-last-seen-written)) (defun lyskom-get-text-above-point (arg) (save-excursion (let ((former-point (point))) (backward-text (+ 1 arg)) (if (looking-at "\\([0-9]+\\)\\s-") (string-to-int (match-string 1)) (progn ;; we probably ended up above the first message in the buffer (forward-text) (if (and (< (point) former-point) (looking-at "\\([0-9]+\\)\\s-")) (string-to-int (match-string 1)) (lyskom-error (lyskom-get-string 'bad-text-no-prefix) arg))))))) (defun lyskom-get-text-below-point (arg) (if (and (numberp arg) (> arg 20)) arg (save-excursion (let ((former-point (point))) (forward-text arg) (if (looking-at "\\([0-9]+\\)\\s-") (string-to-int (match-string 1)) (progn ;; we probably ended up below the final message in the buffer (backward-text) (if (and (> (point) former-point) (looking-at "\\([0-9]+\\)\\s-")) (string-to-int (match-string 1)) (lyskom-error (lyskom-get-string 'bad-text-no-prefix) arg)))))))) (defun lyskom-read-text-no-prompt-p (command) "Return non-nil if the COMMAND should prompt for a text number." (let ((check (assq command kom-text-no-prompts))) (if check (cdr check) (memq command lyskom-text-no-prompts-defaults)))) ;;; ------------------------------------------------------------ ;;; Constraints (defun lyskom-text-written-by-me-p (text-no) (let ((text-stat (blocking-do 'get-text-stat text-no))) (and text-stat (lyskom-is-supervisor (text-stat->author text-stat) lyskom-pers-no)))) ;;; ------------------------------------------------------------ ;;; Functions used in predicates and strategies (defun lyskom-eq-dash (e) (eq e '-)) (defun lyskom-tnpa-prompt (text-nos) (lyskom-tnpa-add-property text-nos 'prompt)) (defun lyskom-tnpa-valid (text-nos) (lyskom-tnpa-add-property text-nos 'valid)) (defun lyskom-tnpa-add-property (text-nos what) (cond ((numberp text-nos) (vector text-nos (list what))) ((vectorp text-nos) (aset text-nos 1 (cons what (aref text-nos 1))) text-nos) ((and text-nos (listp text-nos)) (mapcar (lambda (el) (cond ((vectorp el) (aset el 1 (cons what (aref el 1)))) (t (vector el (list what))))) text-nos)))) (defsubst lyskom-tnpa-text-no (el) (if (vectorp el) (aref el 0) el)) (defsubst lyskom-tnpa-text-property (el prop) (and (vectorp el) (memq prop (aref el 1)))) ;;; ------------------------------------------------------------ ;;; The main function (defun lyskom-tnpa-apply-strategy (strategies filter-spec constraint-spec) (let ((filter-locl (car (cdr (memq :filter strategies)))) (constraint-locl (car (cdr (memq :constraint strategies))))) (lyskom-traverse strategy strategies (if (memq strategy '(:filter :constraint :save)) (lyskom-traverse-break) (let ((tmp (cond ((functionp strategy) (funcall strategy)) ((and (symbolp strategy) (boundp strategy)) (symbol-value strategy)) (t nil)))) (unless (listp tmp) (setq tmp (list tmp))) (when filter-locl (setq tmp (mapcar filter-locl tmp))) (when filter-spec (setq tmp (mapcar filter-spec tmp))) (when (or constraint-spec constraint-locl) (setq tmp (delq nil (mapcar (lambda (el) (when (or (lyskom-tnpa-text-property el 'valid) (and (or (null constraint-locl) (funcall constraint-locl (lyskom-tnpa-text-no el))) (or (null constraint-spec) (funcall constraint-spec (lyskom-tnpa-text-no el))))) el)) tmp)))) (when tmp (lyskom-traverse-break (car tmp)))))))) (defun lyskom-read-text-no-prefix-arg (prompt &optional command) (when (listp prompt) (setq prompt (car prompt))) (let* ((command (or command lyskom-current-command this-command)) (command-spec (cdr (assq command kom-pick-text-no-strategy-alist))) (refer-spec (car (cdr (memq :refer command-spec)))) (default-spec (cdr (assq t kom-pick-text-no-strategy-alist))) (filter-spec (car (cdr (or (memq :filter command-spec) (memq :filter default-spec))))) (constraint-spec (car (cdr (or (memq :constraint command-spec) (memq :constraint default-spec))))) (text nil)) (if refer-spec (lyskom-read-text-no-prefix-arg prompt refer-spec) ;; Traverse all strategy lists, in the appropriate order. ;; Identical predicates are only called once. We traverse ;; command-spec and default-spec until we find an applicable ;; element (one that matches the prefix argument). When we find ;; that element, we call its strategies until we find one that ;; generates a result that passes the filter and the constraint. ;; ;; If we never find an element, we use the t predicates in the ;; specification. These are fallbacks and only applied if no ;; strategy provides a text number. ;; ;; The exit from this block should give us a text (perhaps with ;; properties) that we can either use or prompt for. ;; ;; Using catch and throw significantly simplifies this code. (setq text (catch 'lyskom-tnpa-text (let ((handled nil)) (lyskom-traverse spec-list (list command-spec default-spec) (lyskom-traverse el spec-list (if (not (listp el)) (lyskom-traverse-break) ; We hit :filter or something like that (cond ((memq (car el) handled)) ; Already handled once ((eq (car el) t)) ; Defaults are handled after this loop ((or (eq (car el) current-prefix-arg) (condition-case nil (funcall (car el) current-prefix-arg) (error nil))) ;; The predicate matches the perfix argument, so now we can ;; evaluate the strategies. (let ((tmp (lyskom-tnpa-apply-strategy (cdr el) filter-spec constraint-spec))) (when tmp (throw 'lyskom-tnpa-text tmp))))) (setq handled (cons (car el) handled)))))) ;; The strategies failed to yield anything useful Apply ;; the default strategies, both from the command and from ;; the default strategy list.. (throw 'lyskom-tnpa-text (or (lyskom-tnpa-apply-strategy (cdr (assq t command-spec)) filter-spec constraint-spec) (lyskom-tnpa-apply-strategy (cdr (assq t default-spec)) filter-spec constraint-spec))) )) ;; We now have a text that fits the constraint. Really, the only ;; thing to do at this point is prompt for the text, if that is ;; requested. (if (or (not (lyskom-tnpa-text-no text)) (lyskom-tnpa-text-property text 'prompt) (lyskom-read-text-no-prompt-p lyskom-current-command)) (lyskom-read-number prompt (or (lyskom-tnpa-text-no text) (lyskom-default-value 'lyskom-current-text))) (lyskom-tnpa-text-no text))))) ;;; ============================================================ ;;; Set functions (defun lyskom-subset-p (a b) "Return non-nil if A is a subset of B" (let ((result t)) (while a (if (memq (car a) b) (setq a (cdr a)) (setq result nil a nil))) result)) (defun lyskom-intersection (a b) "Returns as a list the intersection of list A and list B. The order of the list a is kept." (if (or a b) (let ((list nil)) (while a (if (memq (car a) b) (setq list (cons (car a) list))) (setq a (cdr a))) (nreverse list)))) (defun lyskom-union (a b) "Returns a list containing the union of list A and list B. Specifically, concatenate all elements of B that are not in A to the end of A. This operation is destructive and modifies the list pointed to by A." (let ((result nil)) (lyskom-traverse x b (unless (memq x a) (setq result (cons x result)))) (nconc a (nreverse result)))) (defun lyskom-delete-duplicates (list &optional key) "Removes all but one instance of each element in LIST. If optional argument KEY is non-nil, apply KEY to each element before comparison. Comparison is done with eq." (let ((clist (mapcar (lambda (el) (if key (cons (funcall key el) el) (cons el el))) list)) (result nil)) (lyskom-traverse el clist (unless (assq (car el) result) (setq result (cons el result)))) (nreverse (mapcar 'cdr result)))) (defun lyskom-plusp (int) "Returns t for integers greater than 0, nil otherwise." (and (integerp int) (> int 0))) (defun lyskom-minusp (int) "Returns t for integers smaller than 0, nil otherwise." (and (integerp int) (< int 0))) ;;; ====================================================================== ;;; LysKOM Hooks ;;; (defun lyskom-run-hook-with-args (hook &rest args) "Run HOOK with the specified arguments ARGS in the LysKOM buffer. See run-hook-with-args for detailed information." (lyskom-save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) lyskom-buffer) (current-buffer))) (apply 'run-hook-with-args hook args))) (defun lyskom-add-hook (hook function &optional append) "Add to the value of HOOK the function FUNCTION in the LysKOM buffer. If optional APPEND is non-nil, add at the end of HOOK." (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) lyskom-buffer) (current-buffer))) (add-hook hook function append t))) (defun lyskom-remove-hook (hook function) "From the value of HOOK remove the function FUNCTION in the LysKOM buffer." (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) lyskom-buffer) (current-buffer))) (remove-hook hook function t))) ;;; ====================================================================== ;;; Printing ;;; ;;; XEmacs princ does not insert text properties. This function is based ;;; on the C code for princ. ;;; (defun lyskom-princ (object &optional stream) "Output the printed representation of OBJECT, any Lisp OBJECT. No quoting characters are used; no delimiters are printed around the contents of strings. Text properties are retained. Output stream is STREAM, or value of standard-output, and must be a buffer or a marker. Function or minibuffer streams are not supported for strings." (if (not (stringp object)) (princ object stream) (let ((old-point nil) (start-point nil) (old-buffer (current-buffer))) (unwind-protect (progn (cond ((bufferp stream) (set-buffer stream)) ((markerp stream) (setq old-point (point)) (set-buffer (marker-buffer stream)) (goto-char stream) (setq start-point (point))) ((null stream) (cond ((bufferp standard-output) (set-buffer standard-output)) ((markerp standard-output) (setq old-point (point)) (set-buffer (marker-buffer standard-output)) (goto-char standard-output) (setq start-point (point)))))) (insert object)) (cond ((markerp stream) (set-marker stream (point)) (if (>= old-point start-point) (goto-char (+ old-point (- (point) start-point))) (goto-char old-point)))) (set-buffer old-buffer))))) ;;; ====================================================================== ;;; Faces ;;; (make-face 'lyskom-weak-highlight-face) (make-face 'lyskom-strong-highlight-face) (defun lyskom-copy-face (old new) (lyskom-xemacs-or-gnu (copy-face old new nil nil nil 'remove-all) (copy-face old new))) ;;; ============================================================ ;;; Date and time utilities (defun lyskom-current-client-time () "Return time representing current client time." (let ((now (decode-time))) (lyskom-create-time (elt now 0) ;sec (elt now 1) ;min (elt now 2) ;hour (elt now 3) ;mday (elt now 4) ;mon (elt now 5) ;year (elt now 6) ;wday 0 ;yday (if (elt now 7) ;isdst 1 0) ))) (defun lyskom-current-server-time () "Return time representing current server time." (blocking-do 'get-time)) (defun lyskom-format-time (format &optional time) "Return TIME as a string formatted as FORMAT. FORMAT may be a string or a symbol. If it is a symbol, it is interpreted as follows: 'date-and-time Include date and time. [1][2] 'date Include just date. [1] 'time Include just time. [2] [1] If kom-print-seconds-in-time-strings is nil, only hours and minutes will be included in the time; if it is non-nil, seconds will also be included. [2] If kom-print-relative-dates is non-nil and the date is today's or yesterday's, the string \"today\" or \"yesterday\" (respectively) is used instead of the standard date format. If FORMAT is a symbol but not one of the symbols listed above, the format string will be looked up with lyskom-get-string. The timeformat-* strings are tailored to be used as formats for this function. The arguments to the format string are (in order): year, month number \(starting with one for January), day-of-month number, hour, minute, second, full name of the day of the week, abbreviated name of the day of the week. TIME defaults to the current client time." (let* ((time (or time (lyskom-current-client-time))) (fmt (cond ((stringp format) format) ((memq format '(date-and-time date time)) (lyskom-format (cond ((eq format 'date-and-time) 'format-time-date-and-time) ((eq format 'date) 'format-time-just-date) ((eq format 'time) 'format-time-just-time)) (lyskom-get-string (or (and kom-print-relative-dates (lyskom-calculate-day-diff time)) 'timeformat-yyyy-mm-dd)) (lyskom-get-string (if kom-print-seconds-in-time-strings 'timeformat-hh-mm-ss 'timeformat-hh-mm)))) ((symbolp format) (lyskom-get-string format)) (t (error "Invalid argument"))))) (lyskom-format fmt (time->year time) (time->mon time) (time->mday time) (time->hour time) (time->min time) (time->sec time) (elt (lyskom-get-string 'weekdays) (time->wday time)) (elt (lyskom-get-string 'weekdays-short) (time->wday time))))) ;;; ============================================================ ;;; Keymap utilities (defun lyskom-lookup-key (keymap event &optional accept-default) (if (not (arrayp event)) (setq event (vector event))) (if (null keymap) (and accept-default (lookup-key global-map event)) (or (lookup-key keymap event) (lyskom-lookup-key (keymap-parent keymap) event accept-default)))) (defun lyskom-keymap-body (keymap) (setq keymap (cdr keymap)) (cond ((arrayp (car keymap)) (car keymap)) (t keymap))) (defun lyskom-keymap-realbinding (binding) (while (stringp (car-safe binding)) (setq binding (cdr binding))) binding) (defun lyskom-overlay-keymap (basemap overlay keymap &optional prefix) (let ((keys (make-vector (1+ (length prefix)) nil)) (index (length prefix)) (body nil) (r 0)) (while (< r (length prefix)) (aset keys r (aref prefix r)) (setq r (1+ r))) (cond ((not (keymapp keymap))) ((not (keymapp overlay))) ((not (keymapp basemap))) ((setq body (lyskom-keymap-body overlay)) (mapcar (function (lambda (element) (cond ((arrayp element) (let ((len (length element))) (setq r 0) (while (< r len) (aset keys index r) (lyskom-overlay-keys keys (aref element r) basemap overlay keymap) (setq r (1+ r))))) ((consp element) (when (not (eq t (car element))) (aset keys index (car element)) (lyskom-overlay-keys keys (lyskom-keymap-realbinding (cdr element)) basemap overlay keymap))) (t nil)))) body))))) (defun lyskom-overlay-keys (keys binding basemap overlay keymap) (let ((base-binding (lyskom-lookup-key basemap keys nil))) ;; If the binding is a keymap or prefix and ;; the binding in the base is a keymap or prefix ;; then recurse (cond ((and (keymapp binding) (keymapp base-binding)) (lyskom-overlay-keymap basemap binding keymap keys)) ;; If the binding is a keymap or prefix and ;; we are bound in the base ;; then don't recurse ((and (keymapp binding) base-binding) nil) ;; If we are not bound in the base ;; copy the binding ((and binding (null base-binding)) (define-key keymap keys binding))))) (defun lyskom-traverse-keymap (fn keymap) "Like lyskom-map-keymap, but traverses parent links too." (let ((parent (keymap-parent keymap))) (lyskom-map-keymap fn keymap) (when (keymapp parent) (lyskom-traverse-keymap fn parent)))) ;;; ;;; Stuff ;;; (defun lyskom-return-membership-type (mt) "Return a text description of membership type mt" (let ((tmp (mapconcat 'identity (delete nil (list (if (membership-type->invitation mt) (lyskom-get-string 'invitation-mt-type) nil) (if (membership-type->passive mt) (lyskom-get-string 'passive-mt-type) nil) (if (membership-type->secret mt) (lyskom-get-string 'secret-mt-type) nil) (if (eq (membership-type->message-flag mt) (membership-type->passive mt)) (lyskom-get-string (if (membership-type->message-flag mt) 'message-flag-on-mt-type 'message-flag-off-mt-type))))) ", "))) (if (string= tmp "") tmp (concat "[" tmp "]")))) (defun lyskom-find-unread (conf-no) "Return the number of unread texts in CONF-NO. If this function is unable to calculate the number of unread texts it will return nil." (save-excursion (set-buffer lyskom-buffer) (let ((rlist (read-list->all-entries lyskom-to-do-list)) (found nil)) (while (and (not found) rlist) (when (eq conf-no (conf-stat->conf-no (read-info->conf-stat (car rlist)))) (setq found (text-list->length (read-info->text-list (car rlist))))) (setq rlist (cdr rlist))) found))) (defun lyskom-prev-area (num prop &optional goto-point-min) (while (> num 0) (let ((where (previous-single-property-change (point) prop))) (cond (where (if (not (get-text-property where prop)) (setq where (previous-single-property-change where prop))) (if where (goto-char where) (goto-char (point-min)) (setq num 1))) (goto-point-min (goto-char (point-min)) (setq num 1)))) (setq num (1- num)))) (defun lyskom-next-area (num prop &optional goto-point-max) "Move the cursor to the next prompt in the LysKOM buffer" (interactive "p") (while (> num 0) (let ((where (next-single-property-change (point) prop))) (cond (where (if (not (get-text-property where prop)) (setq where (next-single-property-change where prop))) (if where (goto-char where) (goto-char (point-max)) (setq num 1))) (goto-point-max (goto-char (point-max)) (setq num 1)))) (setq num (1- num)))) ;;; ============================================================ ;;; Database stuff (defun lyskom-get-send-comments-to (conf-no &optional want-type) "Get the send-comments-to value for conference CONF-NO. Returns nil if there is no send-comments-to set. Ïf WANT-TYPE is set, return as a conf (RECPT . TYPE), wher RECPT is the conference to use and TYPE is the type of recipient (numeric)." (let* ((conf-stat (if (numberp conf-no) (blocking-do 'get-conf-stat conf-no) conf-no)) (send-comments-to (and conf-stat (car (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 33)))) (result (when send-comments-to (cond ((string-match "^\\([0-9]+\\)\\s-+\\([0-9]+\\)" (aux-item->data send-comments-to)) (cons (string-to-number (match-string 1 (aux-item->data send-comments-to))) (string-to-number (match-string 2 (aux-item->data send-comments-to))))) ((string-match "^\\([0-9]+\\)" (aux-item->data send-comments-to)) (cons (string-to-number (match-string 1 (aux-item->data send-comments-to))) 0)) (t nil))))) (if want-type result (car result)))) (defun lyskom-get-all-conferences (&optional feep) "Return a list of all conferences. If FEEP is non-nil, show progress messages" (and feep (lyskom-message (lyskom-get-string 'getting-all-confs))) (prog1 (mapcar 'conf-z-info->conf-no (conf-z-info-list->conf-z-infos (blocking-do 'lookup-z-name "" nil t))) (and feep (lyskom-message (lyskom-get-string 'getting-all-confs-done))))) (defun lyskom-is-supervisor (conf-no viewer-no) "Return non-nil if the supervisor of CONF-NO is VIEWER-NO." (or (eq viewer-no conf-no) (lyskom-is-strictly-supervisor conf-no viewer-no))) (defun lyskom-is-strictly-supervisor (conf-no viewer-no) "Return non-nil if VIEWER-NO is strictly a supervisor of CONF-NO Cannot be called from a callback." (let ((collector (make-collector)) (conf-stat nil)) (initiate-get-conf-stat 'background 'collector-push conf-no collector) (lyskom-wait-queue 'background) (setq conf-stat (car (collector->value collector))) (cond ((null viewer-no) nil) ((eq viewer-no 0) nil) ((null conf-stat) nil) ((eq viewer-no (conf-stat->supervisor conf-stat)) t) ((lyskom-is-member (conf-stat->supervisor conf-stat) viewer-no) t) (t nil)))) (defun lyskom-i-am-supervisor (conf-stat &optional may-block) "Returns non-nil if lyskom-pers-no is the supervisor of CONF-STAT. If MAY-BLOCK is non-nil, this function never makes server calls, so if the information required to answer accurately is not cached, this function will return an incorrect result (nil instead of t)." (let ((marshal nil)) (when conf-stat (let ((conf (conf-stat->supervisor conf-stat)) (result nil)) (while (and (not (memq conf marshal)) conf (not result)) (setq marshal (cons conf marshal)) (if (lyskom-try-get-membership conf t) (setq result t) (if may-block (setq conf (conf-stat->supervisor (blocking-do 'get-conf-stat conf))) (setq conf (conf-stat->supervisor (cache-get-conf-stat conf)))))) result)))) (defun lyskom-is-member (conf-no pers-no &optional queue) "Return the membership in CONF-NO of PERS-NO Optional argument QUEUE is the queue to send the queries on. Cannot be called from a callback." (or (and (eq pers-no lyskom-pers-no) (lyskom-try-get-membership conf-no t)) (let ((collector (make-collector))) (initiate-query-read-texts (or queue 'background) 'collector-push pers-no conf-no nil 0 collector) (lyskom-wait-queue (or queue 'background)) (car (collector->value collector))))) (defun lyskom-text-recipients (text-stat &optional want-types) "Return the list of recipients for TEXT-STAT. If WANT-TYPES is non-nil then the result is an assoc list where the car of each element is the recipient number and the cdr is the type." (let ((result nil)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (when (memq (misc-info->type misc) lyskom-recpt-types-list) (if want-types (setq result (cons (cons (misc-info->recipient-no misc) (misc-info->type misc)) result)) (setq result (cons (misc-info->recipient-no misc) result))))) (nreverse result))) (defun lyskom-text-comments (text-stat) "Return the list of comments to TEXT-STAT" (let ((result nil)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (cond ((eq (misc-info->type misc) 'FOOTN-IN) (setq result (cons (misc-info->footn-in misc) result))) ((eq (misc-info->type misc) 'COMM-IN) (setq result (cons (misc-info->comm-in misc) result))))) (nreverse result))) (defun lyskom-find-conf-by-date (target-date) "Search all conferences for a conference created on or about TARGET-DATE. Returns the conf-stat of the conference." (blocking-do-multiple ((lowest (find-next-conf-no 0)) (highest (first-unused-conf-no))) (let* ((index (+ lowest (/ (- highest lowest) 2))) (last-index (1- index)) (result nil)) (while (/= last-index index) ;; Get the first conf-stat after index (let ((conf-stat nil) (conf-no index)) (while (and (null conf-stat) (<= conf-no highest)) (setq conf-stat (blocking-do 'get-conf-stat conf-no)) (unless conf-stat (setq conf-no (blocking-do 'find-next-conf-no conf-no)))) ;; If we were unable to find a conf-stat, then set highest ;; equal to index -- there are no conf-stats in that area, ;; so we might as well start looking below index (cond ((null conf-stat) (setq highest index)) ((lyskom-time-greater (conf-stat->creation-time conf-stat) target-date) (setq highest (1+ conf-no))) (t (setq lowest conf-no))) (setq last-index index result conf-stat) (setq index (+ lowest (/ (- highest lowest) 2))))) result))) (defun lyskom-find-text-by-date (conf-stat target-date) "Search texts in CONF-STAT for a text added on or about TARGET-DATE. Returns a cons of (LOCAL . GLOBAL)" (let* ((lowest (conf-stat->first-local-no conf-stat)) (highest (+ lowest (conf-stat->no-of-texts conf-stat))) (conf-no (conf-stat->conf-no conf-stat)) (result nil) (index (+ lowest (/ (- highest lowest) 2))) (last-index (1- index))) (while (/= last-index index) (let* ((map (blocking-do 'local-to-global conf-no index 1))) (cond ((null map) (setq lowest highest)) ((null (text-mapping->global-numbers map)) (setq highest index)) (t (let* ((text-no (car (text-mapping->global-numbers map))) (text-stat (blocking-do 'get-text-stat text-no)) (local-no (text-mapping->global-to-local map text-no)) (date (and text-stat (lyskom-traverse misc (text-stat->misc-info-list text-stat) (when (and (memq (misc-info->type misc) lyskom-recpt-types-list) (eq (misc-info->recipient-no misc) conf-no)) (lyskom-traverse-break (if (misc-info->sent-at misc) (misc-info->sent-at misc) (text-stat->creation-time text-stat)))))))) (when text-stat (setq index local-no) (if (lyskom-time-greater date target-date) (setq highest index) (setq lowest index)) (setq result text-stat)))))) (setq last-index index) (setq index (+ lowest (/ (- highest lowest) 2)))) (cons last-index (text-stat->text-no result)))) (put 'lyskom-parse-date-invalid 'error-conditions '(error lyskom-error)) (put 'lyskom-parse-date-invalid 'error-message "Error parsing date") (defvar lyskom-year-window-start 80 "Windowing threshold for YY year specifications. Years below this are considered in the 21st century. Years above this in the 20th century") (defun lyskom-all-prefixes (s) "Return part of a regular expression matching all prefixes of S. The value returned does not include the parens before at either ends of the expression." (let ((result nil) (i 1)) (while (<= i (length s)) (setq result (cons (substring s 0 i) result) i (1+ i))) (mapconcat 'regexp-quote result "\\|"))) (defun lyskom-read-date (prompt &optional empty) "Read a date from the minibuffer. Returns a list (YEAR MONTH DATE) corresponding to the user's input." (let ((result nil) (date nil)) (while (null result) (setq date (lyskom-verified-read-from-minibuffer prompt date (lambda (data) (condition-case nil (cond ((and empty (string-equal data "")) nil) (t (lyskom-parse-date data) nil)) (lyskom-error (lyskom-get-string 'invalid-date-entry)))))) (condition-case nil (cond ((and empty (string-equal date "")) (setq result t)) (t (setq result (lyskom-parse-date date)))) (lyskom-error nil))) (and (listp result) result))) (defun lyskom-parse-date (arg) "Parse ARG (a string) as a date. Returns a list (YEAR MONTH DAY) corresponding to the date in ARG." (let* ((month-regexp (concat "\\(" (mapconcat (lambda (el) (regexp-quote (car el))) lyskom-month-names "\\|") "\\)")) (y-regexp (concat "\\(" (mapconcat (lambda (el) (lyskom-all-prefixes (lyskom-get-string el))) '(years year) "\\|") "\\)")) (m-regexp (concat "\\(" (mapconcat (lambda (el) (lyskom-all-prefixes (lyskom-get-string el))) '(months month) "\\|") "\\)")) (d-regexp (concat "\\(" (mapconcat (lambda (el) (lyskom-all-prefixes (lyskom-get-string el))) '(days day) "\\|") "\\)")) (test-date (format-time-string "%x" '(20 0))) (now (decode-time)) (current-day (elt now 3)) (current-month (elt now 4)) (current-year (elt now 5)) (case-fold-search t) year month day di mi yi) ;; Look at test-date to see where dates in ambiguous cases should go (cond ((string-match "01.*16.*70" test-date) (setq di 2 mi 1 yi 3)) ((string-match "01.*70.*16" test-date) (setq di 3 mi 1 yi 2)) ((string-match "16.*01.*70" test-date) (setq di 1 mi 2 yi 3)) ((string-match "16.*70.*01" test-date) (setq di 1 mi 3 yi 2)) ((string-match "70.*01.*16" test-date) (setq di 3 mi 2 yi 1)) ((string-match "70.*16.*01" test-date) (setq di 2 mi 3 yi 1))) ;; Match various variants (cond ((string-match "^\\s-*\\([0-9][0-9][0-9][0-9]?\\)\\s-*[ -./]\\s-*\\([0-9][0-9]?\\)\\s-*[ -./]\\s-*\\([0-9][0-9]?\\)\\s-*$" arg) ;; YYYY-MM-DD (setq year (string-to-int (match-string 1 arg)) month (string-to-int (match-string (if (> mi di) 3 2) arg)) day (string-to-int (match-string (if (> mi di) 2 3) arg))) (when (> month 12) (setq month day day month)) ) ((string-match "^\\s-*\\([0-9][0-9]?\\)\\s-*[ -./]\\s-*\\([0-9][0-9]?\\)\\s-*[ -./]\\s-*\\([0-9][0-9][0-9][0-9]?\\)\\s-*$" arg) ;; MM-DD-YYYY (setq year (string-to-int (match-string 3 arg)) month (string-to-int (match-string (if (> mi di) 2 1) arg)) day (string-to-int (match-string (if (> mi di) 1 2) arg))) (when (> month 12) (setq month day day month)) ) ((string-match "^\\s-*\\([0-9][0-9]\\)\\s-*[ -./]\\s-*\\([0-9][0-9]?\\)\\s-*[ -./]\\s-*\\([0-9][0-9]?\\)\\s-*$" arg) ;; Ambiguous: ;; YY/MM/DD, YY/DD/MM, MM/DD/YY, DD/MM/YY (setq year (string-to-int (match-string yi arg)) month (string-to-int (match-string mi arg)) day (string-to-int (match-string di arg))) (when (> month 12) (setq month day day month)) ) ((string-match "^\\s-*\\([0-9][0-9]\\)\\s-*/\\s-*\\([0-9][0-9]\\)\\s-*$" arg) ;; Ambiguous: ;; MM/DD Euro ;; DD/MM US (let ((a (string-to-int (match-string 1 arg))) (b (string-to-int (match-string 2 arg)))) (cond ((> a 12) (setq month b day a)) ((> b 12) (setq month a day b)) ((> di mi) (setq month b day a)) (t (setq month a day b)))) ) ((string-match (format "^\\s-*\\([0-9][0-9]?\\)\\s-*%s\\s-*\\([0-9][0-9][0-9][0-9]\\)\\s-*$" month-regexp) arg) ;; DD Month YYYY (setq day (string-to-int (match-string 1 arg)) month (cdr (lyskom-string-assoc (match-string 2 arg) lyskom-month-names)) year (string-to-int (match-string 3 arg))) ) ((string-match (format "^\\s-*%s \\([0-9][0-9]?\\),\\s-*\\([0-9][0-9][0-9]?[0-9]?\\)\\s-*$" month-regexp) arg) ;; Month DD, YYYY (setq day (string-to-int (match-string 2 arg)) month (cdr (lyskom-string-assoc (match-string 1 arg) lyskom-month-names)) year (string-to-int (match-string 3 arg))) ) ((string-match (format "^\\s-*\\([0-9][0-9]?\\) %s,\\s-*\\([0-9][0-9][0-9]?[0-9]?\\)\\s-*$" month-regexp) arg) ;; DD Month, YYYY (setq day (string-to-int (match-string 1 arg)) month (cdr (lyskom-string-assoc (match-string 2 arg) lyskom-month-names)) year (string-to-int (match-string 3 arg))) ) ((string-match (format "^\\s-*%s,?\\s-*\\([0-9][0-9][0-9][0-9]\\)\\s-*$" month-regexp) arg) ;; Ambiguous: ;; Month YYYY (setq day 1 month (cdr (lyskom-string-assoc (match-string 1 arg) lyskom-month-names)) year (string-to-int (match-string 2 arg))) ) ((string-match (format "^\\s-*%s \\([0-9][0-9]?\\)\\s-*$" month-regexp) arg) ;; Ambiguous: ;; Month DD, Month YY (setq month (cdr (lyskom-string-assoc (match-string 1 arg) lyskom-month-names)) day (string-to-int (match-string 2 arg)) year current-year) (when (> day 31) (setq day 1 year day)) ) ((string-match (format "^\\s-*\\([0-9][0-9]?\\) %s\\s-*$" month-regexp) arg) ;; DD Month (setq day (string-to-int (match-string 1 arg)) month (cdr (lyskom-string-assoc (match-string 2 arg) lyskom-month-names)) year current-year) ) ((string-match (format "^\\s-*-?\\([0-9]+\\)\\s-*%s\\s-*$" y-regexp) arg) ;; -NN years (setq year (- current-year (string-to-int (match-string 1 arg))) day current-day month current-month) ) ((string-match (format "^\\s-*-?\\([0-9]+\\)\\s-*%s\\s-*$" m-regexp) arg) ;; -NN months (setq year current-year month current-month day current-day) (let ((count (string-to-int (match-string 1 arg)))) (while (> count 0) (if (>= count month) (setq count (- count month) year (1- year) month 12) (setq month (- month count) count 0)))) (setq day (lyskom-adjust-day-for-date year month day)) ) ((string-match (format "^\\s-*-?\\([0-9]+\\)\\s-*%s\\s-*$" d-regexp) arg) ;; -NN days ;; Theres probably an off-by-one error in this code on year transitions ;; but I really don't care. (setq year current-year month current-month day current-day) (let ((count (string-to-int (match-string 1 arg)))) (while (> count 0) (if (>= count day) (progn (setq count (- count day) month (1- month)) (when (< month 1) (setq month 12 year (1- year))) (setq day (lyskom-adjust-day-for-date year month 31))) (setq day (- day count) count 0)))) (setq day (lyskom-adjust-day-for-date year month day)) ) ((string-match "^\\s-*\\([0-9][0-9][0-9][0-9]?\\)\\s-*$" arg) ;; YYYY goes last because the pattern is the most general (setq year (string-to-int (match-string 0 arg)) month 1 day 1) ) (t (signal 'lyskom-parse-date-invalid (list (format "Unrecognized date: %s" arg)))) ) ;; Do the window thing for two-digit dates (cond ((< year lyskom-year-window-start) (setq year (+ 2000 year))) ((< year 100) (setq year (+ 1900 year)))) ;; Check date validity. Check month before checking days-in-month or stuff breaks (when (or (< month 1) (< day 1) (> month 12) (> day (lyskom-days-in-month year month))) (signal 'lyskom-parse-date-invalid (list (format "Invalid date: %s" arg)))) (list year month day) )) (defvar lyskom-month-limits '[31 ; Jan 28 ; Feb (non-leap) 31 ; Mar 30 ; Apr 31 ; May 30 ; Jun 31 ; Jul 31 ; Aug 30 ; Sep 31 ; Oct 30 ; Nov 31 ; Dec ] "Number of days in various months. The value for february is not used.") (defun lyskom-is-leap-year (year) "Return non-nil if YEAR is a leap year." (or (and (zerop (% year 4)) (not (zerop (% year 100)))) (zerop (% year 400)))) (defun lyskom-days-in-year (year) "Return number of days in YEAR." (if (lyskom-is-leap-year year) 366 365)) (defun lyskom-days-in-month (year month) "Return the number of days mONTH of YEAR. Args: YEAR MONTH" (cond ((eq month 2) (if (lyskom-is-leap-year year) 29 28)) (t (elt lyskom-month-limits (1- month))))) (defun lyskom-adjust-day-for-date (year month day) "Return an appropriate day of month for a combination of YEAR, MONTH and DAY. If DAY is too high for YEAR and MONTH, return the maximum permissible DAY for that combination. Otherwise return DAY." (let ((mdays (lyskom-days-in-month year month))) (if (> day mdays) mdays day))) ;;; ================================================================ ;;; Check noconversion (defun lyskom-viewing-noconversion () "Return non-nil if we are reviewing in noconversion mode." (eq 'kom-review-noconversion lyskom-current-command)) ;;; ================================================================ ;;; Read membership types (defun lyskom-read-membership-type () "Interactively read a membership type" (let ((invitation (lyskom-j-or-n-p 'mship-type-invitation-q)) (passive (lyskom-j-or-n-p 'mship-type-passive-q)) (secret (lyskom-j-or-n-p 'mship-type-secret-q))) (lyskom-create-membership-type invitation passive secret nil nil nil nil nil))) ;;; ================================================================ ;;; String truncation ;;; (defun lyskom-truncate-to-lines (string threshold show-lines &optional width) "If STRING is more than THRESHOLD lines on screen, truncate it to SHOW-LINES. Optional argument WIDTH is thw window width to use instead of window-width. This function takes the setting of truncate-lines into account, so the resulting string may not have SHOW-LINES newline characters. Result is eq to STRING when no truncation is required. The result is approximate when truncate-lines is non-nil since different Emacsen use a different number of characters for the continuation marks at the end of broken lines. We assume one character continuation marks." (let ((line-length (if truncate-lines lyskom-max-int (- (or width (window-width)) 1))) (count 0) (end nil) (pos 0)) (while (and (< pos (length string)) (< count threshold)) (setq count (1+ count)) (let ((next (string-match "\\(\n\\|\\'\\)" string pos))) (if (> (- next pos) line-length) (setq pos (+ pos line-length)) (setq pos (match-end 0)))) (when (= count show-lines) (setq end pos))) (if (>= count threshold) (substring string 0 end) string))) ;;; ================================================================ ;;; Color model manipulations ;;; ;;; (Of COURSE you need this in a KOM client!) ;;; (defun lyskom-get-color-highlight (color distance) "Create a highlight color for COLOR that is DISTANCE away. COLOR is a list of R G and B components from 0 to 65535. DISTANCE is a non-negative integer no larger than 1.0, that in some way specifies how far away from the original color the new color should be." (when color (let* ((hls (lyskom-rgb-to-hls (mapcar (lambda (x) (/ x 65535.0)) color))) (l (elt hls 1))) (if (> l 0.6) (setq l (- l distance)) (setq l (+ l distance))) (cond ((> l 1.0) (setq l 1.0)) ((< l 0.0) (setq l 0.0))) (aset hls 1 l) (apply 'format "#%02x%02x%02x" (mapcar (lambda (c) (round (* 255 c))) (lyskom-hls-to-rgb hls)))))) (defun lyskom-rgb-to-hls (rgb) "Convert a point in RGB color space to a point in HLS color space. Input value is a vector [R G B], where R, G and B represent red, green and blue components, respectively. Each value is a non-negative floating-point value no larger than 1.0. Output is a vector [H L S], where H, L and S represend hue, lightness and saturation, respectively. H is in the range 0..360, L and S are non-negative floating-point numbers no higher than 1.0. If the input color is a shade of gray (all components are equal), then H in the output is nil. Algorithm adapted from Foley, \"Computer Graphics\"." (let* ((r (elt rgb 0)) (g (elt rgb 1)) (b (elt rgb 2)) (rgbmin (min r g b)) (rgbmax (max r g b)) (h nil) (l (/ (+ rgbmax rgbmin) 2.0)) (s nil) (delta (- rgbmax rgbmin))) (if (zerop delta) (setq s 0.0) (if (<= l 0.5) (setq s (/ delta (+ rgbmax rgbmin))) (setq s (/ delta (- 2.0 rgbmax rgbmin)))) (cond ((= r rgbmax) (setq h (/ (- g b) delta))) ((= g rgbmax) (setq h (+ 2.0 (/ (- b r) delta)))) ((= b rgbmax) (setq h (+ 4.0 (/ (- r g) delta))))) (setq h (* h 60.0)) (if (< h 0) (setq h (+ 360.0 h)))) (vector h l s))) (defun lyskom-hls-to-rgb-value (n1 n2 h) "Helper function for lyskom-hls-to-rgb" (cond ((> h 360) (setq h (- h 360.0))) ((< h 0) (setq h (+ h 360.0)))) (cond ((< h 60) (+ n1 (* (- n2 n1) (/ h 60.0)))) ((< h 180) n2) ((< h 240) (+ n1 (* (- n2 n1) (/ (- 240.0 h) 60.0)))) (t n1))) (defun lyskom-hls-to-rgb (hls) "Convert a point in HLS color space to a point in RGB color space. Input HLS is a vector [H L S], where H, L and S represend hue, lightness and saturation, respectively. H is in the range 0..360, L and S are non-negative floating-point numbers no higher than 1.0. If the input color is a shade of gray (all components are equal), then S in the input is ignored and may be anything. Output value is a vector [R G B], where R, G and B represent red, green and blue components, respectively. Each value is in the range 1..1.0. This algorithm is adapted from Foley, \"Computer Graphics\" (and has the bug in that algorithm fixed)." (let* ((h (elt hls 0)) (l (elt hls 1)) (s (elt hls 2)) (m2 (if (<= l 0.5) (* l (+ 1.0 s)) (+ l (* s (- 1 l))))) (m1 (- (* 2 l) m2))) (if (zerop s) (vector l l l) (vector (lyskom-hls-to-rgb-value m1 m2 (+ h 120)) (lyskom-hls-to-rgb-value m1 m2 h) (lyskom-hls-to-rgb-value m1 m2 (- h 120)))))) ;;; ================================================================ ;;; Automatically test that RGB->X and X->RGB color model conversions ;;; really are the inverse of each other. ;;; ;;; (defun lyskom-test-color-model () ;;; (let ((r 0.0) ;;; (g 0.0) ;;; (b 0.0) ;;; (step 0.05)) ;;; (while (<= r 1.0) ;;; (setq g 0.0) ;;; (while (<= g 1.0) ;;; (setq b 0.0) ;;; (while (<= b 1.0) ;;; (let ((tmp (lyskom-hls-to-rgb ;;; (lyskom-rgb-to-hls (vector r g b))))) ;;; (unless (and (< (- r (elt tmp 0)) 0.000000001) ;;; (< (- g (elt tmp 1)) 0.000000001) ;;; (< (- b (elt tmp 2)) 0.000000001)) ;;; (message "Mismatch %1.2f,%1.2f,%1.2f gave %S/%S" r g b (lyskom-rgb-to-hls (vector r g b)) tmp))) ;;; (setq b (+ b step))) ;;; (setq g (+ g step))) ;;; (setq r (+ r step))))) ;;;(defun lyskom-test-auto-colors () ;;; (make-face 'test-1) ;;; (make-face 'test-2) ;;; (make-face 'test-default) ;;; (while t ;;; (let ((foreground (read-from-minibuffer "Foreground: ")) ;;; (background (read-from-minibuffer "Background: "))) ;;; (pop-to-buffer (get-buffer-create "*kom*-test")) ;;; (erase-buffer) ;;; (set-face-foreground 'test-default foreground) ;;; (set-face-background 'test-default background) ;;; (set-face-background 'test-1 (lyskom-get-color-highlight (x-color-values background) 0.05)) ;;; (set-face-background 'test-2 (lyskom-get-color-highlight (x-color-values background) 0.025)) ;;; (let ((lyskom-buffer (current-buffer))) ;;; (lyskom-format-insert "\ ;;;%#3@Läsa nästa fotnot... ;;;8408827 idag 00:40 /1 rad/ Lunkwill/CH ( Auf das Universum! ) ;;;Fotnot till text 8408825 av Lunkwill/CH ( Auf das Universum! ) ;;;Mottagare: Nätverk, Internet, LysNET, Sunet... <30873> ;;;Mottagare: SUBnet (Stångåstadens och LiU:s) studentbostadsnät <12152> ;;;Mottagare: Lunkwill/CH ( Auf das Universum! ) <2092> ;;;Ärende: Vårmötet ;;;%[%#1$------------------------------------------------------------ ;;;%]%[%#2$Och tack så mycket för förklaringarna! =) ;;;%]%[%#1$(8408827) /Lunkwill/CH ( Auf das Universum! )/------ ;;;%]Gå till nästa möte... ;;;SUN erfarenhetsutbyte - 1 oläst ;;;Läsa nästa text... ;;;8408823 idag 00:39 /4 rader/ Erik Persson, Lysato(r) ;;;Kommentar till text 8407161 av Dejan (något desperat) ;;;Mottagare: SUN erfarenhetsutbyte <23622> ;;;Ärende: Skapa partitionstabell ;;;%[%#1$------------------------------------------------------------ ;;;%]%[%#2$Om du nu vill spela Fibre Channel med IDE-RAID så går du över ån efter ;;;vatten. Det finns redan IDE-RAID med FC-interface. Dock har jag inte ;;;sett någon som stödjer något annat än FC-AL vilket är lite ;;;begränsande. ;;;%]%[%#1$(8408823) ------------------------------------------ ;;;%]Gå till nästa möte... ;;; ;;; ;;; ;;;" ;;; '(face test-1) ;;; '(face test-2) ;;; '(face test-default)))))) ;;; (defun lyskom-safe-color-name (c) "Return a color name as a string or nil." (cond ((stringp c) c) ((lyskom-color-specifier-p c) (lyskom-color-name c)))) (defun lyskom-is-url (text) "Return non-nil if TEXT can be interpreted as an URL. Any whitespace and newlines in TEXT will be ignored." (save-match-data (let ((text (replace-in-string text "\\s-+" ""))) (or (string-match "^\\(file://\\|ftp://\\|gopher://\\|http://\\|https://\\|news:\\|wais://\\|mailto:\\|telnet:\\|rtsp:\\)[^\t \012\014\"<>|\\]*[^][\t \012\014\"<>|.,!(){}?'`:;]$" text) (string-match "^\\(www\\|ftp\\|home\\)\\.[^\t \012\014\"<>|\\]*[^][\t \012\014\"<>|.,!(){}?'`:;]$" text))))) (defun lyskom-nag-about-presentation (&optional harder) (unless kom-dont-complain-about-missing-presentation (blocking-do-multiple ((pers-stat (get-pers-stat (or lyskom-pers-no 0))) (conf-stat (get-conf-stat (or lyskom-pers-no 0)))) (when (and pers-stat conf-stat (or harder (eq (random (max 3 (- 20 (pers-stat->no-of-created-texts pers-stat) (* 5 (pers-stat->created-confs pers-stat)) (* 2 (pers-stat->created-persons pers-stat))))) 1)) (null (blocking-do 'get-text-stat (conf-stat->presentation conf-stat)))) (lyskom-beep 2) (lyskom-format-insert 'why-you-got-no-presentation `(face ,kom-warning-face) (pers-stat->no-of-created-texts pers-stat) (lyskom-session-nickname) 72) (sit-for (if harder 0 1)))))) (defun lyskom-get-server-stats () (let ((descr (blocking-do 'get-stats-description))) (when descr (let ((result (lyskom-create-server-stats)) (collector (make-collector))) (set-server-stats->when result (listify-vector (stats-description->when descr))) (set-server-stats->what result (listify-vector (stats-description->what descr))) (lyskom-traverse name (stats-description->what descr) (initiate-get-stats 'main (lambda (res name c) (when res (collector-push (cons name (listify-vector res)) c))) name name collector)) (lyskom-wait-queue 'main) (set-server-stats->values result (nreverse (collector->value collector))) result)))) (defun lyskom-format-units (val units base-unit) "Format VAL using units. UNITS is an alist (COUNT . NAME), where NAME is the name of a unit and COUNT is the number of base units for that name. For example, if the base unit is seconds, then minutes could be defined with \(60 . \"min\"). BASE-UNIT is the name of the base unit \(which implicitly has a count of 1)." (mapconcat (lambda (el) (format "%d%s" (car el) (cond ((stringp (cdr el)) (cdr el)) ((symbolp (cdr el)) (lyskom-get-string (cdr el)))))) (nreverse (let ((result nil)) (lyskom-traverse unit units (when (>= val (car unit)) (let ((a (/ val (car unit)))) (when (> a 0) (setq result (cons (cons a (cdr unit)) result))) (setq val (% val (car unit)))))) (if (> val 0) (cons (cons val base-unit) result) result))) "")) (defun lyskom-format-time-units (val &optional what) "Format VAL as values per time unit in such a way that the result is readable (i.e. whole numbers, if possible). WHAT is the unit measured." (let ((last-unit nil)) (if (eq val 0) (lyskom-format "0%#1?b%[ %#1s%]%[%]/%#2s" what (lyskom-get-string 'unit-hour)) (lyskom-traverse unit '((unit-second . 1) (unit-minute . 60) (unit-hour . 60) (unit-day . 24) (unit-month . 30) (unit-year . 12)) (setq val (* val (cdr unit))) (setq last-unit unit) (when (> val 1) (lyskom-traverse-break))) (lyskom-format "%0.0.4#1f%#2?b%[ %#2s%]%[%]/%#3s" val what (lyskom-get-string (car last-unit)))))) (defun lyskom-extended-status-information (tag) "Return non-nil is extended status information indicated by TAG should be shown." (cond ((eq kom-extended-status-information t) t) ((assq tag kom-extended-status-information) (cdr (assq tag kom-extended-status-information))) ((cdr (assq t kom-extended-status-information))))) (defun lyskom-extended-status-override (tag) "Return a new value for kom-extended-status-information that reflects an override of the value by the value of TAG." (cond ((eq kom-extended-status-information t) t) ((assq tag kom-extended-status-information) (cdr (assq tag kom-extended-status-information))) (t kom-extended-status-information))) ;;; ============================================================ ;;; Magic that allows us to clear the initial value in the ;;; minibuffer when the user types a character. ;;; ;;; We can't alter the buffer contents in before-change-functions ;;; since this can crash Gnu Emacs 20.7 (it computes positions ;;; internally before calling before-change-functions, and if ;;; those positions are invalid afterwards all sorts of things ;;; can happen). ;;; ;;; Theory of operation: ;;; ;;; In the pre-command-hook, record the position of point and ;;; the contents of the minibuffer. ;;; ;;; In before-change-functions, check if there is initial ;;; input in the buffer yet -- if not we're not yet ready ;;; to erase anything. ;;; ;;; In the post-command-hook, if the buffer contents have changed ;;; since there was inital input in the buffer, erase the initial ;;; input. If the position of point has moved, disable all the ;;; magic (both can happen at the same time). ;;; ;;; We set up advice on read-from-minibuffer and completing-read ;;; that mangles the initial input appropriately. ;;; (defvar lyskom-minibuffer-point) (defvar lyskom-minibuffer-string) (defvar lyskom-minibuffer-do-change) (defun lyskom-magic-minibuffer-pre-command (&rest args) "Save current status of the minibuffer for later magic." (setq lyskom-minibuffer-point (point) lyskom-minibuffer-string (buffer-string))) (defun lyskom-magic-minibuffer-before-change (&rest args) "Check if the initial input has been placed in the minibuffer. This function is called at least once before the initial input has been placed in the minibuffer by Emacs. Most magic needs to be disabled until the input has been deposited." (setq lyskom-minibuffer-do-change (lyskom-next-property-bounds (point-min) (point-max) 'lyskom-initial-mbc))) (defun lyskom-magic-minibuffer-post-command (&rest args) "Function for use as post-command-hook in magic minibuffer. If the contents of the minibuffer have changed since initial input has been placed in the minibuffer, erase the initial input. This happens when the user enters something in the minibuffer. If point has moved, disable magic. This happens either after we delete the initial contents (which is OK) or after the user moves point without altering the buffer contents." (when (and lyskom-minibuffer-do-change (not (equal (buffer-string) lyskom-minibuffer-string))) (let ((ranges nil) (tmp nil) (start (point-min))) (while (setq tmp (lyskom-next-property-bounds start (point-max) 'lyskom-initial-mbc)) (setq ranges (cons tmp ranges) start (cdr tmp))) (lyskom-traverse range ranges (delete-region (car range) (cdr range))) (when ranges (lyskom-magic-minibuffer-cancel)))) (unless (or (null lyskom-minibuffer-point) (eq lyskom-minibuffer-point (point))) (lyskom-magic-minibuffer-cancel))) (defun lyskom-magic-minibuffer-cancel () "Remove hooks used to make the minibuffer magic." (remove-hook 'pre-command-hook 'lyskom-magic-minibuffer-pre-command) (remove-hook 'post-command-hook 'lyskom-magic-minibuffer-post-command) (remove-hook 'before-change-functions 'lyskom-magic-minibuffer-before-change)) (defun lyskom-magic-minibuffer-mangle-initial (initial) "Add text properties to INITIAL (a string or cons) so it is suitable for use as initial input in a magic minibuffer." (cond ((null initial) nil) ((stringp initial) (let ((tmp (copy-sequence initial))) (add-text-properties 0 (length tmp) '(lyskom-initial-mbc t rear-nonsticky t end-open t start-open t front-sticky nil) tmp) tmp)) ((consp initial) (let ((tmp (copy-sequence (car initial)))) (add-text-properties 0 (length tmp) '(lyskom-initial-mbc t rear-nonsticky t end-open t start-open t front-sticky nil) tmp) (cons tmp (cdr initial)))) (t initial))) ;;; ------------------------------------------------------------ ;;; Gnu Emacs and XEmacs have different names for parameters. ;;; This is stupid and makes the code below a lot uglier. (defadvice read-from-minibuffer (around lyskom-magic-minibuffer-read-from-minibuffer nil disable) (let* ((initial-input (and (boundp 'initial-input) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial-input)))) (initial-contents (and (boundp 'initial-contents) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial-contents)))) (initial (and (boundp 'initial) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial)))) (init (and (boundp 'init) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'init)))) (result ad-do-it)) (lyskom-ignore initial-input) (lyskom-ignore initial-contents) (lyskom-ignore initial) (lyskom-ignore init) (when (stringp result) (remove-text-properties 0 (length result) '(end-open nil rear-nonsticky nil lyskom-initial-mbc nil) result) (unless (or (text-properties-at 0 result) (next-property-change 0 result)) (set-text-properties 0 (length result) nil result))) result)) (defadvice completing-read (around lyskom-magic-minibuffer-completing-read nil disable) (let* ((initial-input (and (boundp 'initial-input) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial-input)))) (initial-contents (and (boundp 'initial-contents) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial-contents)))) (initial (and (boundp 'initial) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'initial)))) (init (and (boundp 'init) (lyskom-magic-minibuffer-mangle-initial (symbol-value 'init)))) (result ad-do-it)) (lyskom-ignore initial-input) (lyskom-ignore initial-contents) (lyskom-ignore initial) (lyskom-ignore init) (when (stringp result) (remove-text-properties 0 (length result) '(end-open nil rear-nonsticky nil lyskom-initial-mbc nil) result) (unless (or (text-properties-at 0 result) (next-property-change 0 result)) (set-text-properties 0 (length result) nil result))) result)) (defun lyskom-magic-minibuffer-add-advice () (ad-enable-advice 'read-from-minibuffer 'around 'lyskom-magic-minibuffer-read-from-minibuffer) (ad-enable-advice 'completing-read 'around 'lyskom-magic-minibuffer-completing-read) (ad-activate 'read-from-minibuffer) (ad-activate 'completing-read) ) (defun lyskom-magic-minibuffer-cancel-advice () (ad-disable-advice 'read-from-minibuffer 'around 'lyskom-magic-minibuffer-read-from-minibuffer) (ad-disable-advice 'completing-read 'around 'lyskom-magic-minibuffer-completing-read) ) (defmacro lyskom-with-magic-minibuffer (&rest forms) `(let ((lyskom-minibuffer-point nil) (lyskom-minibuffer-string nil) (lyskom-minibuffer-do-change nil) (pre-command-hook pre-command-hook) (post-command-hook post-command-hook) (before-change-functions before-change-functions)) (add-hook 'pre-command-hook 'lyskom-magic-minibuffer-pre-command) (add-hook 'post-command-hook 'lyskom-magic-minibuffer-post-command) (add-hook 'before-change-functions 'lyskom-magic-minibuffer-before-change) (unwind-protect (progn (lyskom-magic-minibuffer-add-advice) ,@forms) (lyskom-magic-minibuffer-cancel-advice)))) (defun lyskom-completing-read (prompt table &optional predicate require-match init hist def) (let ((this-command this-command)) (lyskom-ignore def) (lyskom-with-lyskom-minibuffer (lyskom-with-magic-minibuffer (let ((res (completing-read prompt table predicate require-match init hist))) (if (or (null res) (equal res "")) def res)))))) (defun lyskom-read-from-minibuffer (prompt &optional initial-contents keymap read hist def) (let ((this-command this-command)) (lyskom-ignore def) (lyskom-with-lyskom-minibuffer (lyskom-with-magic-minibuffer (or (read-from-minibuffer prompt initial-contents keymap read hist) def))))) (defun lyskom-set-connection-time-format (val) "Change protocol time format to UTC if VAL is non-nil." ;; Check for broken encode-time (setq val (and val (condition-case nil (not (equal (encode-time 0 0 0 1 1 1970 0) (encode-time 0 0 0 1 1 1970 -4))) (error nil)))) (when (or (blocking-do 'set-connection-time-format val) (null val)) (lyskom-traverse-buffer-hierarchy (lambda (buf) (save-excursion (set-buffer buf) (make-variable-buffer-local 'lyskom-server-uses-utc) (setq lyskom-server-uses-utc val))) lyskom-buffer))) (put 'lyskom-integer-conversion-error 'error-conditions '(lyskom-integer-conversion-error lyskom-error error)) (put 'lyskom-integer-conversion-error 'error-message "Invalid integer conversion") (defun lyskom-string-to-int (string &optional signal-error) "Convert STRING to an integer by parsing it as a decimal number. This does not parse floating point numbers. It ignores leading spaces and tabs." (or (let ((tmp (string-to-int string))) (cond ((eq tmp 0) (and (string-match "^\\s-*0+\\s-*" string) 0)) ((integerp tmp) tmp) (t nil))) (and signal-error (signal 'lyskom-integer-conversion-error string)))) (defun lyskom-privilege-string (privs &optional format sep) (setq format (or format "%#1s") sep (or sep ", ")) (mapconcat (lambda (x) (lyskom-format format (lyskom-get-string x))) (or (delq nil (list (and (privs->wheel privs) 'privs-wheel) (and (privs->admin privs) 'privs-admin) (and (privs->statistic privs) 'privs-statistic) (and (privs->create_pers privs) 'privs-create-pers) (and (privs->create_conf privs) 'privs-create-conf) (and (privs->change_name privs) 'privs-change-name) (and (privs->flg7 privs) 'privs-flg7) (and (privs->flg8 privs) 'privs-flg8) (and (privs->flg9 privs) 'privs-flg9) (and (privs->flg10 privs) 'privs-flg10) (and (privs->flg11 privs) 'privs-flg11) (and (privs->flg12 privs) 'privs-flg12) (and (privs->flg13 privs) 'privs-flg13) (and (privs->flg14 privs) 'privs-flg14) (and (privs->flg15 privs) 'privs-flg15) (and (privs->flg16 privs) 'privs-flg16) )) '(lyskom-no-privileges)) sep)) (defvar lyskom-gensym-index 0 "Index to use in lyskom-gensym") (defun lyskom-gensym () "Generate a unique symbol" (let ((name "t")) (while (intern-soft name) (setq lyskom-gensym-index (1+ lyskom-gensym-index)) (setq name (format "lyskom-gensym: %d" lyskom-gensym-index))) (intern name))) (put 'lyskom-with-magic-minibuffer 'edebug-form-spec '(body)) ;;; ================================================================ ;;; List text summaries (defvar lyskom-list-text-summary-params) (defvar lyskom-list-text-summary-params-persistent) (defvar lyskom-list-text-summary-format) (defsubst lyskom-list-text-summary-get (sym) (or (plist-get lyskom-list-text-summary-params sym) (plist-get lyskom-list-text-summary-params-persistent sym))) (defsubst lyskom-list-text-summary-put (sym val &optional persistent) (if persistent (setq lyskom-list-text-summary-params-persistent (plist-put lyskom-list-text-summary-params-persistent sym val)) (setq lyskom-list-text-summary-params (plist-put lyskom-list-text-summary-params sym val)))) (defun lyskom-max-mark-width () "Return the maximum width of the user's symbolic mark strings." (apply 'max 3 (mapcar (function (lambda (x) (length (car x)))) kom-symbolic-marks-alist))) (defun lyskom-max-text-no-width () "Ask the server about the maximum text number width." (length (int-to-string (blocking-do 'find-previous-text-no lyskom-max-int)))) (defun lyskom-symbolic-mark-type-string (mark-no &optional strict) "Return a symbolic name string for the mark-type of MARK. If optional argument STRICT is non-nil, return nil if there is no symbolic name for the mark type." (or (car-safe (rassoc mark-no kom-symbolic-marks-alist)) (and (not strict) (int-to-string mark-no)))) (defvar lyskom-text-summary-fields '((mark-type :width lyskom-max-mark-width :prompt mark-type :align left :format "s" :output (lambda (text-stat) (let ((mark (or (lyskom-list-text-summary-get :mark) (cache-text-is-marked (text-stat->text-no text-stat))))) (if mark (lyskom-symbolic-mark-type-string (mark->mark-type mark)) ""))) ) (mark-no :width 3 :prompt mark-no :align left :format "s" :output (lambda (text-stat) (let ((mark (cache-text-is-marked (text-stat->text-no text-stat)))) (if mark (int-to-string (mark->mark-type mark)) ""))) ) (comments :width 2 :prompt Comments :align right :format "s" :output (lambda (text-stat) (if (zerop (length (lyskom-text-comments text-stat))) "" (int-to-string (length (lyskom-text-comments text-stat))))) ) (mark-count :width 2 :prompt Num-marks :align right :format "s" :output (lambda (text-stat) (if (zerop (text-stat->no-of-marks text-stat)) "" (int-to-string (text-stat->no-of-marks text-stat)))) ) (text-no :width lyskom-max-text-no-width :prompt Texts :align left :format "n" :output (lambda (text-stat) (text-stat->text-no text-stat))) (written :width (lambda () (max (length (lyskom-format-time 'time)) (length (lyskom-format-time 'timeformat-yyyy-mm-dd)))) :prompt Written :align left :format "s" :output (lambda (text-stat) (let ((now (lyskom-current-server-time)) (time (or (lyskom-mx-date-to-time (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 21))) (text-stat->creation-time text-stat)))) (if (and (= (time->year now) (time->year time)) (= (time->mon now) (time->mon time)) (= (time->mday now) (time->mday time))) (lyskom-format-time 'time time) (lyskom-format-time 'timeformat-yyyy-mm-dd time)))) ) (lines :width 5 :prompt Lines :align right :align left :format "d" :output (lambda (text-stat) (text-stat->no-of-lines text-stat)) ) (author :width nil :weight 50.0 :prompt Author :align left :format "P" :output (lambda (text-stat) (let ((mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16)))) (if (or mx-from mx-author) (lyskom-format-mx-author mx-from mx-author) (text-stat->author text-stat)))) ) (subject :width nil :weight 100.0 :prompt Subject :align left :format "s" :output (lambda (text-stat) (lyskom-list-text-summary-subject text-stat)) ) ) "Specification of fields that can be included in text summary lists. Each element is a cons (KEY . PLIST), where KEY is the name of the field type (arbitrary symbol). and PLIST is a property list, which may include the following properties: :width Witdh of the field. Function, number or nil. :weight Weight for dynamically sized field. Floating point. :prompt Heading for the column. Symbol. :align Alignment of the column. Either left or right. :format Format code for the column. For lyskom-format. :output Function that outputs the column. If width is nil, the field is dynamically sized. All dynamically sized fields share the available width, according to their respective weights. Columns will always be at least as wide as the column heading. Note that weight must be a floating-point number, or the arithmetic used to comput dynamic columns will not work. The weight is only used for dynamic columns." ) (defun lyskom-list-text-summary-subject (text-stat) "Handle subject field for a text summary listing." (let* ((mode (lyskom-list-text-summary-get :subject-mode)) (indent (lyskom-list-text-summary-get :subject-indent)) (text (lyskom-list-text-summary-get :text)) (txt (text->decoded-text-mass text text-stat)) (eos (and txt (string-match (regexp-quote "\n") txt))) (subject (if eos (substring txt 0 eos) ""))) (cond ((eq mode 'unique) (if (lyskom-string-member subject (lyskom-list-text-summary-get :subjects)) (throw 'lyskom-list-text-summary-abort t) (lyskom-list-text-summary-put :subjects (cons subject (lyskom-list-text-summary-get :subjects)) t))) ((eq mode 'thread) (when (and (not (eq indent 0)) (string-equal (lyskom-list-text-summary-get :subject-last) subject)) (setq subject "")))) (unless (string-equal "" subject) (lyskom-list-text-summary-put :subject-last subject t)) (lyskom-format "%#1@%#2r" (lyskom-default-button 'text (text-stat->text-no text-stat)) (concat (cond ((not indent) "") ((>= indent 10) (format ">>>[%d]>>>" indent)) (t (make-string indent ?\>))) subject)) )) ;; Sub-optimal (i.e. too much code) implementation for the sake of ;; clarity. It is possible to implement this with far less computation ;; and fewer variables, but the code tends to be harder to understand. (defun lyskom-summary-line-format-string (spec) "Return header and format string for text summary lines. SPEC is the specification for the line. It is a list of symbols that must exist as keys in lyskom-text-summary-fields and strings, which must be valid for lyskom-format (i.e. with percent signs doubled. Returns a cons of the header string and a format string for the " (let ((total-field-width 0) (field-width-list nil) (dynamic-width nil) (dynamic-weight 0)) ;; Compute dynamic widths (lyskom-traverse el spec (if (stringp el) (setq total-field-width (+ total-field-width (lyskom-string-width el))) (let* ((field-spec (cdr (assq el lyskom-text-summary-fields))) (prompt (plist-get field-spec :prompt)) (dw (plist-get field-spec :weight)) (w1 (plist-get field-spec :width)) (w2 (cond ((functionp w1) (funcall w1)) ((numberp w1) w1) ((null w1) nil)))) (if (null w2) (setq dynamic-weight (+ dynamic-weight dw)) (setq w2 (max w2 (if prompt (lyskom-string-width (lyskom-get-string prompt)) 0))) (setq total-field-width (+ total-field-width w2))) (setq field-width-list (cons w2 field-width-list))))) (setq dynamic-width (- (1- (window-width)) total-field-width) field-width-list (nreverse field-width-list)) ;; Now dynamic-width contains the total width allocated to dynamically ;; sized fields. We will calculate the individual field widths like ;; this: ;; ;; field-width := floor(dynamic-width / num-dynamic-fields) ;; dynamic-width := dynamic-width - field-width ;; num-dynamic-fields := num-dynamic-fields - 1 ;; ;; This spreads the available space as equally as possible and ;; eliminates any possibility of round-off errors since everything ;; can be implemented using integer arithmetic. (let ((field-no 0) (format-string "") (header-string "")) (lyskom-traverse el spec (if (stringp el) (setq format-string (concat format-string el) header-string (concat header-string (lyskom-format el))) (let* ((field-spec (cdr (assq el lyskom-text-summary-fields))) (prompt (plist-get field-spec :prompt)) (width (car field-width-list))) (unless width (let* ((dw (plist-get field-spec :weight)) (frac (floor (* dynamic-width (/ dw dynamic-weight))))) (setq width (max (if prompt (lyskom-string-width (lyskom-get-string prompt)) 0) frac)) (setq dynamic-width (- dynamic-width width)) (setq dynamic-weight (- dynamic-weight dw)))) (setq field-no (1+ field-no) format-string (concat format-string (format "%%%s%s%d#%d%s" (if (null (car field-width-list)) "=" "") (if (eq (plist-get field-spec :align) 'left) "-" "") width field-no (plist-get field-spec :format))) header-string (concat header-string (lyskom-format (format "%%%s%d#1s" (if (eq (plist-get field-spec :align) 'left) "-" "") width) (if prompt (lyskom-get-string prompt) ""))) field-width-list (cdr field-width-list) )))) (cons header-string format-string)))) (defun lyskom-list-text-summary-print (spec &rest args) (setq lyskom-list-text-summary-params args) (if (or (null (lyskom-list-text-summary-get :text-stat)) (null (lyskom-list-text-summary-get :text))) (lyskom-format-insert 'could-not-read (lyskom-list-text-summary-get :text-no)) (catch 'lyskom-list-text-summary-abort (apply 'lyskom-format-insert lyskom-list-text-summary-format (delq 'CONSTANT-STRING (mapcar (lambda (el) (if (stringp el) 'CONSTANT-STRING (let* ((field-spec (cdr (assq el lyskom-text-summary-fields))) (output (plist-get field-spec :output))) (funcall output (lyskom-list-text-summary-get :text-stat))))) spec))) (lyskom-insert "\n")) )) (defun lyskom-list-text-summary (text-list spec &rest args) "List a summary of texts in TEXT-LIST according to SPEC. TEXT-LIST is a list of text numbers or marks. SPEC is a list of symbols and constant strings. The symbols must be keys in lyskom-text-summary-fields. Args is a list of keywords, some of which may have arguments :unique Only print the first text with a specific subject :comment-order Print texts in comment order, with indented subjects :filter FN Filter function (see below) :filter-args ARGS Filter arguments (see below). The filter function is applied to each element of text-list. It is passed the text-list element as its first argument, and elements of :filter-args as its remaining arguments. The text will be listed only if the filter function returns non-nil." (setq spec (or spec '(text-no " " written " " lines " " comments " " author " " subject))) (let* ((text-no nil) (indent 0) (comment-order nil) (filter-function nil) (filter-args nil) (lyskom-list-text-summary-tmp (lyskom-summary-line-format-string spec)) (lyskom-list-text-summary-params nil) (lyskom-list-text-summary-params-persistent nil) (lyskom-list-text-summary-format (cdr lyskom-list-text-summary-tmp))) (lyskom-list-text-summary-put :subject-mode nil t) (while args (cond ((eq (car args) :unique) (lyskom-list-text-summary-put :subject-mode 'unique t)) ((eq (car args) :comment-order) (setq comment-order t) (lyskom-list-text-summary-put :subject-mode 'thread t)) ((eq (car args) :filter) (setq filter-function (car (cdr args)) args (cdr args))) ((eq (car args) :filter-args) (setq filter-args (car (cdr args)) args (cdr args)))) (setq args (cdr args))) (lyskom-insert (car lyskom-list-text-summary-tmp)) (lyskom-insert "\n") (lyskom-list-text-summary-put :subject-indent 0) (while text-list (setq text-no (car text-list) text-list (cdr text-list)) (when (or (null filter-function) (apply filter-function text-no filter-args)) (cond ((eq text-no 'in) (setq indent (1+ indent))) ((eq text-no 'out) (setq indent (1- indent))) (t (let (mark) (cond ((lyskom-mark-p text-no) (setq mark text-no text-no (mark->text-no text-no))) ((numberp text-no))) (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (lyskom-list-text-summary-print spec :text-no text-no :text-stat text-stat :text text :mark mark :subject-indent indent) (sit-for 0) (when comment-order (let ((comments (lyskom-text-comments text-stat))) (setq text-list (cons 'out text-list)) (lyskom-traverse comment-no (nreverse comments) (when (memq comment-no text-list) (setq text-list (cons comment-no (delq comment-no text-list))))) (setq text-list (cons 'in text-list)))))) )))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: completing-read.el,v 44.52 2003/08/25 17:36:39 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: completing-read.el ;;;; Author: David Byers ;;;; ;;;; This file implements functions for reading a conference name ;;;; or a person name with completion and other help. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: completing-read.el,v 44.52 2003/08/25 17:36:39 byers Exp $\n")) (defvar lyskom-name-hist nil) ;;; ============================================================ ;;; ;;; Name lookup caches ;;; (defvar lyskom-completing-who-info-cache nil "Temporary cache of who-info data") (defvar lyskom-completing-lookup-name-cache nil "Temporary cache of server queries") (defvar lyskom-completing-use-dynamic-info nil) (defun lyskom-completing-clear-cache () (setq lyskom-completing-who-info-cache nil) (setq lyskom-completing-lookup-name-cache nil)) (defun lyskom-completing-who-is-on () "Get information about who is on, first checking the cache. Returns what \(blocking-do 'who-is-on\) would, but as a list, not a vector" (if lyskom-completing-who-info-cache lyskom-completing-who-info-cache (setq lyskom-completing-who-info-cache (listify-vector (if (lyskom-have-feature dynamic-session-info) (blocking-do 'who-is-on-dynamic t t 0) (blocking-do 'who-is-on)))))) (defun lyskom-completing-cache-completion (string data) (let* ((downs (lyskom-unicase string)) (tmp (assoc downs lyskom-completing-lookup-name-cache))) (if (null tmp) (setq lyskom-completing-lookup-name-cache (cons (cons downs data) lyskom-completing-lookup-name-cache))) string)) (defun lyskom-completing-lookup-z-name (string want-conf want-pers) "Look up STRING as a name. Same as \(blocking-do 'lookup-z-name ...\) but first checks a cache." (if (and (eq 0 want-conf) (eq 0 want-pers)) nil (let* ((downs (lyskom-unicase string)) (tmp (assoc downs lyskom-completing-lookup-name-cache))) (if tmp (cdr tmp) (progn (setq tmp (blocking-do 'lookup-z-name string want-pers want-conf)) (setq lyskom-completing-lookup-name-cache (cons (cons downs tmp) lyskom-completing-lookup-name-cache)) tmp))))) ;;; ============================================================ ;;; ;;; Keymaps ;;; (defvar lyskom-minibuffer-local-completion-map (let ((map (copy-keymap minibuffer-local-completion-map))) (define-key map " " nil) map) "Keymap used for reading LysKOM names.") (defvar lyskom-minibuffer-local-must-match-map (let ((map (copy-keymap minibuffer-local-must-match-map))) (lyskom-xemacs-or-gnu (lyskom-set-keymap-parent map lyskom-minibuffer-local-completion-map) (define-key map " " nil)) map) "Keymap used for reading LysKOM names.") (defsubst lyskom-completing-match-string-regexp (string) (concat "^" (replace-in-string (regexp-quote (lyskom-unicase (lyskom-completing-strip-name string))) "\\s-+" "\\\\S-*\\\\s-+") "\\s-*")) (defsubst lyskom-completing-match-string (string name) "Return non-nil if STRING matches NAME using LysKOM completion rules." (string-match (lyskom-completing-match-string-regexp string) (lyskom-completing-strip-name (lyskom-unicase name)))) (defun lyskom-read-conf-no (prompt type &optional empty initial mustmatch) "Read a conference name from the minibuffer with completion and return its number or zero if nothing was matched. See lyskom-read-conf for a description of the parameters." (let ((conf-z-info (lyskom-read-conf prompt type empty initial mustmatch))) (cond ((null conf-z-info) 0) ((stringp conf-z-info) 0) ((lyskom-conf-stat-p conf-z-info) (conf-stat->conf-no conf-z-info)) ((lyskom-uconf-stat-p conf-z-info) (uconf-stat->conf-no conf-z-info)) (t (conf-z-info->conf-no conf-z-info))))) (defun lyskom-read-conf-stat (prompt type &optional empty initial mustmatch) "Read a conference name from the minibuffer with completion and return its conf-stat or nil if nothing was matched. See lyskom-read-conf for a description of the parameters." (let ((conf-z-info (lyskom-read-conf prompt type empty initial mustmatch))) (cond ((null conf-z-info) nil) ((stringp conf-z-info) nil) ((lyskom-conf-stat-p conf-z-info) conf-z-info) ((lyskom-uconf-stat-p conf-z-info) (blocking-do 'get-conf-stat (uconf-stat->conf-no conf-z-info))) (t (blocking-do 'get-conf-stat (conf-z-info->conf-no conf-z-info)))))) (defun lyskom-read-uconf-stat (prompt type &optional empty initial mustmatch) "Read a conference name from the minibuffer with completion and return its conf-stat or nil if nothing was matched. See lyskom-read-conf for a description of the parameters." (let ((conf-z-info (lyskom-read-conf prompt type empty initial mustmatch))) (cond ((null conf-z-info) nil) ((stringp conf-z-info) nil) ((lyskom-uconf-stat-p conf-z-info) conf-z-info) ((lyskom-conf-stat-p conf-z-info) (blocking-do 'get-uconf-stat (conf-stat->conf-no conf-z-info))) (t (blocking-do 'get-uconf-stat (conf-z-info->conf-no conf-z-info)))))) (defun lyskom-read-conf-name (prompt type &optional empty initial mustmatch) "Read a conference name from the minibuffer with completion and return its name. See lyskom-read-conf for a description of the parameters." (let ((conf-z-info (lyskom-read-conf prompt type empty initial mustmatch))) (cond ((null conf-z-info) "") ((stringp conf-z-info) conf-z-info) ((lyskom-conf-stat-p conf-z-info) (conf-stat->name conf-z-info)) ((lyskom-uconf-stat-p conf-z-info) (uconf-stat->name conf-z-info)) (t (conf-z-info->name conf-z-info))))) ;;; ================================================================ ;;; Code to guess defaults for initial input ;;; (defun lyskom-default-conference-at-point (&rest args) (let* ((pos (or lyskom-command-point (point))) (type (and pos (get-text-property pos 'lyskom-button-type)))) (and (memq type '(conf pers)) (list (get-text-property pos 'lyskom-button-arg))))) (defun lyskom-default-conference-current (&rest args) (list lyskom-current-conf)) (defun lyskom-default-conference-self (&rest args) (list lyskom-pers-no)) (defun lyskom-default-conference-last-author (&rest args) (and (lyskom-get-last-read-text) (list (text-stat->author (blocking-do 'get-text-stat (lyskom-get-last-read-text)))))) (defun lyskom-default-conference-restriction (predicate &rest args) (and (assq 'restrict predicate) (cdr (assq 'restrict predicate)))) (defun lyskom-default-conference-empty (&rest args) nil) (defun lyskom-default-conference-saved (sym &rest args) (save-excursion (when lyskom-buffer (set-buffer lyskom-buffer)) (and (cdr (assq (car sym) lyskom-read-conf-saved-inputs)) (list (conf-z-info->conf-no (cdr (assq (car sym) lyskom-read-conf-saved-inputs))))))) (defun lyskom-default-conference-not-self (uc &rest args) (not (eq (uconf-stat->conf-no uc) lyskom-pers-no))) (defun lyskom-default-conference-not-current (uc &rest args) (not (eq (uconf-stat->conf-no uc) lyskom-current-conf))) (defun lyskom-get-initial-conf-strategy (prompt) (when (listp prompt) (setq prompt (car prompt))) (let* ((spec-1 (cdr (assq (or lyskom-current-command this-command) lyskom-default-conference-strategy))) (default-spec (cdr (assq t (assq t lyskom-default-conference-strategy)))) (prompt-spec (cdr (assq prompt spec-1))) (cmd-spec (cdr (assq t spec-1)))) (lyskom-debug-forms (unless spec-1 (save-excursion (when lyskom-buffer (set-buffer lyskom-buffer)) (lyskom-format-insert-before-prompt "%[%#2@%#1s%]\n" (format "Warning: no strategy for %S/%S" (or lyskom-current-command this-command) prompt) `(face ,kom-warning-face))))) (list (or (assq 'default prompt-spec) (assq 'default cmd-spec) (assq 'default default-spec)) (or (assq 'filter prompt-spec) (assq 'filter cmd-spec) (assq 'filter default-spec)) (or (assq 'save prompt-spec) (assq 'save cmd-spec) (assq 'save default-spec))))) (defun lyskom-read-conf-guess-initial (prompt predicate) "Return a guess for the initial value for lyskom-read-conf." (let* ((strategy (lyskom-get-initial-conf-strategy prompt)) (default (cdr (assq 'default strategy))) (filter (cdr (assq 'filter strategy)))) (uconf-stat->name (car (filter-list (lambda (uconf-stat) (and uconf-stat (not (memq nil (mapcar (lambda (fn) (funcall fn uconf-stat)) filter))) (lyskom-read-conf-internal-verify-type (uconf-stat->conf-no uconf-stat) (uconf-stat->conf-type uconf-stat) predicate nil nil))) (mapcar (lambda (conf-no) (blocking-do 'get-uconf-stat conf-no)) (apply 'append (delq nil (mapcar (lambda (fn) (if (listp fn) (funcall (car fn) (cdr fn) predicate) (funcall fn predicate))) default))))))))) (defun lyskom-read-conf-save-input (prompt input) "Save INPUT as input for the current completing read command." (save-excursion (when lyskom-buffer (set-buffer lyskom-buffer)) (lyskom-traverse sym (cdr (assq 'save (lyskom-get-initial-conf-strategy prompt))) (if (assq sym lyskom-read-conf-saved-inputs) (setcdr (assq sym lyskom-read-conf-saved-inputs) input) (setq lyskom-read-conf-saved-inputs (cons (cons sym input) lyskom-read-conf-saved-inputs)) )))) (defun lyskom-read-conf (prompt type &optional empty initial mustmatch) "Completing read a conference or person from the minibuffer. PROMPT is the prompt. It can be a string, symbol or list. If it is a symbol, lyskom-get-string will be used to get the string. If it is a list, it is used as the argument list to lyskom-format to create the prompt. You should use symbols and lists only. TYPE is the type of conferences to return. It is a list of one or more of the following: all Return any conference. conf Return conferences (not letterboxes). pers Return persons (letterboxes). login Return persons who are also logged-in. membership Return only conferences and letterboxes lyskom-pers-no is a member of. none Return names that do not match anything in the database. (restrict c1 c2 ...) Restrict matching to conference numbers c1, c2 etc. The implementation is inefficient for long lists. Optional arguments EMPTY allow nothing to be entered. INITIAL initial contents of the minibuffer. If an integer, use the name of that conference. This is normally computed automatically, so pass nil whenever possible. MUSTMATCH if non-nil, the user must enter a valid name. The return value may be one of A conf-z-info: The conf-z-info associated with the name entered, nil: Nothing was entered, or A string: A name that matched nothing in the database." ;; We bind lyskom-current-command here so that changes to ;; this-command will not confuse our guesses for the initial value ;; (particularly at the end of this function, where we sometimes ;; save the value the user entered). (let ((lyskom-current-command (or lyskom-current-command this-command))) (lyskom-completing-clear-cache) (setq initial (cond ((integerp initial) (uconf-stat->name (blocking-do 'get-uconf-stat initial))) ((stringp initial) initial) ((lyskom-conf-stat-p initial) (conf-stat->name initial)) ((lyskom-uconf-stat-p initial) (uconf-stat->name initial)) ((lyskom-conf-z-info-p initial) (conf-z-info->name initial)) ((consp initial) initial) ((lyskom-read-conf-guess-initial prompt type)) (t nil))) (let* ((completion-ignore-case t) (minibuffer-local-completion-map lyskom-minibuffer-local-completion-map) (minibuffer-local-must-match-map lyskom-minibuffer-local-must-match-map) (read-string nil) (old-prompt prompt) (result nil) (keep-going t)) (setq prompt (cond ((stringp prompt) prompt) ((symbolp prompt) (lyskom-get-string prompt)) ((listp prompt) (apply 'lyskom-format prompt)) (t (lyskom-get-string 'conf-prompt)))) (while keep-going (setq read-string (lyskom-completing-read prompt 'lyskom-read-conf-internal type mustmatch (if (listp initial) initial (cons initial 0)) 'lyskom-name-hist)) (setq result (cond ((null read-string) nil) ((string= "" read-string) nil) (t (lyskom-lookup-conf-by-name read-string type)))) (setq keep-going (and (not empty) (null result)))) (lyskom-read-conf-save-input old-prompt result) result))) (defun lyskom-read-conf-get-logins () "Used internally by lyskom-read-conf-internal to get a list of persons who are logged on." (mapcar (if (lyskom-have-feature dynamic-session-info) (function (lambda (el) (dynamic-session-info->person el))) (function (lambda (el) (who-info->pers-no el)))) (lyskom-completing-who-is-on))) (defun lyskom-read-conf-expand-specials (string predicate login-list x-list &optional return-cs) "Used internally by lyskom-read-conf-internal to expand person and conference number specifications to something useful." (cond ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) (let* ((no (string-to-int (match-string 1 string))) (cs (blocking-do 'get-uconf-stat no))) (if (and cs (lyskom-read-conf-internal-verify-type (uconf-stat->conf-no cs) (uconf-stat->conf-type cs) predicate login-list x-list)) (if return-cs cs (list string))))) ((string-match (lyskom-get-string 'session-no-regexp) string) (let* ((no (string-to-int (match-string 1 string))) (si (blocking-do 'get-session-info no)) (cs (and si (blocking-do 'get-uconf-stat (session-info->pers-no si))))) (if (and cs (lyskom-read-conf-internal-verify-type (uconf-stat->conf-no cs) (uconf-stat->conf-type cs) predicate login-list x-list)) (if return-cs cs (list string))))))) (defun lyskom-read-conf-lookup-specials (string predicate login-list x-list) "Used internally by lyskom-read-conf-internal to look up conf-stats from person and conference number specifications." (let ((cs (lyskom-read-conf-expand-specials string predicate login-list x-list t))) (lyskom-create-conf-z-info (uconf-stat->name cs) (uconf-stat->conf-type cs) (uconf-stat->conf-no cs)))) (defun lyskom-lookup-conf-by-name (string predicate) "Return the conf-z-info associated with STRING that also satisfies PREDICATE or nil if no name matches. See lyskom-read-conf-internal for a documentation of PREDICATE." (if (string= string "") nil (lyskom-read-conf-internal string predicate 'lyskom-lookup))) (defun lyskom-read-conf-internal (string predicate all) "Complete the name STRING according to PREDICATE and ALL. STRING is a string to complete. PREDICATE is a list of name types to return. See lyskom-read-conf for details. ALL is set by try-completion and all-completions. See the Emacs lisp manual for a description. Special value 'lyskom-lookup makes the function work as a name-to-conf-stat translator." ;; ;; Catch some degenerate cases that can cause...problems. This ;; won't solve all the...problems, but should speed things up a ;; little bit. ;; (cond ((and (null all) (string-match "^\\s-*$" string)) "") ((and (eq all 'lyskom-lookup) (string-match "^\\s-*$" string)) nil) ((and (eq all 'lambda) (string-match "^\\s-*$" string)) nil) (t (let* ((login-list (and (memq 'login predicate) (lyskom-read-conf-get-logins))) (x-list (lyskom-completing-lookup-z-name string (if (or (memq 'all predicate) (memq 'membership predicate) (memq 'conf predicate) (memq 'none predicate)) 1 0) (if (or (memq 'all predicate) (memq 'membership predicate) (memq 'pers predicate) (memq 'none predicate) (memq 'login predicate)) 1 0))) (r-list (when (assq 'restrict predicate) (let ((result (make-collector))) (lyskom-traverse conf-no (cdr (assq 'restrict predicate)) (initiate-get-uconf-stat 'main 'collector-push conf-no result)) (lyskom-wait-queue 'main) (delq nil (mapcar (lambda (conf-stat) (when (lyskom-completing-match-string string (uconf-stat->name conf-stat)) (lyskom-create-conf-z-info (uconf-stat->name conf-stat) (uconf-stat->conf-type conf-stat) (uconf-stat->conf-no conf-stat)))) (collector->value result)))))) (candidate-list (append r-list (if x-list (conf-z-info-list->conf-z-infos x-list)))) (result-list nil)) ;; ;; login-list now contains a list of logins, IF the predicate ;; includes 'login ;; ;; candidate-list contains a list of conf-z-infos ;; ;; Now set result-list to the conf-z-infos that fulfill the ;; predicate, fetching the conf-stats asynchronously. ;; (lyskom-traverse el candidate-list (if (lyskom-read-conf-internal-verify-type (conf-z-info->conf-no el) (conf-z-info->conf-type el) predicate login-list candidate-list) (setq result-list (cons el result-list)))) ;; ;; Now the matching conf-z-infos are in result-list ;; (cond ((eq all 'lyskom-lookup) (let ((names (mapcar 'conf-z-info->name result-list)) (specials (lyskom-read-conf-expand-specials string predicate login-list candidate-list))) (cond ((and kom-complete-numbers-before-names specials) (lyskom-read-conf-lookup-specials string predicate login-list candidate-list)) ((= (length result-list) 1) (car result-list)) ((and (> (length result-list) 1) (lyskom-completing-member string names)) (elt result-list (- (length result-list) (length (lyskom-completing-member string names))))) (specials (lyskom-read-conf-lookup-specials string predicate login-list candidate-list)) ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) nil) ((string-match (lyskom-get-string 'session-no-regexp) string) nil) ((lyskom-read-conf-internal-verify-type nil nil predicate login-list candidate-list) string)))) ;; ;; Check for exact match. We have an exact match in the server ;; when there was a single match OR when there was no match, and ;; no match is valid according to predicate ;; ((eq all 'lambda) (let ((specials (lyskom-read-conf-expand-specials string predicate login-list candidate-list))) (cond ((= (length result-list) 1) t) ((and (> (length result-list) 1) (let ((names (mapcar 'conf-z-info->name result-list))) (and (lyskom-completing-member string names) t)))) (result-list nil) ((= (length specials) 1) t) (specials nil) ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) nil) ((string-match (lyskom-get-string 'session-no-regexp) string) nil) (t (lyskom-read-conf-internal-verify-type nil nil predicate login-list candidate-list))))) ;; ;; Called from all-completions. Return a list of all possible ;; completions, in this case all names in the result list plus, ;; if the input string is a person or conf number specification, ;; the input string, PROVIDED, the requested conference matches ;; the predicate. If there were no matches, return the input ;; string if no matches satisfies the predicate. ;; (all (let ((names (mapcar 'conf-z-info->name result-list)) (specials (lyskom-read-conf-expand-specials string predicate login-list candidate-list))) (cond (specials (append specials names)) (names names) ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) nil) ((string-match (lyskom-get-string 'session-no-regexp) string) nil) ((lyskom-read-conf-internal-verify-type nil nil predicate login-list candidate-list) (list string)) (t nil)))) ;; ;; Called from try-completion, and there were no matches. Try to ;; expand the input string as a person or conf number ;; specification or return something sensible if the predicate ;; is satisfied by no matches. ;; ((null result-list) (let ((specials (lyskom-read-conf-expand-specials string predicate login-list candidate-list))) (cond (specials (car specials)) ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) nil) ((string-match (lyskom-get-string 'session-no-regexp) string) nil) ((lyskom-read-conf-internal-verify-type nil nil predicate login-list candidate-list) t) (t nil)))) ;; ;; Called from try-completion, and there were matches in the ;; server. Return t if the string is an exact match to any ;; string returned from the server. Otherwise, expand the string ;; as far as possible and return that ;; (t (let ((name-list (mapcar 'conf-z-info->name result-list)) (specials (lyskom-read-conf-expand-specials string predicate login-list candidate-list))) (if specials (setq name-list (nconc specials name-list))) (cond ((lyskom-completing-member string name-list) (or (and (= (length name-list) 1) t) string)) ; Exact match ((= (length name-list) 1) (car name-list)) ((string-match (lyskom-get-string 'person-or-conf-no-regexp) string) nil) ((string-match (lyskom-get-string 'session-no-regexp) string) nil) (t (or (lyskom-completing-cache-completion (lyskom-complete-string name-list) (if r-list (lyskom-create-conf-z-info-list (apply 'vector candidate-list)) x-list)) (and (lyskom-read-conf-internal-verify-type nil nil predicate login-list candidate-list) (list string)))))))))))) (defun lyskom-completing-member (string list) (let ((string (lyskom-unicase (lyskom-completing-strip-name string))) (result nil)) (while (and list (not result)) (if (lyskom-string= string (lyskom-unicase (lyskom-completing-strip-name (car list)))) (setq result list) (setq list (cdr list)))) result)) (defun lyskom-completing-strip-name (string) "Strip parens and crap from a name." (while (string-match "([^()]*)" string) (setq string (replace-match " " t t string))) (while (string-match "\\s-\\s-+" string) (setq string (replace-match " " t t string))) (while (string-match "([^()]*$" string) (setq string (substring string 0 (match-beginning 0)))) (if (string-match "^\\s-*\\(.*\\S-\\)\\s-*$" string) (match-string 1 string) string)) (defun lyskom-read-conf-internal-verify-type (conf-no conf-type predicate logins x-list) (or (memq conf-no (cdr (assq 'restrict predicate))) (and (memq 'all predicate) conf-no) (and (memq 'conf predicate) conf-type (not (conf-type->letterbox conf-type))) (and (memq 'pers predicate) conf-type (conf-type->letterbox conf-type)) (and (memq 'login predicate) conf-no (memq conf-no logins)) (and (memq 'membership predicate) conf-no (lyskom-get-membership conf-no t)) (and (memq 'none predicate) (and (null conf-no) (null x-list))))) ;;; FOR DEBUGGING (DON'T DELETE) /byers ;;; ;;; (defun lyskom-complete-show-data-list (state data) ;;; (save-excursion ;;; (pop-to-buffer (get-buffer-create "*kom*-complete")) ;;; (erase-buffer) ;;; (lyskom-set-buffer-multibyte nil) ;;; (while data ;;; (insert ;;; (format "%s\n" (substring (aref (car data) 2) ;;; (aref (car data) 0) ;;; (aref (car data) 1)))) ;;; (setq data (cdr data))) ;;; (insert (format "%S %S: %S" (symbol-value current-state) ;;; (elt state 0) ;;; (elt state 1))) ;;; (sit-for 5))) (defun lyskom-complete-string (string-list) "Find the longest common prefix of all strings in STRING-LIST according to the LysKOM rules of string matching." (let ((main-state 'start-of-string) (tmp-state nil) (current-state 'main-state) (main-accumulator nil) (tmp-accumulator nil) (current-accumulator 'main-accumulator) (done nil) (paren-depth 0) (have-here nil) (last-event-worth-noting nil) (data-list (lyskom-complete-string-munge-input string-list)) (next-char-state (vector nil nil))) (while (not done) (lyskom-complete-string-next-char next-char-state data-list) ; (lyskom-complete-show-data-list next-char-state data-list) (cond ;; ;; Case one, a match of two non-special characters. ;; Accumulate one character and advance the lists ;; ((eq (aref next-char-state 0) 'match) (if (eq (aref next-char-state 1) ?\ ) (progn (cond ((memq (symbol-value current-state) '(start-of-word start-of-string)) nil) ((eq last-event-worth-noting 'mismatch) (lyskom-complete-string-accumulate current-accumulator 'SPC)) (t (lyskom-complete-string-accumulate current-accumulator ?\ ))) (set current-state 'start-of-word) (lyskom-complete-string-advance data-list)) (progn (set current-state 'in-a-word) (lyskom-complete-string-accumulate current-accumulator (aref next-char-state 1)) (lyskom-complete-string-advance data-list))) (setq last-event-worth-noting 'match)) ;; ;; Case two, a match of two open-paren expressions Increase ;; paren depth and accumulate a character. First set ;; current-accumulator to the temporary if paren-depth is zero ;; to start with. ;; ((eq (aref next-char-state 0) 'open-paren-match) (setq last-event-worth-noting 'match) (if (zerop paren-depth) (progn (setq current-accumulator 'tmp-accumulator) (setq current-state 'tmp-state) (setq tmp-state main-state) (setq tmp-accumulator nil))) (setq paren-depth (1+ paren-depth)) (lyskom-complete-string-accumulate current-accumulator (aref next-char-state 1)) (lyskom-complete-string-advance data-list)) ;; ;; Case three, a match of two close-paren expressions ;; Accumulate a character. If paren-depth is postitive, ;; decrease it. If it ends up zero, add the temporary ;; accumulator to the main accumulator and set the current ;; accumulator to the main accumulator. ;; ((eq (aref next-char-state 0) 'close-paren-match) (setq last-event-worth-noting 'match) (lyskom-complete-string-accumulate current-accumulator (aref next-char-state 1)) (if (> paren-depth 0) (progn (setq paren-depth (1- paren-depth)) (if (zerop paren-depth) (progn (setq main-accumulator (nconc tmp-accumulator main-accumulator)) (setq main-state tmp-state) (setq current-state 'main-state) (setq current-accumulator 'main-accumulator))))) (lyskom-complete-string-advance data-list)) ;; ;; Case two, a mismatch of any kind in a paren expression ;; ((and (> paren-depth 0) (memq (aref next-char-state 0) '(mismatch space-mismatch open-paren-mismatch))) (setq last-event-worth-noting 'mismatch) (setq tmp-accumulator nil) (setq tmp-state nil) (setq current-state 'main-state) (setq current-accumulator 'main-accumulator) (lyskom-complete-string-close-parens data-list paren-depth) (setq paren-depth 0)) ;; ;; Case two and a half or so, a space mismatch. This is ignored ;; if we're still at the start of the string ;; ((and (eq (aref next-char-state 0) 'space-mismatch) (memq (symbol-value current-state) '(start-of-string start-of-word))) (setq last-event-worth-noting nil) (lyskom-complete-string-skip-whitespace data-list)) ;; ;; Case three, a mismatch of regular characters outside a paren ;; Advance to the end of the current word ;; ((and (memq (aref next-char-state 0) '(mismatch space-mismatch)) (zerop paren-depth)) (setq last-event-worth-noting 'mismatch) (if (memq (symbol-value current-state) '(start-of-word start-of-string)) (setq done t) (progn (if (not have-here) (progn (lyskom-complete-string-accumulate current-accumulator 'HERE) (setq have-here t))) (lyskom-complete-string-advance-to-end-of-word data-list) (set current-state 'in-a-word)))) ;; ;; Case four, a mistmatch where one character is an open-paren ;; ((eq (aref next-char-state 0) 'open-paren-mismatch) (setq last-event-worth-noting 'mismatch) (lyskom-complete-string-skip-parens data-list)) ;; ;; Case five, eof ;; ((eq (aref next-char-state 0) 'eof) (setq done t)) ;; ;; Case six, can't happen ;; (t (error "This can't happen: %S" next-char-state)))) ;; ;; Build the result by reversing the result list and making a ;; string out of it. ;; (if (eq (car main-accumulator) 'SPC) (setq main-accumulator (cdr main-accumulator))) (setq main-accumulator (nreverse main-accumulator)) (if (memq 'HERE main-accumulator) (let ((backup (length (memq 'HERE main-accumulator)))) (if lyskom-experimental-features (setq unread-command-events (append (cons ? (make-list (1- backup) 2)) unread-command-events))) (setq main-accumulator (delq 'HERE main-accumulator)))) (concat (mapcar (lambda (el) (if (eq el 'SPC) ?\ el)) main-accumulator)))) (defun lyskom-complete-string-accumulate (accumulator char) (set accumulator (cons char (symbol-value accumulator)))) (defun lyskom-complete-string-munge-input (string-list) (mapcar (function (lambda (x) (vector 0 (length x) x))) string-list)) ;;; ;;; Advance one regular character or multiple whitespaces ;;; (defun lyskom-complete-string-advance (data-list) (lyskom-traverse el data-list (string-match "\\([ \t]+\\|[^ \t]\\|$\\)" (aref el 2) (aref el 0)) (aset el 0 (match-end 0)))) (defun lyskom-complete-string-skip-whitespace (data-list) (lyskom-traverse el data-list (string-match "[ \t]*" (aref el 2) (aref el 0)) (aset el 0 (match-end 0)))) ;;; ;;; Advance to the end of the current word ;;; (defun lyskom-complete-string-advance-to-end-of-word (data-list) (lyskom-traverse el data-list (aset el 0 (string-match "\\([ \t]\\|$\\)" (aref el 2) (aref el 0))))) ;;; ;;; Unwind a number of parens ;;; (defun lyskom-complete-string-skip-parens (data-list) (lyskom-traverse el data-list (if (eq ?\( (aref (aref el 2) (aref el 0))) (progn (aset el 0 (1+ (aref el 0))) (lyskom-complete-string-close-parens-2 el 1))))) (defun lyskom-complete-string-close-parens (data-list depth) (lyskom-traverse el data-list (lyskom-complete-string-close-parens-2 el depth))) (defun lyskom-complete-string-close-parens-2 (el depth) (let ((string (aref el 2)) (pos (aref el 0))) (while (> depth 0) (cond ((>= pos (length string)) (setq depth 0)) ((eq (aref string pos) ?\)) (setq depth (1- depth))) ((eq (aref string pos) ?\)) (setq depth (1+ depth)))) (setq pos (1+ pos))) (aset el 0 pos))) ;;; ;;; Check what's happenin' next ;;; (defun lyskom-complete-string-next-char (state data-list) (let ((eofp nil) (open-paren-p nil) (close-paren-p nil) (matchp t) (spacep nil) (char nil) (xchar nil)) (lyskom-save-excursion (set-buffer lyskom-buffer) (mapcar (function (lambda (x) (cond ((>= (aref x 0) (aref x 1)) (setq eofp t) (setq matchp nil)) ((eq (aref (aref x 2) (aref x 0)) ?\() (setq open-paren-p t)) ((eq (aref (aref x 2) (aref x 0)) ?\)) (setq close-paren-p t)) ((eq (aref (aref x 2) (aref x 0)) ?\ ) (setq spacep t))) (setq matchp (and matchp (if (null char) (progn (setq xchar (aref (aref x 2) (aref x 0))) (setq char (lyskom-unicase-char xchar))) (eq char (lyskom-unicase-char (aref (aref x 2) (aref x 0))))))))) data-list)) (aset state 1 xchar) (cond (eofp (aset state 0 'eof)) ((and matchp open-paren-p) (aset state 0 'open-paren-match)) ((and matchp close-paren-p) (aset state 0 'close-paren-match)) (matchp (aset state 0 'match)) (spacep (aset state 0 'space-mismatch)) (open-paren-p (aset state 0 'open-paren-mismatch)) (t (aset state 0 'mismatch)))) state) ;;; ============================================================ ;;; ;;; Session reading ;;; ;;; (defun lyskom-read-session-no (prompt &optional empty initial only-one) (let ((possible-matches (lyskom-session-from-conf (lyskom-read-conf-no prompt (if kom-permissive-completion '(pers) '(login)) empty initial t)))) (if (and (> (length possible-matches) 1) only-one) (lyskom-read-session-resolve-ambiguity possible-matches) possible-matches))) (defun lyskom-session-from-conf (conf-no) (let ((who-list (lyskom-completing-who-is-on)) (sessions nil)) (if (lyskom-have-feature dynamic-session-info) (while who-list (if (eq (dynamic-session-info->person (car who-list)) conf-no) (setq sessions (cons (dynamic-session-info->session (car who-list)) sessions))) (setq who-list (cdr who-list))) (while who-list (if (eq (who-info->pers-no (car who-list)) conf-no) (setq sessions (cons (who-info->connection (car who-list)) sessions))) (setq who-list (cdr who-list)))) (cond ((and (null sessions) kom-permissive-completion) (list (- conf-no))) (t sessions)))) (defun lyskom-read-session-resolve-ambiguity (sessions) (lyskom-insert "\n") (let* ((s-width (1+ (apply 'max (mapcar (function (lambda (x) (lyskom-string-width (int-to-string x)))) sessions)))) (format-string-s (lyskom-info-line-format-string s-width "s" "s")) (format-string-p (lyskom-info-line-format-string s-width "P" "M"))) (lyskom-format-insert format-string-s "" (lyskom-get-string 'lyskom-name) (lyskom-get-string 'is-in-conf)) (lyskom-format-insert format-string-s "" (lyskom-get-string 'from-machine) (lyskom-get-string 'is-doing)) (lyskom-insert (concat (make-string (- (lyskom-window-width) 2) ?-) "\n")) (let ((result nil) (who-info (mapcar (function (lambda (el) (let* ((info (blocking-do 'get-session-info el)) (confconfstat (blocking-do 'get-uconf-stat (session-info->working-conf info)))) (lyskom-format-insert format-string-p (format "%d%s" (session-info->connection info) (if (eq (session-info->connection info) lyskom-session-no) "*" " ")) (session-info->pers-no info) (or confconfstat (lyskom-get-string 'not-present-anywhere))) (lyskom-format-insert format-string-p "" (lyskom-return-username info) (concat "(" (session-info->doing info) ")")) (cons (number-to-string (session-info->connection info)) info)))) (sort sessions '<)))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 2) ?-) "\n")) (lyskom-insert (lyskom-format 'total-users-sans-date (length who-info))) (lyskom-scroll) (while (string= "" (setq result (lyskom-completing-read (lyskom-get-string 'resolve-session) (lyskom-maybe-frob-completion-table who-info) nil t (car (car who-info)) nil)))) (list (session-info->connection (cdr (assoc result who-info))))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: keyboard-menu.el,v 44.6 2003/08/16 16:58:45 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: keyboard-menu.el ;;;; ;;;; Implements completing-read almost-compatible lyskom-read-from-menu ;;;; used to implement keyboard navigation of LysKOM menus ('cos tmm ;;;; was *so* ugly). ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: keyboard-menu.el,v 44.6 2003/08/16 16:58:45 byers Exp $\n")) (defvar lyskom-keyboard-menu-menu) (defvar lyskom-keyboard-menu-buffer) (defvar lyskom-keyboard-menu-prompt) (defvar lyskom-keyboard-menu-selection) (defvar lyskom-keyboard-menu-overlay) (defvar lyskom-keyboard-menu-keymap nil) (defun lyskom-keyboard-menu-read-char (prompt) "Read a single keyboard event from the keyboard. Like read-event in Gnu Emacs or next-command-event in XEmacs." (message prompt) (sit-for 0) (lyskom-xemacs-or-gnu (let ((ev (next-command-event nil prompt))) (when (eq 'key-press (event-type ev)) (cond ((eq (event-key ev) 'return) 'return) ((event-to-character ev)) ((event-key ev)) (t nil)))) (read-event))) (defun lyskom-keyboard-menu-keys-for-string (string) "Return a list of suitable mnemonics for menu item STRING." (let ((a-uc nil) (a-lc nil) (b-uc nil) (b-lc nil) (c-uc nil) (c-lc nil)) (lyskom-traverse word (string-split " " string) (unless (eq (elt word 0) ?\() (setq a-lc (cons (downcase (substring word 0 1)) a-lc) a-uc (cons (upcase (substring word 0 1)) a-uc)) (when (> (length word) 1) (setq b-lc (cons (downcase (substring word 1 2)) b-lc) b-uc (cons (upcase (substring word 1 2)) b-uc))) (when (> (length word) 2) (setq c-lc (cons (downcase (substring word 2 3)) c-lc) c-uc (cons (upcase (substring word 2 3)) c-uc))) )) (mapcar (lambda (s) (lyskom-xemacs-or-gnu s (lyskom-encode-coding-string s (and (boundp 'default-keyboard-coding-system) default-keyboard-coding-system)))) (nconc (nreverse a-lc) (nreverse b-lc) (nreverse c-lc) (nreverse a-uc) (nreverse b-uc) (nreverse c-uc) )))) (defun lyskom-keyboard-menu-frob-table (table) "Convert TABLE to a form suitable for keyboard menus. TABLE is an alist whose elements' cars are strings. The result will be an alist whose elements' cars are mnemonics for the string in the same element's cdr." (let ((used-keys nil) (default-keys "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") (default-keys-index 0)) (nconc (mapcar (lambda (element) (let* ((string (car element)) (keys (lyskom-keyboard-menu-keys-for-string string)) (mnemonic (lyskom-traverse key keys (unless (member key used-keys) (lyskom-traverse-break key))))) (while (and (not mnemonic) (< default-keys-index (length default-keys))) (let ((key (substring default-keys default-keys-index (1+ default-keys-index)))) (unless (member key used-keys) (setq mnemonic key)))) (setq used-keys (cons mnemonic used-keys)) (list mnemonic string element))) table) (list (list "C-g" (lyskom-get-string 'keyboard-cancel) nil))))) (defun lyskom-keyboard-menu-highlight-selected () "Highlight the selected menu item" (set-buffer lyskom-keyboard-menu-buffer) (let ((pos (text-property-any (point-min) (point-max) 'lyskom-keyboard-menu-item lyskom-keyboard-menu-selection))) (cond ((or (null pos) (null lyskom-keyboard-menu-selection)) (lyskom-xemacs-or-gnu (set-extent-face lyskom-keyboard-menu-overlay nil) (overlay-put lyskom-keyboard-menu-overlay 'face nil)) (goto-char (point-min))) (t (let ((start pos) (end (or (next-single-property-change pos 'lyskom-keyboard-menu-item) (point-max)))) (lyskom-xemacs-or-gnu (set-extent-endpoints lyskom-keyboard-menu-overlay start end) (move-overlay lyskom-keyboard-menu-overlay start end))) (goto-char pos) (lyskom-xemacs-or-gnu (set-extent-face lyskom-keyboard-menu-overlay kom-mark-face) (overlay-put lyskom-keyboard-menu-overlay 'face kom-mark-face)))) (save-excursion (unless (pos-visible-in-window-p pos) (recenter))))) (defun lyskom-keyboard-menu-format-item (item &optional pad-len) "Format a single menu item as a string" (let ((string (format "%s (%s)" (elt item 1) (elt item 0)))) (when (and pad-len (> pad-len (length string))) (setq string (concat string (make-string (- pad-len (length string)) ?\ )))) (add-text-properties 0 (length string) (list 'lyskom-keyboard-menu-item item) string) string)) (defun lyskom-keyboard-menu-insert (prompt menu) "Insert the text-based representation of the menu. PROMPT is the menu title and MENU is the menu data." (let* ((line-length (apply 'max (mapcar (lambda (x) (+ (length (elt x 0)) (length (elt x 1)) 3)) menu))) (columns (/ (+ (window-width) 1) (+ line-length 2))) (dashes (make-string (+ (* line-length columns) (* 2 (1- columns))) ?-)) (quit-item nil)) (insert (format "%s\n%s\n" prompt dashes)) (lyskom-traverse el menu (if (null (elt el 2)) (setq quit-item el) (let ((string (lyskom-keyboard-menu-format-item el line-length))) (when (> (+ (current-column) (length string) 2) (window-width)) (insert "\n")) (unless (bolp) (insert " ")) (insert string)))) (unless (bolp) (insert "\n")) (insert dashes) (insert "\n") (when quit-item (insert (lyskom-keyboard-menu-format-item quit-item))))) ;;; ================================================================ ;;; Interactive commands ;;; (defun lyskom-read-from-menu (prompt table) "Let the user select one of the values in TABLE. TABLE is an alist whose elements' cars are strings. Returns the selected string." (let* ((menu (lyskom-keyboard-menu-frob-table table)) (buffer (get-buffer-create "*Keyboard menu*")) (menu-window-height 0)) (save-excursion ;; Format the buffer (set-buffer buffer) (erase-buffer) (lyskom-keyboard-menu-insert prompt menu) (goto-char (point-min)) (setq menu-window-height (+ 2 (count-lines (point-min) (point-max)))) ;; Display the window and do the thing (save-window-excursion (if (< (- (window-height (selected-window)) menu-window-height) 5) (select-window (display-buffer buffer t)) (split-window (selected-window) menu-window-height) (switch-to-buffer buffer)) (let* ((lyskom-keyboard-menu-buffer buffer) (lyskom-keyboard-menu-menu menu) (lyskom-keyboard-menu-selection nil) (lyskom-keyboard-menu-overlay (lyskom-xemacs-or-gnu (make-extent 1 1 lyskom-keyboard-menu-buffer) (make-overlay 0 0 lyskom-keyboard-menu-buffer))) (result nil)) (lyskom-xemacs-or-gnu (set-extent-face lyskom-keyboard-menu-overlay nil) (overlay-put lyskom-keyboard-menu-overlay 'face nil)) (condition-case nil (while (null result) (lyskom-keyboard-menu-highlight-selected) (let ((c (lyskom-keyboard-menu-read-char (lyskom-format "%#1s %#2s: %#3s" prompt (lyskom-get-string 'keyboard-menu-help) (or (elt lyskom-keyboard-menu-selection 1) ""))))) (cond ((eq (lookup-key global-map (vector c)) 'keyboard-quit) (keyboard-quit)) ((eq c ?\C-a) (lyskom-keyboard-menu-beginning-of-line)) ((eq c ?\C-e) (lyskom-keyboard-menu-end-of-line)) ((or (eq c 'up) (eq c ?\C-p)) (lyskom-keyboard-menu-up)) ((or (eq c ?\C-b) (eq c 'left)) (lyskom-keyboard-menu-backward)) ((or (eq c 'down) (eq c ?\C-n)) (lyskom-keyboard-menu-down)) ((or (eq c ?\C-f) (eq c 'right)) (lyskom-keyboard-menu-forward)) ((or (eq c 'return) (eq c ?\r) (eq c ?\n)) (setq result lyskom-keyboard-menu-selection)) ((and (lyskom-characterp c) (assoc (make-string 1 c) lyskom-keyboard-menu-menu)) (if kom-keyboard-menu-immediate-selection (setq result (assoc (make-string 1 c) lyskom-keyboard-menu-menu)) (setq lyskom-keyboard-menu-selection (assoc (make-string 1 c) lyskom-keyboard-menu-menu)))))) (when lyskom-keyboard-menu-selection (setq lyskom-keyboard-menu-menu (lyskom-rotate-list lyskom-keyboard-menu-menu lyskom-keyboard-menu-selection)))) (quit (setq result nil))) (elt result 2) ))))) (defun lyskom-keyboard-menu-up () "Move up one menu item" (interactive) (let ((done nil)) (while (not done) ;; Move up one line (condition-case nil (previous-line 1) (beginning-of-buffer (setq done t))) ;; Scan the items on this line until we find the one ;; just before point or just after point or around ;; point. (let ((selection nil) (start (save-excursion (beginning-of-line) (point))) (end (save-excursion (end-of-line) (point))) (pos (point))) (while (and (>= pos start) (null selection)) (setq selection (get-text-property pos 'lyskom-keyboard-menu-item) pos (1- pos))) (setq pos (point)) (while (and (<= pos end) (null selection)) (setq selection (get-text-property pos 'lyskom-keyboard-menu-item) pos (1+ pos))) (when selection (setq done t lyskom-keyboard-menu-selection selection)))))) (defun lyskom-keyboard-menu-down () "Move down one menu item." (interactive) (let ((done nil)) (while (not done) ;; Move up one line (condition-case nil (next-line 1) (end-of-buffer (setq done t))) ;; Scan the items on this line until we find the one ;; just before point or just after point or around ;; point. (let ((selection nil) (start (save-excursion (beginning-of-line) (point))) (end (save-excursion (end-of-line) (point))) (pos (point))) (while (and (>= pos start) (null selection)) (setq selection (get-text-property pos 'lyskom-keyboard-menu-item) pos (1- pos))) (setq pos (point)) (while (and (<= pos end) (null selection)) (setq selection (get-text-property pos 'lyskom-keyboard-menu-item) pos (1+ pos))) (when selection (setq done t lyskom-keyboard-menu-selection selection)))))) (defun lyskom-keyboard-menu-forward () "Move right one menu item." (interactive) (let ((pos (point)) (item nil)) (while (and pos (or (null item) (eq item lyskom-keyboard-menu-selection))) (setq pos (next-single-property-change pos 'lyskom-keyboard-menu-item)) (when pos (setq item (get-text-property pos 'lyskom-keyboard-menu-item)))) (when item (setq lyskom-keyboard-menu-selection item)))) (defun lyskom-keyboard-menu-backward () "Move left one menu item." (interactive) (let ((pos (point)) (item nil)) (while (and pos (or (null item) (eq item lyskom-keyboard-menu-selection))) (setq pos (previous-single-property-change pos 'lyskom-keyboard-menu-item)) (when pos (setq item (get-text-property pos 'lyskom-keyboard-menu-item)))) (when item (setq lyskom-keyboard-menu-selection item)))) (defun lyskom-keyboard-menu-beginning-of-line () "Move to the first menu item of this line." (interactive) (beginning-of-line) (setq lyskom-keyboard-menu-selection (or (get-text-property (point) 'lyskom-keyboard-menu-item) (get-text-property (or (next-single-property-change (point) 'lyskom-keyboard-menu-item nil (save-excursion (end-of-line) (point))) (point)) 'lyskom-keyboard-menu-item)))) (defun lyskom-keyboard-menu-end-of-line () "Move to the last menu item of this line." (interactive) (end-of-line) (setq lyskom-keyboard-menu-selection (if (get-text-property (point) 'lyskom-keyboard-menu-item) (get-text-property (point) 'lyskom-keyboard-menu-item) (let ((pos (previous-single-property-change (point) 'lyskom-keyboard-menu-item nil (1- (save-excursion (beginning-of-line) (point)))))) (when (and pos (not (zerop pos))) (or (get-text-property pos 'lyskom-keyboard-menu-item) (get-text-property (1- pos) 'lyskom-keyboard-menu-item))))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: command.el,v 44.55 2005/01/11 07:35:52 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: command.el ;;;; ;;;; This file contains stuff regarding commands. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: command.el,v 44.55 2005/01/11 07:35:52 _cvs_pont_lyskomelisp Exp $\n")) ;;; ====================================================================== ;;; LysKOM user commands ;;; The new, blocking commands have a very similar structure ;;; ;;; (defun kom-cmd (args) ;;; "Documentation" ;;; (interactive "...") ;;; (lyskom-start-of-command 'kom-cmd) ;;; (unwind-protect ;;; (progn ...) ;;; (lyskom-end-of-command))) ;;; ;;; This can now be written as ;;; ;;; (def-kom-command kom-cmd (args) ;;; "Documentation" ;;; (interactive "...") ;;; ...) (eval-and-compile (defun lyskom-fix-interactive-decl (decl command) (cond ((stringp (car (cdr decl))) decl) (t `(interactive (let ((lyskom-current-command ',command)) ,@(cdr decl))))))) (defmacro def-kom-command (cmd args doc &rest forms) "Define a LysKOM command CMD with args ARGS and docstring DOC. This is like a defun for LysKOM commands. After the docstring you may have a series of keywords that alter the behavior of the command, followed by an interactive declaration (required) and the body of the command. The following keywords are recognized: :dead-ok See the DEAD-OK paramter to lyskom-start-of-command :may-interrupt See the MAY-INTERRUPT parameter to lyskom-start-of-command :prompt-format See the PROMPT-FORMAT parameter to lyskom-start-of-command Note that :prompt-format requires an argument." (let (interactive-decl may-interrupt dead-ok prompt-format) (while (memq (car forms) '(:prompt-format :dead-ok :may-interrupt)) (cond ((eq (car forms) :prompt-format) (setq prompt-format (car (cdr forms))) (setq forms (cdr forms))) ((eq (car forms) :dead-ok) (setq dead-ok t)) ((eq (car forms) :may-interrupt) (setq may-interrupt t))) (setq forms (cdr forms))) (when (and (listp (car forms)) (eq 'interactive (car (car forms)))) (setq interactive-decl (car forms) forms (cdr forms))) (if (not (stringp doc)) (progn (message "!! No docstring for command %S" cmd) (setq forms (cons interactive-decl forms)) (setq interactive-decl doc) (setq doc ""))) (if (not (eq (car interactive-decl) 'interactive)) (progn (message "!! Missing interactive declaration for %S; assuming \(interactive\)" cmd) (setq forms (cons interactive-decl forms)) (setq interactive-decl '(interactive)))) (let ((bufsym (make-symbol (format "%S-start-buffer" cmd))) (winsym (make-symbol (format "%S-start-window" cmd)))) `(defun ,cmd ,args ,doc ,(lyskom-fix-interactive-decl interactive-decl cmd) (let ((lyskom-command-point (point))) (lyskom-start-of-command ',cmd ,may-interrupt ,dead-ok ,prompt-format) (let ((,bufsym (current-buffer)) (,winsym (selected-window))) (unwind-protect (condition-case nil (progn ,@forms) (quit (ding) (lyskom-insert-before-prompt (lyskom-get-string 'interrupted)))) (lyskom-save-excursion (cond ((and (buffer-live-p ,bufsym) (window-live-p ,winsym) (eq (window-buffer ,winsym) ,bufsym)) (save-selected-window (set-buffer ,bufsym) (select-window ,winsym) (lyskom-end-of-command))) ((buffer-live-p ,bufsym) (set-buffer ,bufsym) (lyskom-end-of-command)) (t (lyskom-end-of-command))))))))))) ;; ;; def-kom-emacs-command works like def-kom-command, but the template ;; is different. Commands defined this way will run as regular Emacs ;; commands when invoked outside of a LysKOM buffer. ;; ;; The variable -running-as-kom-command is non-nil when running ;; as a LysKOM command and nil otherwise. ;; ;; Note: this function catches *all* errors in lyskom-start-of-command ;; which may not be what you want, so be careful. ;; ;; ;; (defun kom-cmd (args) ;; "Documentation" ;; (interactive "...") ;; (let ((kom-cmd-running-as-kom-command nil)) ;; (condition-case nil ;; (progn (lyskom-start-of-command 'kom-cmd) ;; (setq kom-cmd-running-as-kom-command t)) ;; (error nil)) ;; (unwind-protect ;; (condition-case nil ;; (progn ...) ;; (quit (ding) ;; (lyskom-insert-before-prompt ;; (lyskom-get-string 'interrupted)))) ;; (and kom-cmd-running-as-kom-command (lyskom-end-of-command))))) ;; (defmacro def-kom-emacs-command (cmd args doc &rest forms) (let (interactive-decl may-interrupt dead-ok prompt-format) (while (memq (car forms) '(:prompt-format :dead-ok :may-interrupt)) (cond ((eq (car forms) :prompt-format) (setq prompt-format (car (cdr forms))) (setq forms (cdr forms))) ((eq (car forms) :dead-ok) (setq dead-ok t)) ((eq (car forms) :may-interrupt) (setq may-interrupt t))) (setq forms (cdr forms))) (when (and (listp (car forms)) (eq 'interactive (car (car forms)))) (setq interactive-decl (car forms) forms (cdr forms))) (if (not (stringp doc)) (progn (message "!! No docstring for command %S" cmd) (setq forms (cons interactive-decl forms)) (setq interactive-decl doc) (setq doc ""))) (if (not (eq (car interactive-decl) 'interactive)) (progn (message "!! Missing interactive declaration for %S; assuming \(interactive\)" cmd) (setq forms (cons interactive-decl forms)) (setq interactive-decl '(interactive)))) (let ((rsym (intern (format "%S-running-as-kom-command" cmd))) (bufsym (make-symbol (format "%S-start-buffer" cmd))) (winsym (make-symbol (format "%S-start-window" cmd)))) `(defun ,cmd ,args ,doc ,(lyskom-fix-interactive-decl interactive-decl cmd) (let ((,rsym nil)) (condition-case nil (progn (lyskom-start-of-command ',cmd ,may-interrupt ,dead-ok ,prompt-format) (setq ,rsym t)) (error nil)) (let ((,bufsym (current-buffer)) (,winsym (selected-window))) (unwind-protect (condition-case nil (progn ,@forms) (quit (ding) (lyskom-insert-before-prompt (lyskom-get-string 'interrupted)))) (and ,rsym (lyskom-save-excursion (cond ((and (buffer-live-p ,bufsym) (window-live-p ,winsym) (eq (window-buffer ,winsym) ,bufsym)) (save-selected-window (set-buffer ,bufsym) (select-window ,winsym) (lyskom-end-of-command))) ((buffer-live-p ,bufsym) (set-buffer ,bufsym) (lyskom-end-of-command)) (t (lyskom-end-of-command)))))))))))) (put 'def-kom-command 'edebug-form-spec '(&define name lambda-list [&optional stringp] ; Match the doc string, if present. ("interactive" interactive) def-body)) (put 'def-kom-emacs-command 'edebug-form-spec '(&define name lambda-list [&optional stringp] ; Match the doc string, if present. ("interactive" interactive) def-body)) ;;;; ================================================================ ;;;; User-level commands and functions. (defsubst lyskom-command-name (command &optional language) "Get the command name for the command COMMAND" (condition-case nil (lyskom-get-string command 'lyskom-command language) (error nil))) (defun lyskom-ok-command (alternative administrator) "Returns non-nil if it is ok to do such a command right now." (when (vectorp alternative) (setq alternative (cons (elt alternative 0) (elt alternative 1)))) (if administrator (not (memq (cdr alternative) lyskom-admin-removed-commands)) (not (memq (cdr alternative) lyskom-noadmin-removed-commands)))) (defun kom-extended-command () "Read a LysKOM function name and call the function." (interactive) (let ((fnc (lyskom-read-extended-command current-prefix-arg))) (cond (fnc (call-interactively fnc)) (t (kom-next-command)))) ) (defvar lyskom-command-minibuffer-local-completion-map (let ((map (copy-keymap minibuffer-local-completion-map))) (define-key map " " 'lyskom-command-complete-word) map) "Keymap used for reading LysKOM names.") (defvar lyskom-command-minibuffer-local-must-match-map (let ((map (copy-keymap minibuffer-local-must-match-map))) (lyskom-xemacs-or-gnu (progn (lyskom-set-keymap-parent map lyskom-minibuffer-local-completion-map) (define-key map " " 'lyskom-command-complete-word)) (define-key map " " 'lyskom-command-complete-word)) map) "Keymap used for reading LysKOM names.") (defun lyskom-read-extended-command (&optional prefix-arg prompt) "Reads and returns a command" (let* ((completion-ignore-case t) (minibuffer-setup-hook minibuffer-setup-hook) (base-prompt (cond ((null prompt) (lyskom-get-string 'extended-command)) ((symbolp prompt) (lyskom-get-string prompt)) (t prompt))) (alternatives (mapcar (lambda (pair) (cons (cdr pair) (car pair))) (lyskom-get-strings lyskom-commands 'lyskom-command))) (name nil) (prefix-text (cond ((eq prefix-arg '-) "- ") ((equal prefix-arg '(4)) "C-u ") ((integerp prefix-arg) (format "%d " prefix-arg)) ((and (consp prefix-arg) (integerp (car prefix-arg))) (format "%d " (car prefix-arg))) (t nil))) (prompt (if prefix-text (concat prefix-text base-prompt) base-prompt))) (let ((minibuffer-local-completion-map lyskom-command-minibuffer-local-completion-map) (minibuffer-local-must-match-map lyskom-command-minibuffer-local-must-match-map)) (while (or (null name) (string= "" name)) (setq name (lyskom-completing-read prompt 'lyskom-complete-command ;; lyskom-is-administrator is buffer-local and ;; must be evalled before the call to ;; completing-read ;; Yes, this is not beautiful (list 'lambda '(alternative) ; (list 'lyskom-ok-command 'alternative lyskom-is-administrator)) t nil 'lyskom-command-history)))) (cdr (lyskom-string-assoc name alternatives)))) (defun lyskom-update-command-completion () "Build a list of alternatives for completion of LysKOM commands. Each list element is a vector [NAME COMMAND CANONICAL]. NAME is the command name, COMMAND is the command and CANONICAL is the name transformed for matching." (setq lyskom-command-alternatives (mapcar (lambda (el) (vector (cdr el) (car el) (lyskom-completing-strip-command (lyskom-unicase (cdr el))) (lyskom-unicase (cdr el)))) (lyskom-get-strings lyskom-commands 'lyskom-command)))) (defun lyskom-lookup-command-by-name (string &optional predicate) "Look up the command that corresponds to a certain string." (lyskom-complete-command string predicate 'lyskom-lookup)) (defsubst lyskom-command-match-string-regexp (string) (concat "^\\s-*" (replace-in-string (regexp-quote (lyskom-unicase (lyskom-completing-strip-command string))) "\\s-+" "\\\\S-*\\\\s-+") "\\s-*")) (defun lyskom-completing-strip-command (string) "Strip parens and crap from a name. If optional DONT-STRIP-SPACES is non-nil, don't strip spaces at front and back of the string." (while (string-match "([^()]*)" string) ; Strip nested parens (setq string (replace-match "" t t string))) (while (string-match "\\s-\\s-+" string) ; Collapse spaces (setq string (replace-match " " t t string))) (while (string-match "([^()]*$" string) ; Strip incomplete parens at end (setq string (substring string 0 (match-beginning 0)))) string) ;;; FIXME: Below is an idea on how to do command completion more right. ;;; ;;; Precompute lists of words in all commands. Include the optional words ;;; and mark them as optional. Possibly allow sublists in the list, and ;;; make lists of words into sublists and mark the entire sublist as ;;; optional. ;;; ;;; When matching, divide the input into a list of words. Start matchin ;;; prefixes against the list of words for a command. It goes something ;;; like this: ;;; ;;; C = 0, I = 0 ;;; while there are more words in the input and command ;;; A = word I of the input ;;; B = word C of the command ;;; if B is an optional word then ;;; N = index of word following optional group that B is part of ;;; push N,I onto backtracking stack ;;; if A is a prefix of B then ;;; I = I + 1 ;;; C = C + 1 ;;; next iteration of the loop ;;; if the backtracking stack is empty then ;;; return mismatch ;;; pop X,Y from the backtracking stack ;;; C = X ;;; I = Y ;;; next iteration of the loop ;;; end while ;;; if there are left-over words in C then ;;; return a mismatch ;;; else ;;; return a match (I,C) ;;; ;;; When doing a word completion we can let the completion function do the ;;; actual work. It computes the longest possible completion we can have ;;; (i.e. one full word more than what we've got) and hands that over to ;;; lyskom-complete-string. Computing the longest possible completion ;;; goes something like this: ;;; ;;; W = nil ;;; Store I,C for all matches ;;; for all matches M = 1 .. N do ;;; do something useful ;;; ;;; The idea is to get the last word that matches the input by storing ;;; the results of the match computation and then looking at the ;;; following word in all possible completions. If the following word ;;; is a word in an optional group that is the same in all possible ;;; completions, then that plus the first C words of any of the ;;; possible completions is the maximum possible. If the next word is ;;; a word of an optional group that does *not* match in all ;;; possibles, then ignore the optional group and look at the next ;;; word instead. (defun lyskom-complete-command (string predicate all) "Completion function for LysKOM commands." (when (string-match "^\\s-+" string) (setq string (substring string (match-end 0)))) (let ((alternatives nil) (m-string (lyskom-command-match-string-regexp string)) (u-string (lyskom-unicase string)) (exact nil)) (lyskom-traverse el lyskom-command-alternatives (when (and (string-match m-string (elt el 2)) (or (null predicate) (funcall predicate el))) (setq alternatives (cons (if (eq all 'lyskom-lookup) el (elt el 0)) alternatives)) (if (string-equal u-string (elt el 3)) (setq exact el)))) (cond ((eq all 'lyskom-lookup) (and exact (elt exact 1))) ((eq all 'lambda) exact) (all alternatives) ((null alternatives) nil) ((and (= (length alternatives) 1) exact) t) (t (let ((tmp (lyskom-complete-string alternatives))) (lyskom-maybe-recode-string (if (string-match (concat (regexp-quote (lyskom-unicase tmp)) "\\s-") u-string) (concat tmp " ") tmp))))))) (defun lyskom-command-complete-word () (interactive) (let ((string (buffer-string))) (when (next-single-property-change 0 'read-only string) (setq string (substring string (next-single-property-change 0 'read-only string)))) (let ((completion (try-completion string minibuffer-completion-table minibuffer-completion-predicate))) (cond ((null completion) (lyskom-minibuffer-message " [No match]") nil) ((eq completion t) nil) (t (let* ((tmp string)) (when (and (string-equal (lyskom-unicase completion) (lyskom-unicase tmp)) (not (string-match "\\s-$" completion))) (if (stringp (setq tmp (try-completion (concat tmp " ") minibuffer-completion-table minibuffer-completion-predicate))) (setq completion tmp))) (if (string-equal (lyskom-unicase completion) (lyskom-unicase string)) (progn (minibuffer-completion-help) nil) (delete-region (- (point-max) (length string)) (point-max)) ;; Now we have the suggested completion ;; Expand what's in the buffer by one real word. (let* ((count (lyskom-command-complete-count-words string)) (result (lyskom-command-complete-word-truncate completion count))) (when (string= result string) (setq result (lyskom-command-complete-word-truncate completion (1+ count)))) (insert result)) t))))))) (defvar lyskom-command-complete-regexp "\\(([^\)]*)\\s-+\\)*\\S-+\\(\\s-*([^\)]*)\\)*\\(\\s-+\\|\\'\\)") (defun lyskom-command-complete-word-truncate (completion count) "Truncate completion COMPLETION to COUNT words." (let ((start 0)) (while (and (> count 0) (string-match lyskom-command-complete-regexp completion start)) (setq start (match-end 0) count (1- count))) (substring completion 0 start))) (defun lyskom-command-complete-count-words (string) "Count number of real words in command name or completion STRING." (let ((start 0) (count 0)) (while (string-match lyskom-command-complete-regexp string start) (setq start (match-end 0) count (1+ count))) count)) ;;; The code below is an alternative implementation of ;;; lyskom-command-complete-word that mucks with the ;;; contents of the minibuffer and then calls the regular ;;; minibuffer functions. ;;; ;;; ;;;(defun lyskom-command-complete-word-count-words (string) ;;; (let ((count 0) ;;; (start 0)) ;;; (while (string-match lyskom-command-complete-regexp string start) ;;; (setq start (match-end 0) ;;; count (1+ count))) ;;; count)) ;;; ;;;(defun lyskom-command-complete-word () ;;; (interactive) ;;; (let* ((string (buffer-string)) ;;; completions) ;;; ;; Strip the prompt in Emacs 21 ;;; (when (next-single-property-change 0 'read-only string) ;;; (setq string ;;; (substring string ;;; (next-single-property-change 0 'read-only string)))) ;;; ;;; (setq completions (save-excursion ;;; (set-buffer lyskom-buffer) ;;; (lyskom-complete-command string ;;; nil ;;; nil))) ;;; (when (stringp completions) ;;; (let ((original-count (lyskom-command-complete-word-count-words string)) ;;; (start 0)) ;;; (while (and (> original-count 0) ;;; (string-match lyskom-command-complete-regexp completions start)) ;;; (setq start (match-end 0) ;;; original-count (1- original-count))) ;;; ;;; (delete-region (- (point-max) (length string)) (point-max)) ;;; (let ((result (substring completions 0 start))) ;;; (string-match "\\s-*\\'" result) ;;; (insert (substring result 0 (match-beginning 0))))))) ;;; (minibuffer-complete-word)) (defun lyskom-start-of-command (function &optional may-interrupt dead-ok prompt-format) "This function is run at the beginning of every LysKOM command. It moves the cursor one line down, and +++ later it will tell the server that the previous text has been read. Argument FUNCTION is a string the string will be written in the buffer on start of the command. If it is a symbol it searches for the corresponding command name in lyskom-commands and writes this in the message buffer. If optional argument MAY-INTERRUPT is present and non-nil, don't signal an error if this call is interrupting another command. If optional DEAD-OK is non-nil, don't signal an error if the session has been closed. If optional PROMPT-FORMAT is non-nil, this will be used to format the prompt. It should be a format string suitable for lyskom-format. Argument one is the command name (a symbol or string). Special: if lyskom-is-waiting then we are allowed to break if we set lyskom-is-waiting nil. This function checks if lyskom-doing-default-command and lyskom-first-time-around are bound. The text entered in the buffer is chosen according to this" (cond ((or (not (boundp 'lyskom-proc)) (not (boundp 'lyskom-buffer)) (and (null lyskom-proc) (null lyskom-buffer))) (lyskom-error "%s" (lyskom-get-string 'not-lyskom-buffer))) ((and (not (or dead-ok (memq function kom-relogin-inhibit-commands))) (or (not lyskom-proc) (memq (process-status lyskom-proc) '(closed signal exited nil)))) (if (or (eq t kom-relogin-behaviour) (and (eq 'ask kom-relogin-behaviour) (lyskom-j-or-n-p (lyskom-get-string 'resurrect-session)))) (lyskom lyskom-server-name lyskom-pers-no) (lyskom-error "%s" (lyskom-get-string 'dead-session))))) (if (and lyskom-is-waiting (listp lyskom-is-waiting)) (progn (setq lyskom-is-waiting nil) (lyskom-end-of-command))) (setq lyskom-is-waiting nil) (if (and lyskom-executing-command (not may-interrupt)) (lyskom-error "%s" (lyskom-get-string 'wait-for-prompt))) (if (not (and (boundp 'lyskom-doing-default-command) lyskom-doing-default-command)) (cond (lyskom-first-time-around) ((stringp function) (lyskom-insert function)) ((lyskom-command-name function) (if prompt-format (lyskom-format-insert prompt-format function) (lyskom-insert (lyskom-command-name function))))) (save-excursion (if lyskom-current-prompt (let ((inhibit-read-only t)) (goto-char (point-max)) (beginning-of-line) (delete-region (point) (point-max))))) (lyskom-insert (lyskom-modify-prompt (cond ((stringp lyskom-current-prompt) (apply 'lyskom-format lyskom-current-prompt lyskom-current-prompt-args)) ((symbolp lyskom-current-prompt) (apply 'lyskom-format (lyskom-get-string lyskom-current-prompt) lyskom-current-prompt-args)) (t (format "%S" lyskom-current-prompt))) t))) (setq mode-line-process (lyskom-get-string 'mode-line-working)) (if (pos-visible-in-window-p (point-max)) (save-excursion (goto-char (point-max)) (lyskom-set-last-viewed))) (setq lyskom-executing-command t) (setq lyskom-current-command function) (setq lyskom-current-prompt nil) (lyskom-insert "\n") (if (and (eq (window-buffer (selected-window)) (current-buffer))) (progn (if (pos-visible-in-window-p (1- (point-max))) (goto-char (point-max))) (sit-for 0))) (run-hooks 'lyskom-before-command-hook) (if kom-page-before-command ;Nice with dumb terminals. (if (or (not (listp kom-page-before-command)) (memq function kom-page-before-command)) (recenter 1)))) (defun lyskom-end-of-command () "Print prompt, maybe scroll, prefetch info." (lyskom-save-excursion (message "") (lyskom-clean-all-buffer-lists) (while (and lyskom-to-be-printed-before-prompt (lyskom-queue->first lyskom-to-be-printed-before-prompt)) (if (not (bolp)) (lyskom-insert "\n")) (lyskom-insert (car (lyskom-queue->first lyskom-to-be-printed-before-prompt))) (lyskom-queue-delete-first lyskom-to-be-printed-before-prompt)) (setq lyskom-executing-command nil) (setq lyskom-current-command nil) (setq lyskom-current-prompt nil) ; Already set in s-o-c really (lyskom-scroll) (setq mode-line-process (lyskom-get-string 'mode-line-waiting)) (if (pos-visible-in-window-p (point-max) (selected-window)) (lyskom-set-last-viewed)) (lyskom-prefetch-and-print-prompt) (run-hooks 'lyskom-after-command-hook) (when (and (lyskom-have-feature idle-time) (not lyskom-is-anonymous)) (save-excursion (set-buffer lyskom-buffer) (initiate-user-active 'background nil))) (if kom-inhibit-typeahead (discard-input)) ;; lyskom-pending-commands should probably be a queue or a stack. (when lyskom-pending-commands (let ((command (car lyskom-pending-commands))) (setq lyskom-pending-commands (cdr lyskom-pending-commands)) (if (symbolp command) (call-interactively command) (eval command)))) (when lyskom-slow-mode (buffer-enable-undo)))) (eval-and-compile (provide 'lyskom-command)) ;;; command.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: buffers.el,v 44.28 2004/11/15 17:27:17 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: buffers.el ;;;; Author: David Byers ;;;; ;;;; This file implements special buffer handling used in LysKOM ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: buffers.el,v 44.28 2004/11/15 17:27:17 _cvs_pont_lyskomelisp Exp $\n")) ;;;; ;;;; LYSKOM BUFFER MANAGEMENT ;;;; ;;;; Buffers are arranged in a tree rooted in a LysKOM buffer. There ;;;; is one tree for each session. ;;;; ;;;; Use lyskom-get-buffer-create to create new buffers ;;;; Use lyskom-display-buffer to display most buffers ;;;; Use lyskom-undisplay-buffer to undisplay those buffers ;;;; ;;;; ============================================================ ;;;; Buffer hierarchy management ;;;; ;;;; This code should not be too dependent on LysKOM ;;;; (defvar lyskom-buffer-children nil "List of buffers that are children to this buffer") (defvar lyskom-buffer-inherited-variables nil "List of variables automatically inherited to sub-buffers when they are created.") (defvar lyskom-buffer-parent nil "Parent of buffer") (defvar lyskom-killing-hierarchy nil "Non-nil while killing a buffer hierarchy.") (make-variable-buffer-local 'lyskom-buffer-parent) (lyskom-protect-variable 'lyskom-buffer-parent) (make-variable-buffer-local 'lyskom-buffer-children) (lyskom-protect-variable 'lyskom-buffer-children) (make-variable-buffer-local 'lyskom-buffer-inherited-variables) (lyskom-protect-variable 'lyskom-buffer-inherited-variables) (defun lyskom-set-buffer-parent (buffer parent) "Set the parent buffer of BUFFER to PARENT. If buffer is already a child of some buffer, reparent it." (save-excursion (set-buffer buffer) (if (and lyskom-buffer-parent (buffer-live-p lyskom-buffer-parent)) (lyskom-remove-buffer-child lyskom-buffer-parent buffer)) (setq lyskom-buffer-parent parent) (if parent (lyskom-add-buffer-child parent buffer)))) (defun lyskom-remove-buffer-child (buffer child) "Remove CHILD from BUFFER's list of children. Args: BUFFER CHILD" (save-excursion (set-buffer buffer) (if (boundp 'lyskom-buffer-children) (setq lyskom-buffer-children (delq child lyskom-buffer-children))))) (defun lyskom-add-buffer-child (buffer child) "Add CHILD as a child of BUFFER. Args: BUFFER CHILD" (save-excursion (set-buffer buffer) (setq lyskom-buffer-children (cons child lyskom-buffer-children)))) (defun lyskom-get-buffer-parent (buffer) "Return the parent of BUFFER or nil if it has no parent" (save-excursion (set-buffer buffer) (and (boundp 'lyskom-buffer-parent) lyskom-buffer-parent))) (defun lyskom-get-buffer-children (buffer) "Return the list of children of buffer BUFFER or nil if there are none." (save-excursion (set-buffer buffer) (and (boundp 'lyskom-buffer-children) lyskom-buffer-children))) (defun lyskom-buffer-root-ancestor (buffer) "Return the ultimate ancestor of buffer BUFFER." (let ((buffer-parent buffer)) (while (setq buffer-parent (lyskom-get-buffer-parent buffer)) (setq buffer buffer-parent)) buffer)) (defun lyskom-traverse-buffer-hierarchy (function buffer) "Apply FUNCTION to each descendent of BUFFER. Results are discarded." (let ((queue (list buffer)) (done nil) (current nil)) (while queue (setq current (car queue)) (setq queue (cdr queue)) (unless (or (memq current done) (not (buffer-live-p current))) (setq done (cons current done)) (setq queue (append queue (lyskom-get-buffer-children current))) (funcall function current))))) (defun lyskom-map-buffer-children (function buffer) "Apply FUNCTION to each child of BUFFER and make a list of the results." (cond ((null buffer) nil) (t (cons (funcall function buffer) (apply 'nconc (mapcar (function (lambda (x) (lyskom-map-buffer-children function x))) (lyskom-get-buffer-children buffer))))))) (defun lyskom-buffer-hierarchy-query-kill-function () "When querying if a buffer is to be killed, ensure that none of the children object" (save-excursion (not (memq nil (mapcar (function (lambda (buffer) (if (buffer-live-p buffer) (progn (set-buffer buffer) (run-hook-with-args-until-failure 'kill-buffer-query-functions)) t))) (lyskom-get-buffer-children (current-buffer))))))) (defun lyskom-buffer-hierarchy-kill-hook () "When killing a buffer, enure that its children also die" (let ((kill-buffer-query-functions nil) (lyskom-killing-hierarchy (or lyskom-killing-hierarchy (current-buffer)))) (lyskom-set-buffer-parent (current-buffer) nil) (let ((buflist (lyskom-get-buffer-children (current-buffer)))) (while buflist (kill-buffer (car buflist)) (setq buflist (cdr buflist)))))) (defun lyskom-buffer-kill-trim-hook () "When killing a buffer, run trimming hooks." (when (eq major-mode 'lyskom-mode) (let ((lyskom-trim-buffer-delete-to (point-max))) (lyskom-ignore lyskom-trim-buffer-delete-to) (run-hooks 'lyskom-trim-buffer-hook)))) (add-hook 'kill-buffer-hook 'lyskom-buffer-hierarchy-kill-hook) (add-hook 'kill-buffer-hook 'lyskom-buffer-kill-trim-hook) (add-hook 'kill-buffer-query-functions 'lyskom-buffer-hierarchy-query-kill-function) ;;;; ====================================================================== (defun lyskom-update-unread-mode-line () (setq lyskom-unread-mode-line (lyskom-make-lyskom-unread-mode-line))) ;;;; ====================================================================== ;;;; ====================================================================== (defun lyskom-clean-all-buffer-lists () "Remove dead buffers from all relevant buffer lists" (setq lyskom-sessions-with-unread (lyskom-clean-buffer-list lyskom-sessions-with-unread) lyskom-sessions-with-unread-letters (lyskom-clean-buffer-list lyskom-sessions-with-unread-letters) lyskom-buffer-list (lyskom-clean-buffer-list lyskom-buffer-list)) (lyskom-update-unread-mode-line) (lyskom-set-default 'lyskom-need-prompt-update t)) (defun lyskom-clean-buffer-list (buffers) "Remove all dead buffers from BUFFERS" (let ((result nil)) (while buffers (if (lyskom-buffer-p (car buffers)) (setq result (cons (car buffers) result)) (save-excursion (set-buffer (car buffers)) (setq lyskom-session-has-unread-letters nil) (setq lyskom-session-has-unreads nil))) (setq buffers (cdr buffers))) (nreverse result))) (defun lyskom-remove-buffer-from-lists (&optional buffer) "Remove BUFFER from all internal lists. If BUFFER is not specified, assume the current buffer" (unless buffer (setq buffer (current-buffer))) (lyskom-remove-unread-buffer buffer) (setq lyskom-buffer-list (delq buffer lyskom-buffer-list)) (lyskom-update-unread-mode-line) (lyskom-set-default 'lyskom-need-prompt-update t)) (defun lyskom-remove-unread-buffer (buffer &optional letters-only) (unless letters-only (lyskom-traverse-buffer-hierarchy (lambda (x) (save-excursion (set-buffer x) (setq lyskom-session-has-unreads nil))) buffer) (setq lyskom-sessions-with-unread (delq buffer lyskom-sessions-with-unread))) (lyskom-traverse-buffer-hierarchy (lambda (x) (save-excursion (set-buffer x) (setq lyskom-session-has-unread-letters nil))) buffer) (setq lyskom-sessions-with-unread-letters (delq buffer lyskom-sessions-with-unread-letters)) (lyskom-update-unread-mode-line) (lyskom-set-default 'lyskom-need-prompt-update t)) (defun lyskom-add-unread-buffer (buffer &optional letters) (unless (memq buffer lyskom-sessions-with-unread) (lyskom-traverse-buffer-hierarchy (lambda (x) (save-excursion (set-buffer x) (setq lyskom-session-has-unreads t))) buffer) (setq lyskom-sessions-with-unread (cons buffer lyskom-sessions-with-unread))) (unless (or (null letters) (memq buffer lyskom-sessions-with-unread-letters)) (lyskom-traverse-buffer-hierarchy (lambda (x) (save-excursion (set-buffer x) (setq lyskom-session-has-unread-letters t))) buffer) (setq lyskom-sessions-with-unread-letters (cons buffer lyskom-sessions-with-unread-letters))) (lyskom-update-unread-mode-line) (lyskom-set-default 'lyskom-need-prompt-update t)) (defvar lyskom-associated-buffer-list nil "List of (CATEGORY . BUFFER-LIST) listing all buffers of various categories") (make-variable-buffer-local 'lyskom-associated-buffer-list) (lyskom-protect-variable 'lyskom-associated-buffer-list) (defvar lyskom-buffer-category nil "Category of this buffer") (make-variable-buffer-local 'lyskom-buffer-category) (lyskom-protect-variable 'lyskom-buffer-category) (def-kom-var lyskom-saved-window-configuration nil "The window configuration to return to when closing the window" protected local) (def-kom-var lyskom-dedicated-frame nil "The frame dedicated to the current buffer" protected local) (def-kom-var lyskom-dedicated-window nil "The window dedicated to the current buffer" protected local) (defvar lyskom-undisplaying-hierarchy nil "The top of the buffer hierarchy being undisplayed.") (defun lyskom-clean-up-buffer-category (cat) (let ((buffers (cdr (assq cat (lyskom-default-value 'lyskom-associated-buffer-list)))) (result nil)) (while buffers (when (buffer-live-p (car buffers)) (setq result (cons (car buffers) result))) (setq buffers (cdr buffers))) (lyskom-set-buffers-of-category cat (nreverse result)))) (defun lyskom-set-buffers-of-category (category buflist) (let ((tmp (assq category (lyskom-default-value 'lyskom-associated-buffer-list)))) (cond (tmp (setcdr tmp buflist)) (t (lyskom-setq-default lyskom-associated-buffer-list (cons (cons category buflist) (lyskom-default-value 'lyskom-associated-buffer-list))))))) (defun lyskom-buffers-of-category (cat) "Return all live buffers of catgory CAT" (lyskom-clean-up-buffer-category cat) (cdr (assq cat (lyskom-default-value 'lyskom-associated-buffer-list)))) (defun lyskom-add-buffer-of-category (buffer category) "Add BUFFER as a buffer of category CATEGORY" (let ((tmp (assq category (lyskom-default-value 'lyskom-associated-buffer-list)))) (cond (tmp (setcdr tmp (cons buffer (cdr tmp)))) (t (lyskom-setq-default 'lyskom-associated-buffer-list (cons (cons category (list buffer)) (lyskom-default-value 'lyskom-associated-buffer-list))))))) (defun lyskom-quit-query () (if (and (boundp 'lyskom-buffer) (local-variable-p 'lyskom-buffer (current-buffer)) (eq lyskom-buffer (current-buffer)) (lyskom-buffers-of-category 'write-texts)) (unwind-protect (progn (display-buffer (car (lyskom-buffers-of-category 'write-texts))) (lyskom-ja-or-nej-p (lyskom-get-string 'quit-in-spite-of-unsent))) nil) t)) (add-hook 'kill-buffer-query-functions 'lyskom-quit-query) (add-hook 'kill-emacs-query-functions 'lyskom-quit-query) (defun lyskom-recode-buffer-name (name) (cond ((and (lyskom-multibyte-string-p name) (not enable-multibyte-characters)) (lyskom-encode-coding-string name (or (and lyskom-language (lyskom-language-coding lyskom-language)) 'raw-text))) ((and (not (lyskom-multibyte-string-p name)) enable-multibyte-characters) (lyskom-decode-coding-string name (or (and lyskom-language (lyskom-language-coding lyskom-language)) 'raw-text))) (t name))) (defun lyskom-generate-new-buffer (name) (setq name (lyskom-recode-buffer-name name)) (let ((buf (generate-new-buffer name))) (save-excursion (set-buffer buf)) buf)) (defun lyskom-get-buffer-create (category name &optional unique) "Create a new buffer of category CATEGORY with name generated from NAME. If UNIQUE is non-nil, re-use the first existing buffer of category CATEGORY, renaming it and killing its local variables. The created buffer is made a child of the current buffer." (setq name (lyskom-recode-buffer-name name)) (let ((buffers (lyskom-buffers-of-category category)) (buffer nil)) (if (and unique buffers) (progn (setq buffer (car buffers)) (save-excursion (set-buffer buffer) (let ((inhibit-read-only t)) ;;; +++ FIXME: This is that erase-buffer works if there are widgets (setq before-change-functions (delq 'widget-before-change before-change-functions)) (erase-buffer)) (kill-all-local-variables) (if (equal (buffer-name (current-buffer)) name) nil (rename-buffer name t)))) (progn (setq buffer (generate-new-buffer name)) (lyskom-add-buffer-of-category buffer category))) (lyskom-set-buffer-parent buffer (current-buffer)) (lyskom-update-inherited-variables buffer) (save-excursion (set-buffer buffer) (setq lyskom-buffer-category category)) buffer)) (defun lyskom-update-inherited-variables (buffer) "Update all inherited variables in this buffer and propagate them to all children" (save-excursion (let ((variables nil) (tmp lyskom-inherited-variables)) (set-buffer buffer) (when lyskom-buffer-parent (set-buffer lyskom-buffer-parent) (setq variables (mapcar 'symbol-value lyskom-inherited-variables)) (set-buffer buffer) (while tmp (make-local-variable (car tmp)) (set (car tmp) (car variables)) (setq tmp (cdr tmp) variables (cdr variables)))) (mapcar 'lyskom-update-inherited-variables lyskom-buffer-children)))) (defun lyskom-display-buffer (buffer &optional keep-frame-iconified) "Display the buffer BUFFER and select the window displaying it. If BUFFER is already visible in some window in any frame, iconified or otherwise, make that window visible. Otherwise display buffer as per which category it is in. Selects the window. If optional argument KEEP-FRAME-ICONIFIED is non-nil, then don't deiconify any frames. Returns the window displaying BUFFER." (set-buffer buffer) (let ((windows (lyskom-get-buffer-window-list buffer nil 0)) (iconified-frame nil) (visible-frame)) ;; ;; Find out if the buffer is visible somewhere ;; (while windows (cond ((not (frame-live-p (window-frame (car windows))))) ((eq (frame-visible-p (window-frame (car windows))) 'icon) (setq iconified-frame (car windows))) ((frame-visible-p (window-frame (car windows))) (setq visible-frame (car windows)) (setq windows nil))) (setq windows (cdr windows))) ;; ;; Display it ;; (cond (visible-frame (select-window visible-frame) visible-frame) (iconified-frame (unless keep-frame-iconified (make-frame-visible (window-frame iconified-frame))) (select-window iconified-frame) iconified-frame) (t (let ((category lyskom-buffer-category) (window nil)) (if (null category) (progn (select-window (display-buffer buffer)) (selected-window)) (let* ((sym (intern-soft (concat "kom-" (symbol-name category) "-in-window"))) (open (lyskom-default-value-safe sym)) (saved-window-configuration (save-excursion (set-buffer (or (and (boundp 'lyskom-buffer) lyskom-buffer) (current-buffer))) (current-window-configuration))) (dedicated-frame nil) (dedicated-window nil)) (cond ;; ;; NULL -- Just switch to the buffer ;; ((null open) (switch-to-buffer buffer) (setq window (selected-window))) ;; ;; OTHER, OTHER-WINDOW -- Switch to in another window ;; ((memq open '(other other-window)) (switch-to-buffer-other-window buffer) (setq dedicated-window (selected-window)) (setq window (selected-window))) ;; ;; OTHER-FRAME -- Switch to in another frame ;; Create frame if none exist ;; ((eq open 'other-frame) (if (eq (selected-frame) (next-frame)) (switch-to-buffer-other-frame buffer) (other-frame 1) (switch-to-buffer buffer)) (setq window (selected-window))) ;; ;; NEW-FRAME ;; Create a new frame and display buffer in that frame ;; ((eq open 'new-frame) (switch-to-buffer-other-frame buffer) (setq dedicated-frame (selected-frame)) (setq dedicated-window (selected-window)) (setq window (selected-window)) (setq saved-window-configuration nil)) ;; ;; String or buffer ;; Switch to buffer in window displaying named buffer ;; Prefer windows in selected frame ;; ((and (or (stringp open) (bufferp open)) (lyskom-get-buffer-window-list open nil 'visible)) (let ((tmp (lyskom-get-buffer-window-list open nil 'visible))) (setq window (car tmp)) (while tmp (if (eq (window-frame (car tmp)) (selected-frame)) (progn (setq window (car tmp)) (setq tmp nil)) (setq tmp (cdr tmp)))) (select-window window) (switch-to-buffer buffer))) ;; ;; Otherwise just switch ;; (t (switch-to-buffer buffer) (setq window (selected-window)))) ;; ;; Set up kill-buffer-hooks and similar things ;; (select-window window) (set-buffer buffer) (make-local-variable 'lyskom-dedicated-frame) (setq lyskom-dedicated-frame dedicated-frame) (make-local-variable 'lyskom-dedicated-window) (setq lyskom-dedicated-window dedicated-window) (make-local-variable 'lyskom-saved-window-configuration) (setq lyskom-saved-window-configuration saved-window-configuration) (lyskom-make-local-hook 'kill-buffer-hook) (add-hook 'kill-buffer-hook 'lyskom-undisplay-buffer-hook nil t) (put 'kill-buffer-hook 'permanent-local t) window))))))) (defun lyskom-undisplay-buffer-hook () (save-excursion (lyskom-undisplay-buffer (current-buffer)))) (defun lyskom-undisplay-buffer (&optional buffer) "Undisplay BUFFER. If buffer is not specified, undisplay the current buffer" (setq buffer (or buffer (current-buffer))) (let ((dedicated-frame (and (boundp 'lyskom-dedicated-frame) lyskom-dedicated-frame)) (dedicated-window (and (boundp 'lyskom-dedicated-window) lyskom-dedicated-window)) (lyskom-undisplaying-hierarchy (or buffer lyskom-undisplaying-hierarchy)) (saved-window-configuration (and (boundp 'lyskom-saved-window-configuration) lyskom-saved-window-configuration))) (cond ;; ;; If buffer has a dedicated frame AND ;; buffer is visible in that frame THEN ;; delete the frame ;; (dedicated-frame (when (memq dedicated-frame (mapcar 'window-frame (lyskom-get-buffer-window-list buffer nil t))) (delete-frame dedicated-frame) (setq dedicated-frame nil))) ((and lyskom-killing-hierarchy (not (eq lyskom-killing-hierarchy buffer))) nil) ((and lyskom-undisplaying-hierarchy (not (eq lyskom-undisplaying-hierarchy buffer))) nil) (dedicated-window (when (and (window-live-p dedicated-window) (eq (get-buffer buffer) (window-buffer dedicated-window))) (if (eq dedicated-window (next-window dedicated-window)) (bury-buffer buffer) (delete-window dedicated-window)) (setq dedicated-window nil)) (when saved-window-configuration (lyskom-set-partial-window-configuration saved-window-configuration))) (saved-window-configuration (lyskom-set-partial-window-configuration lyskom-saved-window-configuration))))) (defun lyskom-set-partial-window-configuration (configuration) "Set CONFIGURATION as the current window configuration with the exception of point mark and window-start in all windows." (let* ((info nil) (binfo nil)) (save-excursion (setq binfo (mapcar (function (lambda (b) (set-buffer b) (list b (point) (mark t)))) (buffer-list))) (walk-windows (function (lambda (w) (set-buffer (window-buffer w)) (setq info (cons (list w (window-start w) (window-point w) (window-buffer w)) info)))) t t)) (unwind-protect (set-window-configuration configuration) (save-selected-window (let (buffer window saved-point saved-mark saved-start) (while binfo (setq buffer (elt (car info) 0) saved-point (elt (car info) 1) saved-mark (elt (car info) 2)) (when (buffer-live-p buffer) (set-buffer buffer) (goto-char saved-point) (set-mark saved-mark)) (setq binfo (cdr binfo))) (while info (setq window (elt (car info) 0) saved-start (elt (car info) 1) saved-point (elt (car info) 2) buffer (elt (car info) 3)) (when (and (window-live-p window) (eq (window-buffer window) buffer)) (set-window-start window saved-start) (set-window-point window saved-point)) (setq info (cdr info)))))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: aux-items.el,v 44.42 2004/02/24 12:23:16 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: aux-items.el ;;;; ;;;; Implementation of aux-item specific stuff. ;;;; Hopefulle more of this will be made more general in the future. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: aux-items.el,v 44.42 2004/02/24 12:23:16 byers Exp $\n")) (def-kom-var lyskom-aux-item-definitions nil "List of aux item definitions.") (defmacro def-aux-item (name number &rest data) (` (setq lyskom-aux-item-definitions (add-to-list 'lyskom-aux-item-definitions (cons (, number) (cons (cons 'name (quote (, name))) (quote (, data)))))))) (defun lyskom-aux-item-definition->name (def) (cdr (assq 'name def))) (defun lyskom-aux-item-definition->number (def) (car def)) (defun lyskom-aux-item-try-call (item method default &rest args) (when (lyskom-aux-item-p item) (setq item (lyskom-find-aux-item-definition item))) (cond ((listp method) (let ((result nil) (found nil)) (while method (when (lyskom-aux-item-definition-field item (car method)) (setq result (apply (lyskom-aux-item-definition-field item (car method)) args) found t method nil)) (setq method (cdr method))) (if found result default))) (t (if (lyskom-aux-item-definition-field item method) (apply (lyskom-aux-item-definition-field item method) args) default)))) (defun lyskom-aux-item-has-call (item method) "Return non-nil if aux-item ITEM has a defined method METHOD" (when (lyskom-aux-item-p item) (setq item (lyskom-find-aux-item-definition item))) (lyskom-aux-item-definition-field item method)) (defun lyskom-aux-item-call (def method &rest args) (apply 'lyskom-aux-item-try-call def method nil args)) (defun lyskom-aux-item-definition-field (def method) (when (lyskom-aux-item-p def) (setq def (lyskom-find-aux-item-definition def))) (cdr (assq method def))) (defun lyskom-find-aux-item-definition (aux) (assq (aux-item->tag aux) lyskom-aux-item-definitions)) (defun lyskom-match-aux-items (item-list predicate) "Return a list of all aux-items in ITEM-LIST that match PREDICATE. PREDICATE should receives a single aux-item as its argument and should return non-nil if the item is to be included in the list." (let ((result nil)) (while item-list (when (funcall predicate (car item-list)) (setq result (cons (car item-list) result))) (setq item-list (cdr item-list))) (nreverse result))) (defun lyskom-get-aux-item (item-list tag) "Return all aux-items in ITEM-LIST with tag TAG." (lyskom-match-aux-items item-list (lambda (el) (eq (aux-item->tag el) tag)))) (defun lyskom-aux-item-terminating-button (item obj) (if obj (lyskom-format " %#1@%[[*]%]" (lyskom-default-button 'aux (cond ((lyskom-text-stat-p obj) (list 'text (text-stat->text-no obj) (aux-item->aux-no item))) ((lyskom-conf-stat-p obj) (list 'conf (conf-stat->conf-no obj) (aux-item->aux-no item))) ((eq obj 'server) (list 'server nil (aux-item->aux-no item))) (t item)))) "")) (defun lyskom-aux-item-after-parse (item) (lyskom-aux-item-try-call item 'decode-data nil) item) (defun lyskom-aux-item-output-data (item) (lyskom-aux-item-try-call item 'encode-data (aux-item->data item) item)) (defun lyskom-aux-item-modify-list (item-list deleted added) "Return a copy of ITEM-LIST with items in DELETED removed and items in ADDED added." (let ((new-nos (nconc (mapcar 'aux-item->aux-no deleted) (mapcar 'aux-item->aux-no added)))) (nconc (filter-list (lambda (el) (not (memq (aux-item->aux-no el) new-nos))) item-list) added))) (defun lyskom-aux-item-validate (data &rest tests) "Validata aux-item data. DATA is data to validate. TESTS are the tests to use. A test can be a function or a regular expression to match. Invalid tests are silently ignored." (not (lyskom-traverse test tests (condition-case nil (unless (cond ((stringp test) (string-match test data)) ((functionp test) (funcall test data))) (lyskom-traverse-break t)) (error (lyskom-traverse-break t)))))) ;;; ====================================================================== (def-aux-item content-type 1 (text-name aux-content-type-name) (parse . lyskom-parse-content-type) (text-print . lyskom-print-content-type) (info . lyskom-aux-item-info)) (def-aux-item fast-reply 2 (text-name aux-fast-reply-name) (parse . nil) (parse-data . lyskom-aux-item-decode-data) (encode-data . lyskom-aux-item-encode-data) (info . lyskom-aux-item-info)) (def-aux-item cross-reference 3 (text-name aux-cross-reference-name) (status-print . lyskom-status-print-cross-reference) (text-print-when . comment) (parse . lyskom-parse-cross-reference) (parse-data . lyskom-aux-item-decode-data) (encode-data . lyskom-aux-item-encode-data) (text-print . lyskom-print-cross-reference) (edit-insert . lyskom-edit-insert-cross-reference) (info . lyskom-aux-item-info)) (def-aux-item no-comments 4 (text-name aux-no-comments-name) (text-print-when . footer) (parse . lyskom-parse-no-comments) (text-print . lyskom-print-no-comments) (edit-insert . lyskom-edit-insert-no-comments) (info . lyskom-aux-item-info)) (def-aux-item personal-comment 5 (text-name aux-personal-comment-name) (text-print-when . footer) (parse . lyskom-parse-personal-comments) (text-print . lyskom-print-personal-comments) (edit-insert . lyskom-edit-insert-personal-comments) (info . lyskom-aux-item-info)) (def-aux-item request-confirmation 6 (text-name aux-request-confirmation-name) (text-print-when . header) (parse . lyskom-parse-request-confirmation) (text-print . lyskom-print-request-confirmation) (edit-insert . lyskom-edit-insert-request-confirmation) (info . lyskom-aux-item-info) (read-action . lyskom-request-confirmation-action)) (def-aux-item read-confirm 7 (text-name aux-read-confirm-name) (text-print-when . header) (text-print . lyskom-print-read-confirm) (info . lyskom-aux-item-info)) (def-aux-item redirect 8 (text-name aux-redirect-name) (print . lyskom-print-redirect) (info . lyskom-aux-item-info)) (def-aux-item x-face 9 (text-name aux-x-face-name) (print . lyskom-print-xface) (info . lyskom-aux-item-info)) (def-aux-item alternate-name 10 (text-name aux-alternate-name-name) (text-print-when . header) (text-print . lyskom-print-alternate-name) (encode-data . lyskom-aux-item-encode-data) (parse-data . lyskom-aux-item-decode-data) (info . lyskom-aux-item-info)) (def-aux-item pgp-signature 11 (text-name aux-pgp-signature-name) (info . lyskom-aux-item-info)) (def-aux-item pgp-public-key 12 (text-name aux-pgp-public-key-name) (info . lyskom-aux-item-info)) (def-aux-item e-mail-address 13 (text-name aux-e-mail-address-name) (info . lyskom-aux-item-info)) (def-aux-item faq-text 14 (text-name aux-faq-text-name) (info . lyskom-aux-item-info) (text-header-line . (faq-in-text faq-in-text-by)) (status-print . lyskom-status-print-faq-text)) (def-aux-item creating-software 15 (text-name aux-creating-software-name) (info . lyskom-aux-item-info) (text-print-when . header) (parse-data . lyskom-aux-item-decode-data) (encode-data . lyskom-aux-item-encode-data) (text-print . lyskom-print-creating-software)) (def-aux-item mx-author 16 (text-name aux-mx-author-name) (info . lyskom-aux-item-info)) (def-aux-item mx-from 17 (text-name aux-mx-from-name) (info . lyskom-aux-item-info)) (def-aux-item mx-reply-to 18 (text-name aux-mx-reply-to-name) (info . lyskom-aux-item-info)) (def-aux-item mx-to 19 (text-name aux-mx-to-name) (info . lyskom-aux-item-info)) (def-aux-item mx-cc 20 (text-name aux-mx-cc-name) (info . lyskom-aux-item-info)) (def-aux-item mx-date 21 (text-name aux-mx-date-name) (info . lyskom-aux-item-info)) (def-aux-item mx-message-id 22 (text-name aux-mx-message-id-name) (info . lyskom-aux-item-info)) (def-aux-item mx-in-reply-to 23 (text-name aux-mx-in-reply-to-name) (info . lyskom-aux-item-info)) (def-aux-item mx-misc 24 (text-name aux-mx-misc-name) (info . lyskom-aux-item-info)) (def-aux-item mx-allow-filter 25 (text-name aux-mx-allow-filter-name) (info . lyskom-aux-item-info)) (def-aux-item mx-reject-forward 26 (text-name aux-mx-reject-forward-name) (info . lyskom-aux-item-info)) (def-aux-item notify-comments 27 (text-name aux-notify-comments-name) (info . lyskom-aux-item-info)) (def-aux-item faq-for-conf 28 (text-name aux-faq-for-conf-name) (text-print . lyskom-print-faq-for-conf) (text-print-when . header) (info . lyskom-aux-item-info) (read-action . lyskom-faq-for-conf-action)) (def-aux-item recommended-conf 29 (text-name aux-recommended-conf-name) (status-print . lyskom-print-recommended-conf) (info . lyskom-aux-item-info)) (def-aux-item allowed-content-type 30 (text-name aux-allowed-content-type-name) (info . lyskom-aux-item-info)) (def-aux-item canonical-name 31 (text-name aux-canonical-name-name) (info . lyskom-aux-item-info)) (def-aux-item mx-list-name 32 (text-name aux-mx-list-name-name) (info . lyskom-aux-item-info) (status-print . lyskom-print-mx-list-name)) (def-aux-item send-comments-to 33 (text-name aux-send-comments-to-name) (info . lyskom-aux-item-info) (status-print . lyskom-print-send-comments-to)) (def-aux-item world-readable 34 (text-name aux-world-readable-name) (info . lyskom-aux-item-info) (text-print . lyskom-print-world-readable) (parse . lyskom-parse-world-readable) (edit-insert . lyskom-edit-insert-world-readable) (text-print-when . header)) (def-aux-item mx-refuse-import 35 (text-name aux-mx-refuse-import) (info . lyskom-aux-item-info) (status-print . lyskom-print-mx-refuse-import)) (def-aux-item elisp-client-read-faq 10000 (text-name aux-elisp-client-read-faq-name) (info . lyskom-aux-item-info) (status-print . lyskom-print-elisp-client-read-faq)) (def-aux-item elisp-client-rejected-invitation 10001 (text-name aux-elisp-client-rejected-invitation-name) (info . lyskom-aux-item-info) (status-print . lyskom-print-elisp-client-rejected-invitation)) ;;; ================================================================ (defun lyskom-aux-item-decode-data (item) (set-aux-item->data item (lyskom-decode-coding-string (aux-item->data item) lyskom-server-coding-system))) (defun lyskom-aux-item-encode-data (item) (lyskom-encode-coding-string (aux-item->data item) lyskom-server-coding-system) ) (defun lyskom-aux-item-info (item header) (let ((def (lyskom-find-aux-item-definition item))) (concat (lyskom-get-string 'aux-item-for) header "\n" (lyskom-format 'aux-item-info (aux-item->aux-no item) (aux-item->tag item) (if def (lyskom-aux-item-definition->name def) "unknown") (aux-item->creator item) (lyskom-format-time 'date-and-time (aux-item->sent-at item)) (if (aux-item-flags->deleted (aux-item->flags item)) (format "(%s)" (lyskom-get-string 'deleted)) "") (mapconcat 'identity (delq nil (list (and (aux-item-flags->secret (aux-item->flags item)) (lyskom-get-string 'secret)) (and (aux-item-flags->anonymous (aux-item->flags item)) (lyskom-get-string 'hide-creator)) (and (aux-item-flags->inherit (aux-item->flags item)) (lyskom-get-string 'inherit)))) ", ") (cond ((not (aux-item-flags->inherit (aux-item->flags item))) (lyskom-get-string 'no-inheritance)) ((zerop (aux-item->inherit-limit item)) (lyskom-get-string 'unlimited-inherit)) ((eq 1 (aux-item->inherit-limit item)) (lyskom-get-string 'no-more-inherit)) (t (lyskom-format 'inherit-steps (1- (aux-item->inherit-limit item))))) (aux-item->data item))))) (defun lyskom-print-content-type (item &optional obj) (concat (lyskom-format 'content-type-aux (aux-item->data item)) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-parse-content-type () (and (looking-at (lyskom-get-string 'content-type-regexp)) (match-string 1))) (defun lyskom-parse-cross-reference () (or (and (looking-at (lyskom-get-string 'cross-reference-text-regexp)) (concat "T" (match-string 1))) (and (looking-at (lyskom-get-string 'cross-reference-conf-regexp)) (concat "C" (match-string 1))) (and (looking-at (lyskom-get-string 'cross-reference-pers-regexp)) (concat "P" (match-string 1))))) (defun lyskom-edit-insert-cross-reference (item pers) (concat (lyskom-print-cross-reference item nil pers) (lyskom-edit-generate-aux-item-flags (aux-item->flags item)))) (defun lyskom-print-cross-reference (item &optional obj pers) (let ((pers (if (and (zerop (aux-item->creator item)) pers) pers (aux-item->creator item)))) ;; We use string-to-int here since we handle floats in ;; lyskom-format. (concat (cond ((string-match "^P\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-pers-aux (string-to-int (match-string 1 (aux-item->data item))) pers )) ((string-match "^C\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-conf-aux (string-to-int (match-string 1 (aux-item->data item))) pers )) ((string-match "^T\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-text-aux (string-to-int (match-string 1 (aux-item->data item))) pers )) (t (lyskom-format 'strange-cross-reference (aux-item->data item) pers ))) (lyskom-aux-item-terminating-button item obj) ))) (defun lyskom-status-print-cross-reference (item &optional obj pers) ;; We use string-to-int here since we handle floats in ;; lyskom-format. (lyskom-insert (concat (cond ((string-match "^P\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-pers-status-aux (string-to-int (match-string 1 (aux-item->data item))) (aux-item->creator pers) )) ((string-match "^C\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-conf-status-aux (string-to-int (match-string 1 (aux-item->data item))) pers )) ((string-match "^T\\([0-9]+\\)" (aux-item->data item)) (lyskom-format 'cross-reference-text-status-aux (string-to-int (match-string 1 (aux-item->data item))) (aux-item->creator pers) )) (t (lyskom-format 'strange-cross-reference-status (aux-item->data item) (aux-item->creator pers) ))) (lyskom-aux-item-terminating-button item obj) "\n"))) (defun lyskom-parse-no-comments () (and (looking-at (lyskom-get-string 'no-comments-regexp)) "")) (defun lyskom-print-no-comments (item &optional obj) (concat (lyskom-format 'no-comments-aux) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-edit-insert-no-comments (item &optional obj) (concat (lyskom-format 'no-comments-edit-aux) (lyskom-edit-generate-aux-item-flags (aux-item->flags item)))) (defun lyskom-parse-personal-comments () (and (looking-at (lyskom-get-string 'personal-comment-regexp)) "")) (defun lyskom-print-personal-comments (item &optional obj) (concat (lyskom-format 'personal-comment-aux) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-edit-insert-personal-comments (item &optional obj) (concat (lyskom-format 'personal-comment-edit-aux) (lyskom-edit-generate-aux-item-flags (aux-item->flags item)))) (defun lyskom-parse-request-confirmation () (and (looking-at (lyskom-get-string 'request-confirmation-regexp)) "")) (defun lyskom-print-request-confirmation (item &optional obj) (concat (lyskom-format 'request-confirmation-aux (aux-item->creator item)) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-edit-insert-request-confirmation (item &optional obj) (concat (lyskom-format 'request-confirmation-edit-aux) (lyskom-edit-generate-aux-item-flags (aux-item->flags item)))) (defun lyskom-faq-for-conf-action (text-stat) (let ((faqs (text-stat-find-aux text-stat 28))) (lyskom-traverse aux faqs (condition-case nil (lyskom-register-read-faq (lyskom-string-to-int (aux-item->data aux) t) (text-stat->text-no text-stat)) (lyskom-integer-conversion-error nil))))) (defun lyskom-request-confirmation-action (text-stat) (let ((confirmations (text-stat-find-aux text-stat 7)) (have-confirmation nil)) (while confirmations (when (eq lyskom-pers-no (aux-item->creator (car confirmations))) (setq have-confirmation t) (setq confirmations nil)) (setq confirmations (cdr confirmations))) (when (not have-confirmation) (lyskom-scroll) (when (lyskom-j-or-n-p (lyskom-format (lyskom-get-string 'confirm-read-q) text-stat)) (let ((item (lyskom-create-aux-item 0 7 lyskom-pers-no nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 ""))) (initiate-modify-text-info 'background nil (text-stat->text-no text-stat) nil (list item)) (cache-del-text-stat (text-stat->text-no text-stat))))))) (defun lyskom-print-read-confirm (item &optional obj) (concat (lyskom-format 'read-confirm-aux (aux-item->creator item) (lyskom-format-time 'date-and-time (aux-item->sent-at item))) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-print-redirect (item &optional obj) ;; We use string-to-int here since we handle floats in ;; lyskom-format. (concat (cond ((string-match "^E-mail:\\(.*\\)$" (aux-item->data item)) (lyskom-format 'redirect-email-aux (match-string 1 (aux-item->data item)))) ((string-match "^LysKOM:\\(.*\\)$" (aux-item->data item)) (lyskom-format 'redirect-lyskom-aux (string-to-int (match-string 1 (aux-item->data item)))))) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-print-xface (item &optional obj) (lyskom-xemacs-or-gnu (lyskom-maybe-add-face-to-string item (make-string 0 ?X)) nil)) (defun lyskom-maybe-add-face-to-string (item string) (lyskom-xemacs-or-gnu (if (null item) string (setq item (car item)) (unless (lyskom-find-face 'kom-xface) (make-face 'kom-xface)) (let* ((h (concat "X-Face: " (aux-item->data item))) (g (intern h lyskom-xface-cache)) (e (make-extent 0 (length string) string))) (if (boundp g) (setq g (symbol-value g)) (set g (make-glyph (list (list 'global (cons '(tty) [nothing])) (list 'global (cons '(win) (vector 'xface ':data h)))))) (setq g (symbol-value g)) (set-glyph-face g 'kom-xface)) (set-extent-begin-glyph e g) (set-extent-property e 'end-open nil) (set-extent-property e 'start-open nil) (set-extent-property e 'duplicable t) string)) string)) (defun lyskom-print-alternate-name (item &optional obj) (concat "[" (aux-item->data item) "] " (lyskom-aux-item-terminating-button item obj))) (defun lyskom-print-faq-format-subject (text text-stat text-no) (if (and text text-stat) (concat "\"" (cond ((string-match "\n" (text->decoded-text-mass text text-stat)) (substring (text->decoded-text-mass text text-stat) 0 (match-beginning 0))) (t "")) "\"") (lyskom-format 'no-such-text-m text-no))) (defun lyskom-deferred-print-faq (text-stat defer-info) (if text-stat (initiate-get-text 'deferred (lambda (text text-stat defer-info) (lyskom-replace-deferred defer-info (lyskom-format "%#1r" (lyskom-print-faq-format-subject text text-stat (defer-info->data defer-info))))) (text-stat->text-no text-stat) text-stat defer-info) (lyskom-replace-deferred defer-info (lyskom-print-faq-format-subject nil nil (defer-info->data defer-info))))) (defun lyskom-status-print-faq-text (item &optional obj) (if (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let* ((text-no (string-to-int (aux-item->data item))) (subject (if kom-deferred-printing (lyskom-create-defer-info 'get-text-stat text-no 'lyskom-deferred-print-faq nil nil nil text-no) (blocking-do-multiple ((text (get-text text-no)) (text-stat (get-text-stat text-no))) (lyskom-print-faq-format-subject text text-stat text-no))))) (lyskom-format-insert 'faq-in-text-aux text-no subject) (lyskom-insert (lyskom-aux-item-terminating-button item obj))) (lyskom-format-insert 'bad-faq-in-text-aux (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj))) (lyskom-insert "\n")) (defun lyskom-print-faq-for-conf (item &optional obj) (if (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let ((conf-no (string-to-int (aux-item->data item)))) (concat (cond ((zerop conf-no) (lyskom-get-string 'faq-for-server-aux)) (t (lyskom-format 'faq-for-conf-aux conf-no))) (lyskom-aux-item-terminating-button item obj))) (lyskom-format 'bad-faq-for-conf-aux (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj)))) (defun lyskom-print-creating-software (item &optional obj) (when (or kom-show-creating-software (lyskom-viewing-noconversion)) (concat (lyskom-format 'creating-software-aux (aux-item->data item)) (lyskom-aux-item-terminating-button item obj)))) (defun lyskom-print-send-comments-to (item &optional obj) (if (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let ((conf-no (string-to-int (aux-item->data item)))) (lyskom-format-insert 'status-send-comments-to conf-no (lyskom-aux-item-terminating-button item obj))) (lyskom-format-insert 'bad-status-send-comments-to (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj)))) (defun lyskom-parse-world-readable () (and (looking-at (regexp-quote (lyskom-get-string 'world-readable-text-edit-aux))) "")) (defun lyskom-edit-insert-world-readable (item &optional obj) (concat (lyskom-format 'world-readable-text-edit-aux) (lyskom-edit-generate-aux-item-flags (aux-item->flags item)))) (defun lyskom-print-world-readable (item &optional obj) (concat (lyskom-format 'world-readable-text-aux) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-print-mx-list-name (item &optional obj) (lyskom-format-insert 'conf-mx-list-name (aux-item->data item) (lyskom-aux-item-terminating-button item obj))) (defun lyskom-print-mx-refuse-import (item &optional obj) (let* ((sym (intern (format "mx-refuse-import-%s" (aux-item->data item)))) (s (or (lyskom-try-get-string sym 'lyskom-message) (format "'%s'" (aux-item->data item))))) (lyskom-format-insert 'conf-mx-refuse-import s (lyskom-aux-item-terminating-button item obj)))) (defun lyskom-print-recommended-conf (item &optional obj) (if (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let ((conf-no (string-to-int (aux-item->data item)))) (lyskom-format-insert 'recommended-conf-aux conf-no (lyskom-aux-item-terminating-button item obj))) (lyskom-format-insert 'bad-recommended-conf-aux (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj)))) (defun lyskom-print-elisp-client-read-faq (item &optional obj) (when (lyskom-extended-status-information 'read-faq) (when (string-match "^\\([0-9]+\\) \\([0-9]+\\)" (aux-item->data item)) (condition-case nil (let ((conf-no (lyskom-string-to-int (match-string 1 (aux-item->data item)) t)) (text-no (lyskom-string-to-int (match-string 2 (aux-item->data item)) t))) (lyskom-format-insert 'status-read-faq-aux-item conf-no text-no (lyskom-aux-item-terminating-button item obj))) (lyskom-integer-conversion-error (lyskom-format-insert 'bad-status-read-faq-aux-item (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj))))))) (defun lyskom-print-elisp-client-rejected-invitation (item &optional obj) (if (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let ((conf-no (string-to-int (aux-item->data item)))) (lyskom-format-insert 'status-rejected-recommendation-aux-item conf-no (lyskom-aux-item-terminating-button item obj))) (lyskom-format-insert 'bad-status-rejected-recommendation-aux-item (aux-item->data item) `(face ,kom-warning-face) (lyskom-aux-item-terminating-button item obj)))) (provide 'lyskom-aux-items) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: mime.el,v 44.11 2004/11/11 07:14:59 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: mime.el ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: mime.el,v 44.11 2004/11/11 07:14:59 _cvs_pont_lyskomelisp Exp $\n")) (defvar lyskom-charset-alist '(((ascii) . us-ascii) ((ascii latin-iso8859-1) . iso-8859-1) ((ascii latin-iso8859-2) . iso-8859-2) ((ascii latin-iso8859-3) . iso-8859-3) ((ascii latin-iso8859-4) . iso-8859-4) ((ascii cyrillic-iso8859-5) . iso-8859-5) ;;; ((ascii cyrillic-iso8859-5) . koi8-r) ((ascii arabic-iso8859-6) . iso-8859-6) ((ascii greek-iso8859-7) . iso-8859-7) ((ascii hebrew-iso8859-8) . iso-8859-8) ((ascii latin-iso8859-9) . iso-8859-9) ((ascii latin-iso8859-15) . iso-8859-15) ((ascii latin-jisx0201 japanese-jisx0208-1978 japanese-jisx0208) . iso-2022-jp) ((ascii latin-jisx0201 katakana-jisx0201 japanese-jisx0208) . shift_jis) ((ascii korean-ksc5601) . euc-kr) ((ascii chinese-gb2312) . gb2312) ((ascii chinese-big5-1 chinese-big5-2) . big5) ((ascii latin-iso8859-1 greek-iso8859-7 latin-jisx0201 japanese-jisx0208-1978 chinese-gb2312 japanese-jisx0208 korean-ksc5601 japanese-jisx0212) . iso-2022-jp-2) ;; ((ascii latin-iso8859-1 greek-iso8859-7 ;; latin-jisx0201 japanese-jisx0208-1978 ;; chinese-gb2312 japanese-jisx0208 ;; korean-ksc5601 japanese-jisx0212 ;; chinese-cns11643-1 chinese-cns11643-2) . iso-2022-int-1) ;; ,(if (or (not (fboundp 'charsetp)) ;; non-Mule case ;; (charsetp 'unicode-a) ;; (not (mm-coding-system-p 'mule-utf-8))) ;; '(utf-8 unicode-a unicode-b unicode-c unicode-d unicode-e) ;; ;; If we have utf-8 we're in Mule 5+. ;; (append '(utf-8) ;; (delete 'ascii ;; (lyskom-coding-system-get 'mule-utf-8 'safe-charsets)))) )) (defun lyskom-mime-string-charset (data) (let* ((cs (lyskom-find-charset-string data)) (tmp lyskom-charset-alist) (best-guess (let ((system nil)) (while (and tmp cs) (if (lyskom-subset-p cs (car (car tmp))) (setq system (cdr (car tmp)) tmp nil) (setq tmp (cdr tmp)))) system))) (or best-guess (lyskom-xemacs-or-gnu lyskom-server-coding-system (let ((coding (lyskom-find-coding-systems-for-charsets cs))) (while (and (car coding) (null (or (lyskom-coding-system-get (car coding) 'mime-charset) (lyskom-coding-system-get (car coding) :mime-charset)))) (setq coding (cdr coding))) (and (car coding) (or (lyskom-coding-system-get (car coding) 'mime-charset) (lyskom-coding-system-get (car coding) :mime-charset))))) lyskom-server-coding-system))) (defun lyskom-mime-charset-coding-system (charset) (condition-case nil (and (lyskom-check-coding-system charset) charset) (error 'raw-text))) (defun lyskom-mime-encode-string (data) (let* ((mime-charset (lyskom-mime-string-charset data)) (coding-system (lyskom-mime-charset-coding-system mime-charset))) (when (and mime-charset coding-system) (cons mime-charset (lyskom-encode-coding-string data coding-system))))) (defun lyskom-mime-decode-string (data charset) (let* ((coding-system (lyskom-mime-charset-coding-system charset))) (if coding-system (lyskom-decode-coding-string data coding-system) data))) (defun lyskom-mime-decode-content-type (data) (let ((content-type nil) (params nil) (start 0)) (when (string-match "^[^;]*" data) (setq content-type (match-string 0 data)) (setq start (match-end 0))) (while (string-match ";\\s *\\([^=;]*\\)\\(=\\([^;]*\\)\\)" data start) (let ((param-name (intern (match-string 1 data))) (param-value (match-string 3 data))) (when (and (memq param-name '(charset format)) param-value) (setq param-value (intern param-value))) (setq params (cons (cons param-name (or param-value t)) params))) (setq start (match-end 0))) (cons content-type params))) (provide 'lyskom-mime) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: prefetch.el,v 44.32 2004/07/15 17:13:03 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: prefetch.el ;;;; ;;;; The (new) prefetch system. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: prefetch.el,v 44.32 2004/07/15 17:13:03 byers Exp $\n")) (def-kom-var lyskom-prefetch-queue nil "A queue where all prefetch requests are entered." local) (defvar lyskom-inhibit-prefetch nil "When non-nil, disables the prefetch.") (def-kom-var lyskom-pending-prefetch 0 "Variable counting the number of unfinished prefetch requests." local) (defun lyskom-setup-prefetch () "Set up the prefetch system" (setq lyskom-prefetch-queue (lyskom-queue-create)) (setq lyskom-pending-prefetch 0) (setq lyskom-membership-is-read 0)) (defun lyskom-reset-prefetch () "Reset the prefetch system" (lyskom-setup-prefetch)) (defsubst lyskom-membership-is-read () "Return t if the while membership list has been fetched, and nil otherwise." (eq lyskom-membership-is-read 't)) (defun lyskom-fetch-start-of-map (conf-stat membership) "Block fetching map for MEMBERSHIP until we see a text. Start the prefetch for the remainder of the map." (let* ((first-local (1+ (membership->last-text-read membership))) (map (blocking-do 'local-to-global (membership->conf-no membership) first-local lyskom-fetch-map-nos))) (when map (lyskom-enter-map-in-to-do-list map conf-stat membership) (when (text-mapping->later-texts-exist map) (lyskom-prefetch-map-using-conf-stat conf-stat (text-mapping->range-end map) membership))))) (defun lyskom-prefetch-conf (conf-no) "Prefetch the conf-stat for the conference with number CONF-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-conf-stat prefetch lyskom-prefetch-handler ,conf-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-pers (pers-no) "Prefetch the pers-stat for person with number PERS-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-pers-stat prefetch lyskom-prefetch-handler ,pers-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-text (text-no) "Prefetch the text-stat for the text with number TEXT-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text-stat prefetch lyskom-prefetch-handler ,text-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-textmass (text-no) "Prefetch the text mass for the text with number TEXT-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text prefetch lyskom-prefetch-handler ,text-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-textauth (text-no) "Prefetch the text stat and the author of text number TEXT-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text-stat prefetch lyskom-prefetch-textauth-handler ,text-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-text-all (text-no) "Prefetch all info about the text with number TEXT-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text-stat prefetch lyskom-prefetch-text-all-handler ,text-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-text-stat-all (text-stat) "Prefetch all info about the text with text stat TEXT-STAT." (lyskom-prefetch-text-all-handler text-stat)) (defun lyskom-prefetch-texttree (text-no &optional only-new) "Prefetch all info about the text with number TEXT-NO and descends recursively. If ONLY-NEW is non-nil and the text-stat in question is already prefetched the prefetch is not done." (unless (and only-new (cache-get-text-stat text-no)) (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text-stat prefetch lyskom-prefetch-texttree-handler ,text-no))) (lyskom-continue-prefetch)) (defun lyskom-prefetch-membership (pers-no) "Prefetch memberships for PERS-NO." (lyskom-queue-enter lyskom-prefetch-queue (list (lambda (pers-no) (if (numberp lyskom-membership-is-read) (initiate-get-part-of-membership 'prefetch 'lyskom-prefetch-membership-handler pers-no lyskom-membership-is-read lyskom-fetch-membership-length pers-no) (lyskom-prefetch-handler))) pers-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-one-membership (conf-no pers-no) "Prefetch the membership in CONF-NO for PERS-NO." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-query-read-texts prefetch lyskom-prefetch-read-texts-handler ,pers-no ,conf-no t ,lyskom-max-int ,conf-no)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-map (conf-no membership) "Prefetches a map for conf CONF-NO." (lyskom-prefetch-map-from conf-no (1+ (membership->last-text-read membership)) membership)) (defun lyskom-prefetch-map-from (conf-no first-local membership) "Prefetches a map for conf CONFNO starting att FIRST-LOCAL." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-conf-stat prefetch lyskom-prefetch-confstatformap-handler ,conf-no ,first-local ,membership)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-map-using-conf-stat (conf-stat first-local membership) "Prefetches a map for conf CONFSTAT starting att FIRST-LOCAL." (lyskom-queue-enter lyskom-prefetch-queue `(initiate-local-to-global prefetch lyskom-prefetch-map-handler ,(conf-stat->conf-no conf-stat) ,first-local ,lyskom-fetch-map-nos ,conf-stat ,first-local ,membership)) (lyskom-continue-prefetch)) (defun lyskom-prefetch-texts (texts) "Prefetches a list of texts." (when texts (lyskom-queue-enter lyskom-prefetch-queue `(initiate-get-text-stat prefetch lyskom-prefetch-texts-handler ,(car texts) ,(cdr texts)))) (lyskom-continue-prefetch)) (defun lyskom-prefetch-cancel-prefetch-map (conf-no &optional queue)) ;;; ================================================================ ;;; Internal prefetch functions (defun lyskom-stop-prefetch () "Stop the prefetch process temporarily." ) (defun lyskom-start-prefetch () "Start the whole prefetch process" (lyskom-continue-prefetch)) (defun lyskom-continue-prefetch () "Called after each prefetch is finished and also when the whole prefetch process is started. Used to keep prefetch going." (unless lyskom-inhibit-prefetch (let ((lyskom-inhibit-prefetch t)) (while (and (< lyskom-pending-prefetch lyskom-prefetch-limit) (lyskom-prefetch-one-item) (++ lyskom-pending-prefetch)))))) (defun lyskom-prefetch-one-item () "Get the first element of the prefetch data structure and fetch it. Return t if an element was prefetched, otherwise return nil." (let ((item (lyskom-queue-delete-first lyskom-prefetch-queue))) (cond ((null item) nil) ((functionp (car item)) (apply (car item) (cdr item)) t) (t (signal 'lyskom-internal-error (list "unknown prefetch key" (car item))))))) ;;; ================================================================ ;;; Handlers ;;; (defun lyskom-prefetch-textauth-handler (text-stat) "Prefetch the conf-stat of the author of the text TEXT-STAT." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (when text-stat (lyskom-prefetch-conf (text-stat->author text-stat))) (lyskom-start-prefetch)) (defun lyskom-prefetch-text-all-handler (text-stat) "Prefetch all info neccessary to write the text with text-stat TEXT-STAT." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (lyskom-prefetch-conf (text-stat->author text-stat)) (lyskom-prefetch-textmass (text-stat->text-no text-stat)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (cond ((memq type lyskom-recpt-types-list) (lyskom-prefetch-conf (misc-info->recipient-no misc))) ((eq type 'COMM-IN) (lyskom-prefetch-textauth (misc-info->comm-in misc))) ((eq type 'FOOTN-IN) (lyskom-prefetch-textauth (misc-info->footn-in misc))) ((eq type 'COMM-TO) (lyskom-prefetch-textauth (misc-info->comm-to misc))) ((eq type 'FOOTN-TO) (lyskom-prefetch-textauth (misc-info->footn-to misc))) (t nil)))) (lyskom-start-prefetch)) (defun lyskom-prefetch-texttree-handler (text-stat) "Prefetch all info neccessary to write the text with text-stat TEXT-STAT. Then prefetch all info (texttree) of comments." (-- lyskom-pending-prefetch) (when text-stat (lyskom-stop-prefetch) (lyskom-prefetch-conf (text-stat->author text-stat)) (lyskom-prefetch-textmass (text-stat->text-no text-stat)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (cond ((memq type lyskom-recpt-types-list) (lyskom-prefetch-conf (misc-info->recipient-no misc))) ((eq type 'COMM-IN) (lyskom-prefetch-texttree (misc-info->comm-in misc) t)) ((eq type 'FOOTN-IN) (lyskom-prefetch-texttree (misc-info->footn-in misc) t)) ((eq type 'COMM-TO) (lyskom-prefetch-textauth (misc-info->comm-to misc))) ((eq type 'FOOTN-TO) (lyskom-prefetch-textauth (misc-info->footn-to misc))) (t nil))))) (lyskom-start-prefetch)) (defun lyskom-prefetch-read-texts-handler (membership pers-no) (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (when membership (let ((old-mship (lyskom-try-get-membership (membership->conf-no membership) t))) (if old-mship (set-membership->read-texts old-mship (membership->read-texts membership)) (lyskom-add-memberships-to-membership (list membership))) (when (and (lyskom-visible-membership membership) (lyskom-prefetch-map (membership->conf-no membership) membership)))) (lyskom-start-prefetch))) (defun lyskom-prefetch-membership-handler (memberships pers-no) "Handle the return of the membership prefetch call." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (lyskom-add-memberships-to-membership memberships) (if (and (numberp lyskom-membership-is-read) (< (length memberships) lyskom-fetch-membership-length)) (setq lyskom-membership-is-read t) (setq lyskom-membership-is-read (+ lyskom-membership-is-read lyskom-fetch-membership-length)) (lyskom-prefetch-membership pers-no)) (lyskom-start-prefetch)) (defun lyskom-prefetch-confstatformap-handler (conf-stat first-local membership) "Now that we have the conf-stat we can fetch the map." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (lyskom-prefetch-map-using-conf-stat conf-stat first-local membership) (lyskom-start-prefetch)) (defun lyskom-prefetch-map-handler (map conf-stat first-local membership) "Handle the return of the membership prefetch call. Maps are `cached' in lyskom-to-do-list." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (let ((next-start (and map (text-mapping->range-end map)))) (when map (when (text-mapping->later-texts-exist map) (lyskom-prefetch-map-using-conf-stat conf-stat next-start membership)) (lyskom-enter-map-in-to-do-list map conf-stat membership))) (lyskom-start-prefetch) (lyskom-update-prompt) (lyskom-set-mode-line)) (defun lyskom-prefetch-texts-handler (text-stat texts queue) "Prefetch all info neccessary to write the text with text-stat TEXT-STAT." (-- lyskom-pending-prefetch) (lyskom-stop-prefetch) (lyskom-prefetch-conf (text-stat->author text-stat)) (lyskom-prefetch-textmass (text-stat->text-no text-stat)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (cond ((memq type lyskom-recpt-types-list) (lyskom-prefetch-conf (misc-info->recipient-no misc))) ((eq type 'COMM-IN) (lyskom-prefetch-textauth (misc-info->comm-in misc))) ((eq type 'FOOTN-IN) (lyskom-prefetch-textauth (misc-info->footn-in misc))) ((eq type 'COMM-TO) (lyskom-prefetch-textauth (misc-info->comm-to misc))) ((eq type 'FOOTN-TO) (lyskom-prefetch-textauth (misc-info->footn-to misc))) (t nil)))) (lyskom-prefetch-texts texts) (lyskom-start-prefetch)) (defun lyskom-prefetch-handler (&rest data) "Handler called after each simple prefetch request is done." (-- lyskom-pending-prefetch) (lyskom-continue-prefetch)) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: startup.el,v 44.111 2005/01/09 01:16:02 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: startup.el ;;;; ;;;; This file contains functions that are called only when lyskom ;;;; is loaded, started or when a new user is logged in during a ;;;; session. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: startup.el,v 44.111 2005/01/09 01:16:02 byers Exp $\n")) ;;; ================================================================ ;;; Start kom. (defvar lyskom-www-proxy-connect-phase 1 "Phase when reading connection response from www-proxy: 1: (initial phase) waiting for the string \"HTTP/1.0 2000 Connection established\" 2: we have seen the connection string. After this, it may come lines stating proxy-agents and other things. They all seem to end with an empty line, so in this phase we wait for an empty line.") (eval-and-compile (defun lyskom-compilation-in-progress () "Returns non-nil if the client currently is being compiled, else nil." ;; This horrid code is inspired from how cl-compiling-file in the ;; cl package works. (let ((outbuffersym (lyskom-xemacs-or-gnu 'byte-compile-outbuffer 'outbuffer))) (and (boundp outbuffersym) (bufferp (symbol-value outbuffersym)) (equal (buffer-name (symbol-value outbuffersym)) " *Compiler Output*"))))) (defconst lyskom-is-running-compiled (eval-when-compile (lyskom-compilation-in-progress)) "Non-nil if the client is running compiled, else nil.") ;;;###autoload (defun lyskom (&optional host username password session-priority invisiblep) "Start a LysKOM session. Optional arguments: HOST, USERNAME, PASSWORD and INVISIBLEP. A numeric prefix argument sets the session priority. A prefix argument of `C-u', on the other hand, logs in the session without notifying other clients of the event. See lyskom-mode for details on lyskom." (interactive (list (lyskom-read-server-name (lyskom-format 'server-q (or (getenv "KOMSERVER") lyskom-default-server kom-default-server))) nil nil (if current-prefix-arg (prefix-numeric-value current-prefix-arg) nil) (and current-prefix-arg (listp current-prefix-arg)))) (run-hooks 'lyskom-init-hook) (setq username (or username lyskom-default-user-name kom-default-user-name (getenv "KOMNAME"))) (setq password (or password (when (and lyskom-default-password ; Got default password? (or (not lyskom-server-name) ; For this host? (string= lyskom-server-name host))) lyskom-default-password) kom-default-password (getenv "KOMPASSWORD"))) (if (zerop (length host)) (let* ((env-kom (getenv "KOMSERVER")) (canon (or (lyskom-string-rassoc env-kom kom-server-aliases) (lyskom-string-rassoc env-kom kom-builtin-server-aliases)))) (setq host (or (car canon) env-kom lyskom-default-server kom-default-server)))) (let ((port 4894) (init-done nil)) (cond ;Allow "nanny:4892" to use port 4892. ((string-match ":" host) (setq port (string-to-int (substring host (match-end 0)))) (cond ((zerop (match-beginning 0)) (setq host (or lyskom-default-server kom-default-server))) (t (setq host (substring host 0 (match-beginning 0))))))) (let* ((duplicate-buffers (delq nil (mapcar (lambda (buffer) (and (lyskom-buffer-p buffer t) (buffer-name buffer) (string-match (regexp-quote host) (buffer-name buffer)) (save-excursion (set-buffer buffer) (and (boundp 'lyskom-server-port) (eq port lyskom-server-port))) buffer)) (buffer-list)))) (name nil) (proc nil) (buffer (car duplicate-buffers)) ;; (alive (lyskom-buffer-p buffer)) (reused-buffer nil)) ;;<<<<<<< startup.el ;; (if (and buffer ;; alive ;;======= (if (and (lyskom-buffer-p buffer nil) (not (prog1 (j-or-n-p (lyskom-get-string 'start-new-session-same-server)) (message "")))) (progn (switch-to-buffer buffer) (setq reused-buffer t)) (unwind-protect (progn (cond ((and buffer (not (lyskom-buffer-p buffer))) (set-buffer buffer) (setq reused-buffer t) (goto-char (point-max)) (lyskom-insert (format (lyskom-get-string 'new-session-in-buffer) (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss))) (setq name (buffer-name buffer))) (t (setq buffer (lyskom-generate-new-buffer host)) (setq name (buffer-name buffer)))) (let* ((www-proxy-host-string (cond ((stringp kom-www-proxy) kom-www-proxy) ((listp kom-www-proxy) (or (cdr (lyskom-string-assoc host kom-www-proxy)) (cdr (assq t kom-www-proxy)) nil)) (t nil))) (www-proxy-host nil) (www-proxy-port nil) (match (string-match "\\(.*\\):\\([0-9]+\\)" (or www-proxy-host-string ""))) (headers nil)) (setq www-proxy-host (or (and match (match-string 1 www-proxy-host-string)) www-proxy-host-string) www-proxy-port (or (and match (string-to-int (match-string 2 www-proxy-host-string))) 80)) (cond (www-proxy-host (setq headers (cond ((stringp kom-www-proxy-headers) (list kom-www-proxy-headers)) ((and (listp kom-www-proxy-headers) (stringp (car kom-www-proxy-headers))) kom-www-proxy-headers) ((and (listp kom-www-proxy-headers) (consp (car kom-www-proxy-headers))) (cdr (or (lyskom-string-assoc www-proxy-host kom-www-proxy-headers) (assq t kom-www-proxy-headers)))))) (setq proc (lyskom-open-network-stream name buffer www-proxy-host www-proxy-port)) ;; We do explicit coding (lyskom-set-process-coding-system proc 'no-conversion 'no-conversion) ;; Install our filter. ;; Do this before we send the CONNECT command to ;; the proxy, in case the proxy answers fast. (setq lyskom-www-proxy-connect-phase 1) (set-process-filter proc 'lyskom-www-proxy-connect-filter) (lyskom-set-process-query-on-exit-flag proc nil) (lyskom-process-send-string proc (format "CONNECT %s:%d HTTP/1.0\r\n" host port)) (mapcar (lambda (header) (lyskom-process-send-string proc header) (lyskom-process-send-string proc "\r\n")) headers) (lyskom-process-send-string proc "\r\n") ;; Now wait for the answer from the proxy ;; ;; This is because anything we send before the ;; connection ack will be thrown away by the proxy ;; so it is bad to try to start talking with the ;; server before the connection is up. (while (eq 'lyskom-www-proxy-connect-filter (process-filter proc)) (accept-process-output proc)) ;; Now the proxy has connected to the kom server ) (t (setq proc (lyskom-open-network-stream name buffer host port)) ;; We do explicit coding (lyskom-set-process-coding-system proc 'no-conversion 'no-conversion)))) (switch-to-buffer buffer) (lyskom-mode) ;Clearing lyskom-default... (setq lyskom-buffer buffer) (setq lyskom-default-user-name username) (setq lyskom-default-password password) (setq lyskom-server-name host) (setq lyskom-server-port port) (setq lyskom-proc proc) (lyskom-setup-faces-for-buffer) (lyskom-check-configuration) (lyskom-insert (lyskom-format 'try-connect lyskom-clientversion host)) (set-process-filter proc 'lyskom-connect-filter) (lyskom-set-process-query-on-exit-flag proc nil) (lyskom-process-send-string proc (concat "A" (lyskom-format-objects (concat (user-login-name) "%" (system-name))) "\n")) (while (eq 'lyskom-connect-filter (process-filter proc)) (accept-process-output proc)) ;; Now we have got the correct response. (set-process-sentinel proc 'lyskom-sentinel) (save-excursion (lyskom-init-parse buffer)) ;; Set up timestamps and stuff (lyskom-set-connection-time-format t) ;; Async messages (lyskom-accept-async) ;; +++PREFETCH+++ (lyskom-setup-prefetch) ;; Tell the server who we are (initiate-set-client-version 'background nil "lyskom.el" lyskom-clientversion) (setq lyskom-server-version-info (blocking-do 'get-version-info)) (when (or (null lyskom-server-version-info) (<= (version-info->protocol-version lyskom-server-version-info) 7)) (lyskom-error 'too-old-server)) (lyskom-setup-client-for-server-version) (setq lyskom-server-info (blocking-do 'get-server-info)) (lyskom-format-insert 'connection-done (version-info->software-version lyskom-server-version-info)) (when (lyskom-have-call 85) (setq lyskom-collate-table (blocking-do 'get-collate-table)) (setq lyskom-char-classes nil) (lyskom-update-command-completion)) (if (not (zerop (server-info->motd-of-lyskom lyskom-server-info))) (blocking-do-multiple ((text (get-text (server-info->motd-of-lyskom lyskom-server-info))) (text-stat (get-text-stat (server-info->motd-of-lyskom lyskom-server-info)))) (let* ((conf-stat (and text-stat (blocking-do 'get-conf-stat (text-stat->author text-stat)))) (str (and text text-stat (text->decoded-text-mass text text-stat)))) (if (null text-stat) (lyskom-get-string 'lyskom-motd-was-garbed) (lyskom-insert (lyskom-get-string 'server-has-motd)) (when (string-match "\n" str) (setq str (substring str (match-end 0)))) (lyskom-format-insert "%#2$%#1s\n" (if kom-dashed-lines (make-string kom-text-header-dash-length ?-) "") (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face)))) (lyskom-format-insert "%#2$%#1t\n" str (when kom-highlight-text-body `(face ,(or kom-text-body-face lyskom-default-text-body-face)))) (lyskom-format-insert "%#2$%#1s\n" (lyskom-format-text-footer text-stat conf-stat (cond ((eq (text-stat->author text-stat) 0) (lyskom-get-string 'person-is-anonymous)) (conf-stat (conf-stat->name conf-stat)) (t (lyskom-format 'person-does-not-exist (text-stat->author text-stat)))) kom-text-footer-format lyskom-last-text-format-flags) (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face)))) )))) ;; Can't use lyskom-end-of-command here. (setq lyskom-executing-command nil) ;; Log in (kom-start-anew t session-priority invisiblep) (if (memq lyskom-buffer lyskom-buffer-list) (while (not (eq lyskom-buffer (car lyskom-buffer-list))) (setq lyskom-buffer-list (nconc (cdr lyskom-buffer-list) (list (car lyskom-buffer-list))))) (setq lyskom-buffer-list (cons lyskom-buffer lyskom-buffer-list))) ;; We're done (setq init-done t) ) ;; Something went wrong. Lets cleanup everything. :-> (if init-done nil (if proc (delete-process proc)) (unless reused-buffer (kill-buffer buffer)))))))) (defun lyskom-accept-async () (blocking-do 'accept-async '(5 7 8 9 11 12 13 14 15 16 17 18 19 20 21 22)) (let* ((ans (blocking-do 'query-async))) (unless (memq 15 (listify-vector ans)) ;; async-new-text is not implemented, so use async-new-text-old (blocking-do 'accept-async '(0 5 7 8 9 11 12 13 14 16 17 18 19 20 21 22))))) (defun lyskom-www-proxy-connect-filter (proc output) "Receive connection acknowledgement from proxy." (if lyskom-debug-communications-to-buffer (lyskom-debug-insert proc "-----> " output)) (cond ((and (= lyskom-www-proxy-connect-phase 1) (string-match "^HTTP/1\\.. 200.*\r\n" output)) (setq lyskom-www-proxy-connect-phase 2) ;; safety check: see if the empty line is already in this output (lyskom-www-proxy-connect-filter proc output)) ((and (= lyskom-www-proxy-connect-phase 2) (string-match "^\r\n" output)) (set-process-filter proc 'lyskom-connect-filter)))) (defun lyskom-open-network-stream (name buffer host service) (let ((relay (lyskom-setup-ssh-relay host service buffer))) (if relay (open-network-stream name buffer "127.0.0.1" (get relay 'relay-port)) (open-network-stream name buffer host service)))) (defun lyskom-setup-ssh-relay (server port kom-buffer) (when kom-ssh-relay-host (let* ((procname (format "ssh<%s:%s:%d>" kom-ssh-relay-host server port)) (bufname (concat " *" procname "*")) (proc (get-process procname)) (procsym (intern procname)) (relay-port (and proc (eq (process-status proc) 'run) (get procsym 'relay-port))) (msg nil)) (unwind-protect (save-excursion (set-buffer (get-buffer-create bufname)) (if relay-port (lyskom-message "%s" (lyskom-format (setq msg 'using-ssh-connection) kom-ssh-relay-host)) (when proc (delete-process proc)) (setq relay-port (+ 10000 (random 20000))) (put procsym 'relay-host (if (string-match "@" kom-ssh-relay-host) (substring kom-ssh-relay-host (1+ (match-beginning 0))) kom-ssh-relay-host)) (put procsym 'relay-port relay-port) (put procsym 'num-connected 0) (lyskom-message "%s" (lyskom-format (setq msg 'opening-ssh-connection) kom-ssh-relay-host)) (goto-char (point-max)) (insert "\n--- new connection ---\n") (let ((old-lc-all (getenv "LC_ALL"))) (unwind-protect (progn (setenv "LC_ALL" "C") (setq proc (start-process procname bufname kom-ssh-command "-n" "-x" "-L" (format "%d:%s:%d" relay-port server port) kom-ssh-relay-host "sh -c \"while :; do echo ok; sleep 600; done\""))) (setenv "LC_ALL" old-lc-all))) (lyskom-set-process-query-on-exit-flag proc nil)) (while (progn (goto-char (point-max)) (re-search-backward "^--- .* ---$" nil t) (not (re-search-forward "^ok$" nil t))) (when (re-search-forward "\\<\\(Enter passphrase.*$\\|^.*password.*$\\)\\|refused\\|disconnect\\|denied\\|error\\|key not found\\>" nil t) (cond ((match-string 1) (process-send-string proc (concat (silent-read (match-string 1)) "\n")) (delete-region (match-beginning 0) (match-end 0))) (t (error (lyskom-get-string 'ssh-cant-connect) (buffer-substring-no-properties (progn (beginning-of-line) (point)) (progn (skip-chars-forward "^\n\r") (point))))))) (sleep-for 0.5)) (setq proc nil) (lyskom-message "%s" (lyskom-format (concat (lyskom-format msg kom-ssh-relay-host) (lyskom-get-string 'done))))) (if proc (delete-process proc))) (save-excursion (set-buffer kom-buffer) (put procsym 'num-connected (1+ (or (get procsym 'num-connected) 0))) (make-local-variable 'lyskom-ssh-proxy) (setq lyskom-ssh-proxy procsym)) ))) (defun lyskom-setup-client-for-server-version () "Setup flags according to protocol versions." (lyskom-clear-features) (let ((protocol-version (version-info->protocol-version lyskom-server-version-info))) (when (>= protocol-version 8) (lyskom-set-feature long-conf-types t)) (when (>= protocol-version 9) (lyskom-set-feature dynamic-session-info t) (lyskom-set-feature idle-time t)) (when (>= protocol-version 10) (lyskom-set-feature bcc-misc t) (lyskom-set-feature aux-items t) (lyskom-set-feature highest-call 105) (lyskom-set-feature local-to-global t)) (when (>= protocol-version 11) (lyskom-set-feature read-ranges t) (lyskom-set-feature highest-call 110)) )) (defun lyskom-connect-filter (proc output) "Receive connection acknowledgement from server." (if lyskom-debug-communications-to-buffer (lyskom-debug-insert proc "-----> " output)) (cond ((string-match "^LysKOM\n" output) (set-process-filter proc 'lyskom-filter)))) ;;; ================================================================ ;;; Start anew (defun kom-start-anew (&optional lyskom-first-time-around session-priority invisiblep) "Start/login as a new person. If INVISIBLEP is not nil, the login will not be shown to other users." (interactive) (lyskom-start-of-command 'kom-start-anew) (lyskom-completing-clear-cache) (let ((new-me nil) (login-successful nil) (ignored-user-area-vars nil)) (unwind-protect (progn (if lyskom-first-time-around nil (lyskom-tell-internat 'kom-tell-login)) ;; We can't allow the prefetch to go on after the new user ;; is logged in, but to shut down the prefetch would be too ;; brutal, since the new login might be cancelled. To ;; prevent the blocking-do calls below from allowing ;; prefetch we set lyskom-inhibit-prefetch locally. (let ((lyskom-inhibit-prefetch t)) (while (not new-me) (if (and lyskom-first-time-around lyskom-default-user-name) ;; This is nil if we can't find a unique match. (setq new-me (if (integerp lyskom-default-user-name) lyskom-default-user-name (conf-z-info->conf-no (lyskom-lookup-conf-by-name lyskom-default-user-name '(pers)))))) (if new-me nil (let ((name nil)) (while (or (null name) (string= name "")) (setq name (lyskom-read-conf-name 'what-is-your-name '(pers none) nil nil t))) (setq new-me (or (conf-z-info->conf-no (lyskom-lookup-conf-by-name name '(pers))) (lyskom-create-new-person name))))) ;; Now new-me contains a number of a person. ;; Lets log him in. (if new-me (let ((conf-stat (blocking-do 'get-conf-stat new-me)) (lyskom-inhibit-minibuffer-messages t)) ;; Previously this code used lyskom-pers-no ;; directly instead of new-me, but that caused ;; problem with asynchrounous code trying to ;; access it. ;; ;; Setting lyskom-pers-no fscks up other things ;; if we do keyboard-quit in the middle, so don't. ;; ;; (setq lyskom-pers-no new-me) ;; DEBUG (if (null conf-stat) (lyskom-insert "You don't exist. Go away.\n")) (lyskom-insert (concat (conf-stat->name conf-stat) "\n")) (setq lyskom-first-time-around nil) (if (blocking-do 'login new-me (setq lyskom-default-password (if lyskom-default-password lyskom-default-password ;; Use password read when creating ;; the person when loggin in new ;; users (or lyskom-is-new-user (silent-read (lyskom-get-string 'password))))) (if invisiblep 1 0)) (progn (if lyskom-is-new-user (blocking-do 'add-member (server-info->conf-pres-conf lyskom-server-info) new-me 100 1 (lyskom-create-membership-type nil nil nil nil nil nil nil nil))) (setq login-successful t)) (lyskom-insert-string 'wrong-password) (setq lyskom-default-password nil) (when (lyskom-get-aux-item (server-info->aux-item-list lyskom-server-info) 13) ; e-mail (lyskom-insert 'wrong-password-help) (mapcar (lambda (el) (lyskom-format-insert 'wrong-password-email (aux-item->data el))) (lyskom-get-aux-item (server-info->aux-item-list lyskom-server-info) 13) ; e-mail )) (setq new-me nil)) (setq lyskom-is-new-user nil)))) ;; Now we are logged in. (setq lyskom-pers-no new-me) (setq lyskom-is-administrator nil) (lyskom-insert-string 'are-logged-in) (unless lyskom-is-running-compiled (lyskom-insert-string 'warning-about-uncompiled-client)) (unless lyskom-dont-read-user-area (setq ignored-user-area-vars (lyskom-read-options))) (unless kom-remember-password (setq lyskom-default-password nil)) ;Update mode-line string if needed (as early as possible). (lyskom-mode-name-from-host) (when (or session-priority kom-default-session-priority) (setq lyskom-session-priority (or session-priority kom-default-session-priority))) (lyskom-run-hook-with-args 'lyskom-change-conf-hook lyskom-current-conf 0) (lyskom-run-hook-with-args 'kom-change-conf-hook lyskom-current-conf 0) (setq lyskom-current-conf 0) (cache-set-marked-texts (blocking-do 'get-marks)) ;; What is this variable? It is never used. It is ust to ;; fill the cache? (let ((lyskom-who-am-i (blocking-do 'who-am-i))) (if lyskom-who-am-i (setq lyskom-session-no lyskom-who-am-i)))) ;; If login succeeded, clear the caches and set the language (when login-successful (clear-all-caches) (lyskom-init-membership) (when (lyskom-set-language (lyskom-default-language) 'local) (unless lyskom-have-one-login (lyskom-set-language (lyskom-default-language) 'global) (setq-default lyskom-language lyskom-language) (setq-default kom-default-language (list lyskom-language))) (lyskom-format-insert-before-prompt 'language-set-to (lyskom-language-name (lyskom-default-language)) "Help on changing languages" `(face underline mouse-face highlight lyskom-button t lyskom-button-text "" lyskom-button-type func lyskom-buffer ,(current-buffer) lyskom-button-arg (kom-help ("Changing Languages" . language-help)))) ) (setq lyskom-have-one-login t)) (when ignored-user-area-vars (lyskom-format-insert-before-prompt 'ignored-user-area-var (mapconcat (lambda (x) (symbol-name (car x))) ignored-user-area-vars "\n ") (lyskom-string= lyskom-clientversion lyskom-settings-version) lyskom-settings-version lyskom-clientversion 72) (setq lyskom-saved-unknown-variables ignored-user-area-vars)) ;; Show motd and encourage writing a presentation (let ((conf-stat (blocking-do 'get-conf-stat lyskom-pers-no))) (if (and conf-stat (/= (conf-stat->msg-of-day conf-stat) 0)) (progn (lyskom-insert-string 'you-have-motd) (lyskom-view-text (conf-stat->msg-of-day conf-stat)))) (lyskom-nag-about-presentation t)) (setq lyskom-is-new-user nil) ;; Start the prefetch and update some basic caches (lyskom-refetch)) (lyskom-end-of-command))) ;; Run the hook kom-login-hook. We don't want to hang the ;; login, just because something crashed here. (condition-case err (progn (run-hooks 'lyskom-login-hook) (run-hooks 'kom-login-hook)) (error (lyskom-format-insert-before-prompt 'error-in-login-hook (format "%s" err))))) (defun lyskom-refetch () "Resets and fetches all reading info. This is called at login and after prioritize and set-unread." ;; The whole membership! (lyskom-init-membership) (setq lyskom-to-do-list (lyskom-create-read-list)) (setq lyskom-reading-list (lyskom-create-read-list)) (lyskom-reset-prefetch) (let ((lyskom-inhibit-prefetch t)) (let ((unreads (blocking-do 'get-unread-confs lyskom-pers-no))) (lyskom-traverse conf-no (conf-no-list->conf-nos unreads) (lyskom-prefetch-one-membership conf-no lyskom-pers-no))) (lyskom-prefetch-membership lyskom-pers-no)) (lyskom-start-prefetch) (condition-case nil (progn (lyskom-update-read-faqs) (lyskom-clean-read-faqs lyskom-pers-no) (lyskom-update-rejected-recommendations) (lyskom-startup-check-faqs) (lyskom-startup-check-recommended-memberships)) (error nil) (quit nil))) (defun lyskom-create-new-person (name) "A new user named NAME (or an old that mis-spelled his name)." (lyskom-insert (lyskom-format 'first-greeting name)) (lyskom-scroll) (cond ((ja-or-nej-p (lyskom-format 'is-name-correct name)) (let ((password (silent-read (lyskom-get-string 'personal-password)))) (cond ((not (equal password (silent-read (lyskom-get-string 'repeat-password)))) ;; Failed to enter the same password twice (lyskom-insert-string 'repeat-failure) nil) (t ;; Entered the same password twice (let ((new-person (blocking-do 'create-person name password (lyskom-create-flags nil nil nil nil nil nil nil nil) nil))) (if (null new-person) (lyskom-insert-string 'could-not-create-you) ;; Raise a flag so the user will be added to the ;; presentation conference after login (setq lyskom-is-new-user password)) new-person))))) (t ;; Do not create a new person nil))) (defun lyskom-read-server-name (prompt) "Read the name of a LysKOM server. Copmpletion is done on the servers i kom-server-aliases and kom-builtin-server-aliases. If an alias name is entered, the corresponding address is returned." ;; Create a completion table like ;; (("kom.lysator.liu.se" . "kom.lysator.liu.se") ;; ("LysKOM" . "kom.lysator.liu.se")) (let ((known-servers (append (mapcar (function (lambda (pair) (cons (car pair) (car pair)))) (append kom-server-aliases kom-builtin-server-aliases)) (mapcar (function (lambda (pair) (cons (cdr pair) (car pair)))) (append kom-server-aliases kom-builtin-server-aliases)))) (completion-ignore-case t) server) (setq server (lyskom-completing-read prompt (lyskom-maybe-frob-completion-table known-servers) nil nil)) (or (cdr (lyskom-string-assoc server known-servers)) server))) ;;; ================================================================ ;;; The LysKOM mode. ;; The LysKOM mode should not be inherited if we create a new buffer ;; and default-major-mode is nil. (put 'lyskom-mode 'mode-class 'special) (defun lyskom-mode () "\\Mode for LysKOM client. Commands: \\[kom-next-command] Do the default action. This can be to read the next text,select next conference with unread texts or whatever the prompt says. \\[kom-go-to-conf] Go to a conference. LysKOM will ask you for a conference and make you a member of it if you are not already. \\[kom-list-conferences] List conferences matching a given string. \\[kom-list-persons] List persons matching a given string. \\[kom-list-news] List the conferences you have unread texts in. \\[kom-go-to-next-conf] Go to the next conference with unread texts. \\[kom-membership] Display a buffer with the list of conferences you are member in. \\[kom-quit] Leave this LysKOM session. \\[kom-who-is-on] Show a list of all the users of lyskom right now. \\[kom-extended-command] Read a command using the minibuffer and execute it. This is another way to give commands. \\[kom-write-text] Start writing a new text. \\[kom-write-comment] Start writing a comment to the last read article. \\[kom-private-answer] Start writing a personal answer to the author of the last read article. \\[kom-send-letter] Start writing a letter to a person or conference. \\[kom-page-next-command] Clear the page and do what \\[kom-next-command] does. \\[kom-line-next-command] Do what \\[kom-next-command] does, but scroll at most 1 line. 0 .. 9 Give a numeric argument to the next command. \\[describe-mode] Display this help text. \\[kom-busy-wait] Put the lyskom-session in wait mode. The next created text with a priority higher than that of the next conference you are going to will be read directly when it is created. \\[kom-set-unread] Mark a number of texts as unread. \\[kom-jump] Skip (mark as read) all the comments to this article recursively. \\[kom-display-time] Show the current date and time. \\[kom-change-presentation] Change your presentation. \\[kom-view] View the specified text. \\[kom-view-commented-text] View the text that the current text comments or is a footnote to. \\[kom-review-presentation] Show the presentation for a person or a conferencce. \\[kom-review-comments] View all comments to the current text. \\[kom-review-tree] View all comments to the current text and step through the tree in depth-first order. \\[kom-find-root-review] View the complete comment tree. \\[kom-find-root] Show the root text of this comment tree. \\[kom-review-by-to] View the last (first or all) article written by named author in a named conference. \\[kom-mark-text] Create a mark on a text. \\[kom-unmark-text] Remove the mark on a text. \\[kom-review-marked-texts] View all text marked with a certain mark. \\[kom-review-all-marked-texts] View all marked text. \\[kom-view-next-new-text] Read the next text from the list of unread. \\[kom-review-next] Continue the viewing. \\[kom-review-stack] Show the stack of things we are viewing. \\[kom-review-clear] Clear the stack of things we are viewing. \\[kom-review-backward] Toggles the read order of reviewed texts. This can only be done when viewing texts with \\[kom-review-by-to], \\[kom-review-marked-texts] and \\[kom-review-all-marked-texts]. \\[kom-status-conf] Show the status of a conference. \\[kom-status-person] Show the status of a person \\[kom-save-text] Save the text you are looking at to a file. \\[kom-get-abuse] Get an insulting text. \\[kom-get-appreciation] Get an encouraging text. \\[kom-add-self] Become a member of a conference. \\[kom-sub-self] Removes you as a member of a conference. All bindings (this is here due to the fact that inconsistensies while developping this package are frequent): \\{lyskom-mode-map} Entry to this mode runs lyskom-mode-hook. Functions and variables beginning with kom- are intended for the user to see, set or call. Functions and variables beginning with lyskom- are not intended for the user to see, set of call." (interactive) (lyskom-clear-vars) (lyskom-mode-name-from-host) (setq mode-line-buffer-identification ; Must start with a string to be handled properly, it seems. (list "" 'mode-line-server-name ": " 'mode-line-conf-name)) (setq major-mode 'lyskom-mode) (setq mode-name "LysKOM") (setq mode-line-process (lyskom-get-string 'mode-line-working)) (use-local-map lyskom-mode-map) (lyskom-set-menus 'lyskom-mode lyskom-mode-map) (run-hooks 'lyskom-mode-hook) (buffer-disable-undo (current-buffer)) (setq buffer-read-only t)) (defun lyskom-clear-vars () "Set up buffer-local vars." (lyskom-save-variables (lyskom-proc lyskom-pers-no lyskom-last-viewed lyskom-unparsed-buffer lyskom-unparsed-marker lyskom-server-info lyskom-server-name) (kill-all-local-variables)) (lyskom-setup-local-variables) (setq lyskom-do-when-done (cons kom-do-when-done kom-do-when-done)) (setq lyskom-output-queues (make-vector 10 nil)) (setq lyskom-collate-table lyskom-default-collate-table) (setq lyskom-char-classes nil) (let ((i 0)) (while (< i 10) (aset lyskom-output-queues i (lyskom-queue-create)) (setq i (1+ i)))) (setq lyskom-pending-calls nil) (lyskom-set-mode-line (lyskom-get-string 'not-present-anywhere))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: reading.el,v 44.22 2004/07/21 11:14:39 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: reading.el ;;;; ;;;; This file contains functions that manage membership and reading ;;;; lists, namely lyskom-membersip lyskom-reading-list and ;;;; lyskom-to-do-list. These are called both from prefetch and from ;;;; startup procedures. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: reading.el,v 44.22 2004/07/21 11:14:39 byers Exp $\n")) (defun lyskom-enter-map-in-to-do-list (map conf-stat membership) "Takes a MAP and enters all its listed text-nos in the conference CONF-STAT. This works by modifying the lyskom-to-do-list which in some cases also means modifying the lyskom-reading-list. The zero text-nos are skipped." (let ((list (lyskom-list-unread map membership)) (mship (lyskom-try-get-membership (conf-stat->conf-no conf-stat)))) (when (and list mship) (read-list-enter-read-info (lyskom-create-read-info 'CONF conf-stat (membership->priority (lyskom-try-get-membership (conf-stat->conf-no conf-stat))) (lyskom-create-text-list list)) lyskom-to-do-list)))) (defun lyskom-sort-to-do-list () "Sort lyskom-to-do-list in order of membership priorities. The priorities for CONF elements are updated to match the membership priorities. Elements that are not of type CONF appear first on the list within their priority. This may not be totally accurate, but it's a reasonable guess." (let ((todo (read-list->all-entries lyskom-to-do-list)) (info nil)) ;; Update the priorities in the read list (while todo (setq info (car todo)) (setq todo (cdr todo)) (when (eq (read-info->type info) 'CONF) (let ((mship (lyskom-get-membership (conf-stat->conf-no (read-info->conf-stat info)) t))) (when mship (set-read-info->priority info (membership->priority mship)))))) ;; Sort the todo list (setq lyskom-to-do-list (cons 'READ-LIST (sort (read-list->all-entries lyskom-to-do-list) 'lyskom-read-info-<))) (lyskom-update-prompt))) (defun lyskom-read-info-< (a b) (cond ((< (read-info->priority a) (read-info->priority b)) nil) ((> (read-info->priority a) (read-info->priority b)) t) ;; Both are confs of equal priority; check position in mship ((and (eq (read-info->type a) 'CONF) (eq (read-info->type b) 'CONF)) (< (lyskom-membership-position (conf-stat->conf-no (read-info->conf-stat a))) (lyskom-membership-position (conf-stat->conf-no (read-info->conf-stat b))))) ;; A is a CONF and B is not; B is greater. ((eq (read-info->type a) 'CONF) nil) ;; Both are not CONF, so A is not less than B (t t))) ;;; ================================================================ ;;; Fundamental membership cache functions (def-komtype mship-list-node (prev next data)) (def-komtype membership-list ((head :automatic nil) (tail :automatic nil) (size :automatic 0))) ;;; (def-komtype smship (id priority position)) ;;; ---------------------------------------------------------------- ;;; INSERTION FUNCTIONS ;;; ;;; There are three functions for inserting memberships into a list. ;;; ;;; Use lyskom-membership-list-insert when inserting memberships in ;;; random order. It uses a heuristic based on the priority of the ;;; membership to determine whether to search from the front of back ;;; of the list. ;;; ;;; Use lyskom-membership-list-append when you know that the position ;;; of the membership is towards the end of the list. ;;; ;;; Use lyskom-membership-list-prepend when you know that the position ;;; of the membership is towards the front of the list. ;;; ;;; ;;; The heuristic is optimized for randomly inserting memberships. If ;;; the list is near-full and a single membership is to be inserted, ;;; other heuristics might perform better. If the approximate position ;;; of the membership is already known, this heuristic is not the best. ;;; (defun lyskom-membership-list-compare-next (mship next &optional after) (and next (or (> (membership->priority (mship-list-node->data next)) (membership->priority mship)) (and (= (membership->priority (mship-list-node->data next)) (membership->priority mship)) (membership->position mship) (if after (>= (membership->position mship) (membership->position (mship-list-node->data next))) (> (membership->position mship) (membership->position (mship-list-node->data next)))))))) (defun lyskom-membership-list-compare-prev (mship prev) (and prev (or (< (membership->priority (mship-list-node->data prev)) (membership->priority mship)) (and (= (membership->priority (mship-list-node->data prev)) (membership->priority mship)) (membership->position mship) (<= (membership->position mship) (membership->position (mship-list-node->data prev))))))) (defun lyskom-membership-list-insert (mship-list mship &optional simulate) "Insert a new membership MSHP into MSHIP-LIST." (if (and (membership-list->head mship-list) (membership-list->tail mship-list) (< (- (membership->priority mship) (membership->priority (mship-list-node->data (membership-list->head mship-list)))) (- (membership->priority (mship-list-node->data (membership-list->tail mship-list))) (membership->priority mship)))) (lyskom-membership-list-append mship-list mship simulate) (lyskom-membership-list-prepend mship-list mship simulate))) (defun lyskom-membership-list-insert-position (mship prev next) "Return position MSHIP should have if inserted between PREV and NEXT. Internal function for lyskom-membership-list-insert." ;; If it already has a position that is between the positions of cur and prev ;; then we do not alter that position. If it has some other position or no ;; position, set its position to the position of cur (which is appropriate ;; when adding a new membership). We do this even if there is room between ;; prev and cur since such a hole probably indicates that we haven't gotten ;; the entire membership from the server -- once we have all memberships there ;; shouldn't be any holes left. (if (or (null (membership->position mship)) (<= (membership->position mship) (if prev (membership->position (mship-list-node->data prev)) -1)) (>= (membership->position mship) (if next (membership->position (mship-list-node->data next)) lyskom-max-int))) (cond (next (membership->position (mship-list-node->data next))) (prev (1+ (membership->position (mship-list-node->data prev)))) (t 0)) (membership->position mship))) (defun lyskom-membership-list-prepend (mship-list mship &optional simulate) "Insert new membership MSHIP into MSHIP-LIST." (let ((cur (membership-list->head mship-list)) (prev nil)) ;; Search for the element in the list at which we want to insert ;; the new membership. (while (lyskom-membership-list-compare-next mship cur) (setq prev cur cur (mship-list-node->next cur))) (if simulate (lyskom-membership-list-insert-position mship prev cur) (let ((new (lyskom-create-mship-list-node prev cur mship))) (set-membership->position mship (lyskom-membership-list-insert-position mship prev cur)) ;; If cur is nil, then we want to insert at the end of the list ;; If prev is nil, then we want to insert at the beginning of the list ;; If both are nil, the list is empty and we are inserting the first element (if prev (set-mship-list-node->next prev new) (set-membership-list->head mship-list new)) (if cur (set-mship-list-node->prev cur new) (set-membership-list->tail mship-list new)) (setq prev new) ;; If the position we chose for the new element collides with the position of ;; the element following it, we adjust the positions of following elements ;; until all elements again have unique positions. (while (and cur (eq (membership->position (mship-list-node->data prev)) (membership->position (mship-list-node->data cur)))) (set-membership->position (mship-list-node->data cur) (1+ (membership->position (mship-list-node->data cur)))) (setq prev cur cur (mship-list-node->next cur))) (set-membership-list->size mship-list (1+ (membership-list->size mship-list))) new)))) (defun lyskom-membership-list-append (mship-list mship &optional simulate) "Like lyskom-insert-membership, but searches from the end of the list" (let ((cur (membership-list->tail mship-list)) (prev nil)) (while (lyskom-membership-list-compare-prev mship cur) (setq prev cur cur (mship-list-node->prev cur))) (if simulate (if (or (null (membership->position mship)) (<= (membership->position mship) (if cur (membership->position (mship-list-node->data cur)) -1)) (>= (membership->position mship) (if prev (membership->position (mship-list-node->data prev)) lyskom-max-int))) (set-membership->position mship (cond (prev (membership->position (mship-list-node->data prev))) (cur (1+ (membership->position (mship-list-node->data cur)))) (t 0)))) (if simulate (lyskom-membership-list-insert-position mship prev cur) (let ((new (lyskom-create-mship-list-node cur prev mship))) (set-membership->position mship (lyskom-membership-list-insert-position mship cur prev)) ;; If cur is nil, then we want to insert at the end of the list ;; If prev is nil, then we want to insert at the beginning of the list ;; If both are nil, the list is empty and we are inserting the first element (if cur (set-mship-list-node->next cur new) (set-membership-list->head mship-list new)) (if prev (set-mship-list-node->prev prev new) (set-membership-list->tail mship-list new)) ;; Set up for scanning back to the end of the list to adjust positions ;; of elements that are after the newly inserted element. (setq prev new cur (mship-list-node->next new)) ;; If the position we chose for the new element collides with the position of ;; the element following it, we adjust the positions of following elements ;; until all elements again have unique positions. (while (and cur (eq (membership->position (mship-list-node->data prev)) (membership->position (mship-list-node->data cur)))) (set-membership->position (mship-list-node->data cur) (1+ (membership->position (mship-list-node->data cur)))) (setq prev cur cur (mship-list-node->next cur))) (set-membership-list->size mship-list (1+ (membership-list->size mship-list))) new))))) (defun lyskom-membership-list-delete (mship-list node) "Remove NODE from MSHIP-LIST" (if (mship-list-node->next node) (set-mship-list-node->prev (mship-list-node->next node) (mship-list-node->prev node)) (set-membership-list->tail mship-list (mship-list-node->prev node))) (if (mship-list-node->prev node) (set-mship-list-node->next (mship-list-node->prev node) (mship-list-node->next node)) (set-membership-list->head mship-list (mship-list-node->next node))) (setq node (mship-list-node->next node)) (while node (set-membership->position (mship-list-node->data node) (1- (membership->position (mship-list-node->data node)))) (setq node (mship-list-node->next node))) (set-membership-list->size mship-list (1- (membership-list->size mship-list)))) (defun lyskom-membership-list-move (mship-list node) "Move the node NODE in MSHIP-LIST to its new position. Returns non-nil value if the membership actually moved." (let* ((prev (mship-list-node->prev node)) (next (mship-list-node->next node)) (mship (mship-list-node->data node)) (moved nil) (new-pos nil)) (cond ((lyskom-membership-list-compare-next mship next t) ; Move right (setq prev nil) (while (lyskom-membership-list-compare-next mship next t) (setq moved t) (setq new-pos (membership->position (mship-list-node->data next))) (set-membership->position (mship-list-node->data next) (1- new-pos)) (setq prev next next (mship-list-node->next next))) (set-membership->position mship new-pos)) ((lyskom-membership-list-compare-prev mship prev) ; Move left (setq next nil) (while (lyskom-membership-list-compare-prev mship prev) (setq moved t) (setq new-pos (membership->position (mship-list-node->data prev))) (set-membership->position (mship-list-node->data prev) (1+ new-pos)) (setq next prev prev (mship-list-node->prev prev))) (set-membership->position mship new-pos)) (t ; Stay in the same place (setq prev (mship-list-node->prev node)) (setq next (mship-list-node->next node)) (setq new-pos (membership->position mship)))) ;; Remove the node from its current position (if (mship-list-node->prev node) (set-mship-list-node->next (mship-list-node->prev node) (mship-list-node->next node)) (set-membership-list->head mship-list (mship-list-node->next node))) (if (mship-list-node->next node) (set-mship-list-node->prev (mship-list-node->next node) (mship-list-node->prev node)) (set-membership-list->tail mship-list (mship-list-node->prev node))) ;; Splice it into the list at the new position (set-mship-list-node->prev node prev) (set-mship-list-node->next node next) (if prev (set-mship-list-node->next prev node) (set-membership-list->head mship-list node)) (if next (set-mship-list-node->prev next node) (set-membership-list->tail mship-list node)) moved )) ;;; ================================================================ ;;; The following functions are concerned with managing the cache (def-kom-var lyskom-mship-cache nil "Membership cache. Do not alter directly." local) (defsubst lyskom-mship-cache-index () (aref lyskom-mship-cache 0)) (defsubst lyskom-mship-cache-data () (aref lyskom-mship-cache 1)) (defun lyskom-mship-cache-create () "Initialize the membership cache to empty." (vector (lyskom-make-hash-table :size 300 :test 'eq) (lyskom-create-membership-list))) (defun lyskom-mship-cache-get (conf-no) "Get the membership for CONF-NO from the membership cache." (lyskom-gethash conf-no (lyskom-mship-cache-index))) (defun lyskom-mship-cache-put (mship) "Add MSHIP to the membership cache." (lyskom-puthash (membership->conf-no mship) (lyskom-membership-list-insert (lyskom-mship-cache-data) mship) (lyskom-mship-cache-index))) (defun lyskom-mship-cache-append (mship) "Add MSHIP to the membership cache." (lyskom-puthash (membership->conf-no mship) (lyskom-membership-list-append (lyskom-mship-cache-data) mship) (lyskom-mship-cache-index))) (defun lyskom-mship-cache-del (conf-no) "Delete CONF-NO from the membership cache." (let ((node (lyskom-mship-cache-get conf-no))) (when node (lyskom-membership-list-delete (lyskom-mship-cache-data) node) (lyskom-remhash conf-no (lyskom-mship-cache-index))))) (defun lyskom-add-memberships-to-membership (memberships) "Adds newly fetched MEMBERSHIPS to the membership list." (lyskom-with-lyskom-buffer (lyskom-traverse mship memberships (unless (lyskom-mship-cache-get (membership->conf-no mship)) (lyskom-mship-cache-append mship))))) (defun lyskom-insert-membership (mship) "Add MSHIP into lyskom-membership, sorted by priority." (lyskom-with-lyskom-buffer (lyskom-mship-cache-put mship) (lp--update-buffer (membership->conf-no mship)) )) (defun lyskom-replace-membership (mship) "Replace the membership MSHIP." (lyskom-with-lyskom-buffer (let ((node (lyskom-mship-cache-get (membership->conf-no mship)))) (set-mship-list-node->data node mship) (if node (when (lyskom-membership-list-move (lyskom-mship-cache-data) node) (lyskom-sort-to-do-list)) (lyskom-mship-cache-put mship))) (lp--update-buffer (membership->conf-no mship)))) (defun lyskom-remove-membership (conf-no) "Remove the membership for CONF-NO from lyskom-membership." (lyskom-with-lyskom-buffer (lyskom-mship-cache-del conf-no) (lp--update-buffer conf-no))) (defun lyskom-membership-position (conf-no) "Return the position of the membership for CONF-NO." (lyskom-with-lyskom-buffer (membership->position (lyskom-get-membership conf-no t)))) (defun lyskom-init-membership () "Initialize membership cache and information." (setq lyskom-mship-cache (lyskom-mship-cache-create))) (defun lyskom-membership-length () "Return the size of the membership list." (membership-list->size (lyskom-mship-cache-data))) (defun lyskom-get-membership (conf-no &optional want-passive) "Return membership for conference CONF-NO. If optional WANT-PASSIVE is non-nil, also return passive memberships. If the membership has not been cached, a blocking call is made to the server to attempt to get it, so this function should not be used from a callback function." (lyskom-with-lyskom-buffer (or (lyskom-try-get-membership conf-no want-passive) (and (not (lyskom-membership-is-read)) (let ((mship (blocking-do 'query-read-texts lyskom-pers-no conf-no t 0))) (when (and mship (lyskom-visible-membership mship)) (lyskom-add-membership mship conf-no)) (when (or want-passive (not (membership-type->passive (membership->type mship)))) mship)))))) (defun lyskom-try-get-membership (conf-no &optional want-passive) "Return membership for conference CONF-NO. If optional WANT-PASSIVE is non-nil, also return passive memberships. This call does not block. If the membership has not been cached, this call will return nil." (lyskom-with-lyskom-buffer (let ((mship (lyskom-mship-cache-get conf-no))) (when (and mship (or want-passive (not (membership-type->passive (membership->type (mship-list-node->data mship)))))) (mship-list-node->data mship))))) (defun lyskom-query-membership-position (priority position) "Return the real position of a membership with PRIORITY and POSITION. The position returned is the position at which the membership would be placed in the membership cache." (let ((mship (lyskom-create-membership position nil nil priority nil nil nil nil nil))) (lyskom-membership-list-insert (lyskom-mship-cache-data) mship t))) ;;; ================================================================ ;;; Testing ;;;(defun lps (l) ;;; (let ((cur (membership-list->head l)) ;;; res) ;;; (while cur ;;; (setq res (cons (cons (smship->id (mship-list-node->data cur)) ;;; (smship->position (mship-list-node->data cur))) ;;; res) ;;; cur (mship-list-node->next cur))) ;;; (nreverse res))) ;;; ;;; ;;; ;;;(progn (setq l (lyskom-create-membership-list)) ;;;(setq a (lyskom-create-smship 'a 255 0)) ;;;(setq b (lyskom-create-smship 'b 100 1)) ;;;(setq c (lyskom-create-smship 'c 100 2)) ;;;(setq d (lyskom-create-smship 'd 100 3)) ;;;(setq e (lyskom-create-smship 'e 50 4)) ;;;(setq f (lyskom-create-smship 'f 50 5)) ;;;(setq g (lyskom-create-smship 'g 20 6)) ;;;(setq h (lyskom-create-smship 'h 1 7))) ;;; ;;;(setq x (lyskom-create-smship 'x 100 nil)) ;;; ;;;(mapcar (lambda (el) (lyskom-membership-list-insert l el)) (list c g f b d a x)) ;; (let ((mx 0) ;; (times nil)) ;; (while (<= mx 500) ;; ; (garbage-collect) ;; (message "%d" mx) ;; (let ((enter-time nil) ;; (exit-time nil) ;; (l (lyskom-create-membership-list)) ;; (i 0) ;; (x 0) ;; (y 0)) ;; (garbage-collect) ;; (setq mx (+ mx 10)) ;; (setq enter-time (current-time)) ;; (while (< i mx) ;; (let* ((val (random mx)) ;; (el (lyskom-create-smship i val (- mx val)))) ;; (lyskom-membership-list-insert l el)) ;; (setq i (1+ i))) ;; (setq exit-time (current-time)) ;; (princ (format "%05d %.8f %.8f %4d %4d\n" ;; mx ;; (elp-elapsed-time enter-time exit-time) ;; (/ (elp-elapsed-time enter-time exit-time) mx) ;; x ;; y)) ;; (sit-for 0) ;; (setq times (cons (cons mx ;; (elp-elapsed-time enter-time exit-time)) times)) ;; )) ;; times) ;; (defun lyskom-map-membership-list (fn list) ;; (let ((cur (membership-list->tail list)) ;; (res nil)) ;; (while cur ;; (setq res (cons (funcall fn (mship-list-node->data cur)) res) ;; cur (mship-list-node->prev cur))) ;; res)) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: internal.el,v 44.11 2004/02/12 21:07:52 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: internal.el ;;;; ;;;; Here are internal functions that handles the different kom-queue ;;;; calls. Add a call, apply the handler when a call is done. ;;;; ;;;; Originally written: ceder ;;;; Completely rewritten: Inge Wallin ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: internal.el,v 44.11 2004/02/12 21:07:52 byers Exp $\n")) ;;;; ================================================================ ;;;; Variables. (defvar lyskom-call-data nil "This is an assoc-list of data for the kom-queues. Each element on the list has the following format: (NAME . KOM-QUEUE) NAME is an atom, the name of the kom-queue. A kom-queue is a way to send questions to the LysKOM server and deal with the replies in a controlled way. KOM-QUEUE is a kom-queue.") (make-variable-buffer-local 'lyskom-call-data) ;;; ================================================================ ;;; Data type kom-queue ;;; ;;; Each kom-queue consists of the following 4 fields: ;;; PENDING - ;;; a list where each element represents a call to a service on ;;; the server, or a call to lyskom-collect, lyskom-use or ;;; lyskom-run. The elements are lists. The first element on each ;;; list is a key to what it represents, as described below. ;;; COLLECT-FLAG - ;;; t means this queue is collecting results for a future ;;; lyskom-use of lyskom-list-use. The results are collected ;;; on collect-queue ;;; COLLECT-QUEUE - ;;; This is where the results described above are collected. ;;; HALTED - ;;; An integer counting the number of times this queue is halted. ;;; A call to lyskom-halt increments this counter, a call to ;;; lyskom-resume decrements it. ;;; ;;; ;;; The items on PENDING is one of the following: ;;; ;;; ('CALL REF-NO PARSER PARSER-DATA HANDLER HANDLER-DATA) ;;; A call that has not yet returned. ;;; ;;; ('PARSED REF-NO RESULT HANDLER HANDLER-DATA) ;;; A call that has returned, but the result can not be ;;; handled until all previous calls has returned. ;;; ;;; ('COLLECT) ;;; Marks the start of a sequence of results that will be ;;; handled by a multi-handler or multi-list-handler. ;;; ;;; ('COLLECT-IGNORE) ;;; Marks the start of a sequence of results that will be ;;; handled by a multi-handler of multi-list-handler with ;;; errors stripped away. ;;; ;;; ('USE MULTI-HANDLER MULTI-HANDLER-DATA) ;;; Marks the end of a sequence. MULTI-HANDLER is called ;;; when all calls before this element have been handled. ;;; MULTI-HANDLER is a function whose first arguments are ;;; the results from calls between previous COLLECT and ;;; this USE. MULTI-HANDLER-DATA is optional. If it ;;; exists it is a list of more arguments to send to ;;; MULTI-HANDLER. ;;; ;;; ('LIST-USE MULTI-HANDLER MULTI-HANDLER-DATA) ;;; Marks the end of a sequence. MULTI-HANDLER is called ;;; when all calls before this element have been handled. ;;; MULTI-HANDLER is a function whose first argument is a ;;; list of all results from calls between previous ;;; COLLECT and this LIST-USE. MULTI-HANDLER-DATA is ;;; optional. If it exists it is a list of more arguments ;;; to send to MULTI-HANDLER. ;;; ;;; ('RUN FUNCTION FUNCTION-ARGS) ;;; Run FUNCTION when all calls before this have been handled. ;;; ;;; (defun kom-queue-create () "Creates a new instance of an empty kom-queue." (vector (lyskom-queue-create) nil (lyskom-queue-create) 0)) (defun kom-queue->pending (queue) "Returns the pending field of the kom-queue QUEUE." (elt queue 0)) (defun kom-queue->collect-flag (queue) "Returns the collect-flag field of the kom-queue QUEUE." (elt queue 1)) (defun kom-queue->collect-queue (queue) "Returns the collect-queue field of the kom-queue QUEUE." (elt queue 2)) (defun set-kom-queue-collect-flag (queue new-val) "Set the collect-flag field of the kom-queue QUEUE to NEW-VAL." (aset queue 1 new-val)) (defun kom-queue-halt (queue) "Halts the kom-queue QUEUE." (aset queue 3 (1+ (elt queue 3)))) (defun kom-queue-resume (queue) "Resume execution on the kom-queue QUEUE." (if (eq (elt queue 3) 0) (signal 'lyskom-internal-error (list "kom-queue-resume called on an unhalted queue: " queue)) (aset queue 3 (1- (elt queue 3))))) (defun kom-queue-is-halted (queue) "Return t if the kom-queue QUEUE is halted at least once." (> (elt queue 3) 0)) ;;; ================================================================ ;;; Entry points to this communication packet. (defun lyskom-collect (kom-queue) "Collect the results of future calls via KOM-QUEUE. The results of the calls will be available to the multi-handler. See lyskom-use and lyskom-list-use." (lyskom-call-add kom-queue 'COLLECT)) (defun lyskom-collect-ignore-err (kom-queue) "Collect the result of future calls via KOM-QUEUE. The result of the calls will be available to the multi-handler with the calls producing errors stripped." (lyskom-call-add kom-queue 'COLLECT-IGNORE)) (defun lyskom-use (kom-queue multi-handler &rest multi-handler-data) "Use the previously collected results from calls to the server. Args: KOM-QUEUE MULTI-HANDLER &rest MULTI-HANDLER-DATA MULTI-HANDLER is a function that is called when all previous results have been handled. MULTI-HANDLER-DATA is a list of additional arguments the multi-handler wants. See also lyskom-list-use." (lyskom-call-add kom-queue 'USE multi-handler multi-handler-data) (lyskom-check-call kom-queue)) (defun lyskom-list-use (kom-queue multi-handler &rest multi-handler-data) "Use the previously collected results from calls to the server. Args: KOM-QUEUE MULTI-HANDLER &rest MULTI-HANDLER-DATA MULTI-HANDLER is a function that is called when all previous results have been handled. The first argument is a list of the results. MULTI-HANDLER-DATA is a list of additional arguments the multi-handler wants. The difference between lyskom-use and lyskom-list-use is the way the MULTI-HANDLER receives the data. lyskom-list-use sends them as a list, lyskom-use as different parameters." (lyskom-call-add kom-queue 'LIST-USE multi-handler multi-handler-data) (lyskom-check-call kom-queue)) (defun lyskom-run (kom-queue function &rest function-args) "Call a function when all calls have been handled. Args: KOM-QUEUE FUNCTION &rest FUNCTION-ARGS Register a FUNCTION that shall be called with FUNCTION-ARGS when all previous calls to the server via KOM-QUEUE have been handled." (lyskom-call-add kom-queue 'RUN function function-args) (lyskom-check-call kom-queue)) (defun lyskom-halt (queue-name) "Prohibit execution of handlers on QUEUE-NAME. The execution will resume when (lyskom-resume KOM-QUEUE) is called." (let ((queue-pair (assq queue-name lyskom-call-data))) (if (null queue-pair) (setq queue-pair (lyskom-add-new-queue queue-name))) (kom-queue-halt (cdr queue-pair)))) (defun lyskom-resume (kom-queue) "Resume execution of waiting handlers on KOM-QUEUE. See documentation for lyskom-halt." (let ((queue (assq kom-queue lyskom-call-data))) (cond ((null queue) ;A new kom-queue? (signal 'lyskom-internal-error (list "lyskom-resume called on an unused queue:" kom-queue))) ((kom-queue-is-halted (cdr queue)) ;A halted queue? (kom-queue-resume (cdr queue)) ;Resume execution on the queue. (lyskom-check-call kom-queue)) ;Run any pending handlers. (t ;The queue was not halted. This (signal 'lyskom-internal-error ;is an error. (list "lyskom-resume:" kom-queue "(not halted)")))))) (defun lyskom-call (kom-queue ref-no handler handler-data parser &rest parser-data) "Add information about a call that has not yet returned to kom-queue. Arguments: KOM-QUEUE REF-NO HANDLER HANDLER-DATA PARSER &rest PARSER-DATA." (lyskom-call-add kom-queue 'CALL ref-no parser parser-data handler handler-data)) (defun lyskom-fake-call (kom-queue ref-no handler handler-data) "Add information about a call that will not return from the server, but will be filled in by some other function." (lyskom-call-add kom-queue 'CALL ref-no nil nil handler handler-data)) (defun lyskom-complete-call (kom-queue ref-no result) "Force a call placed on KOM-QUEUE with reference number REF-NO to return RESULT. This should only be used to complete calls placed on the queue using lyskom-fake-call, or the parser might get confused." (let ((call-info (lyskom-locate-ref-no kom-queue ref-no))) (if call-info (progn (lyskom-tr-call-to-parsed call-info result) (lyskom-check-call kom-queue))))) (defun lyskom-cancel-calls (ref-nos) "Cancel the calls in the list REF-NOS. Calls that have been sent to the server will have their callbacks canceled, but as they have been sent, the client must wait for them to complete in some way." (let ((unsent nil)) (lyskom-traverse queue lyskom-output-queues (lyskom-traverse ref-no ref-nos (when (assq ref-no (car (cdr queue))) (setq unsent (cons ref-no unsent))))) ;; (lyskom-format-insert "REF-NOS\n") ;; (lyskom-format-insert " %#1s\n" (format "%S" ref-nos)) ;; (lyskom-format-insert "UNSENT\n") ;; (lyskom-format-insert " %#1s\n" (format "%S" unsent)) (lyskom-traverse queue lyskom-output-queues (lyskom-queue-remove-matching queue (lambda (el) (memq (car el) unsent)))) (lyskom-traverse queue lyskom-call-data (lyskom-queue-remove-matching (kom-queue->pending (cdr queue)) (lambda (el) (or (and (eq (car el) 'CALL) (memq (car (cdr el)) unsent)) (and (eq (car el) 'PARSED) (memq (car (cdr el)) ref-nos))))) (lyskom-traverse call-data (car (cdr (kom-queue->pending (cdr queue)))) (when (and (eq (car call-data) 'CALL) (memq (car (cdr call-data)) ref-nos)) ;; (lyskom-format-insert "Canceling callback %#1d\n" (car (cdr call-data))) (setcdr call-data (list (elt (cdr call-data) 0) ; ref-no (elt (cdr call-data) 1) ; parser (elt (cdr call-data) 2) ; parser-data nil ; handler, then handler-data nil))))) (lyskom-check-output-queues))) ;;;; ================================================================ ;;;; Internal functions. (defun lyskom-add-new-queue (queue-name) "Add QUEUE-NAME to lyskom-call-data as an empty queue. Return a dotted pair consisting of the QUEUE-NAME and the new queue." (let ((new-queue-list (list (cons queue-name (kom-queue-create))))) (if (null lyskom-call-data) (setq lyskom-call-data new-queue-list) (nconc lyskom-call-data new-queue-list)) (car new-queue-list))) (defun lyskom-set-queue-priority (queue-name priority) (put queue-name 'lyskom-queue-priority priority)) (defun lyskom-queue-priority (queue-name) (or (get queue-name 'lyskom-queue-priority) 0)) (defun lyskom-call-add (queue-name type &rest data) "Add an entry to the kom-queue QUEUE-NAME. The entry is of type TYPE and third argument DATA contains the rest of the necessary data." (let ((queue (assoc queue-name lyskom-call-data))) (if (null queue) (setq queue (lyskom-add-new-queue queue-name))) (lyskom-queue-enter (kom-queue->pending (cdr queue)) (cons type data)))) (defun lyskom-send-packet (kom-queue string) "Send a packet to the server. Add info on lyskom-pending-calls. Update lyskom-ref-no. Args: KOM-QUEUE STRING." ;; Queue it (lyskom-queue-enter (aref lyskom-output-queues (lyskom-queue-priority kom-queue)) (cons lyskom-ref-no string)) (setq lyskom-pending-calls (cons (cons lyskom-ref-no kom-queue) lyskom-pending-calls)) (setq lyskom-ref-no (1+ lyskom-ref-no)) (when (< lyskom-ref-no 0) (setq lyskom-ref-no 1)) ;; Send something from the output queues (lyskom-check-output-queues)) (defun lyskom-check-output-queues () "Check for pending calls to the server. Send calls from queues with higher priority first, and make sure that at most lyskom-max-pending-calls are sent to the server at the same time." (catch 'done (let ((i 9)) (while (and lyskom-ok-to-send-new-calls (< lyskom-number-of-pending-calls lyskom-max-pending-calls)) (while (lyskom-queue-isempty (aref lyskom-output-queues i)) (-- i) (if (< i 0) (throw 'done nil))) (let ((entry (lyskom-queue-delete-first (aref lyskom-output-queues i)))) (++ lyskom-number-of-pending-calls) (lyskom-process-send-string lyskom-proc (concat (number-to-string (car entry)) (cdr entry) "\n"))))))) (defun lyskom-decrease-pending-calls () "A reply has come. Send a pending call or decrease lyskom-number-of-pending-calls." (-- lyskom-number-of-pending-calls) (if (< lyskom-number-of-pending-calls 0) (setq lyskom-number-of-pending-calls 0)) (lyskom-check-output-queues)) (defun lyskom-process-send-string (process string) "Send PROCESS the contents of STRING. STRING is split in several parts if the operating system can't deal with big strings." (let ((tries 0)) (while (condition-case err (progn (lyskom-process-send-string-2 process string) nil) (file-error (if lyskom-debug-communications-to-buffer (lyskom-debug-insert process "Error: " (format "%s" err)) ;;; (save-excursion ;;; (set-buffer (get-buffer-create ;;; lyskom-debug-communications-to-buffer-buffer)) ;;; (save-excursion ;;; (goto-char (point-max)) ;;; (insert "\n" ;;; (format "%s" process) ;;; (concat "Error: " (format "%s" err)))) ;;; (set-buffer (process-buffer process))) ) (cond ((and (string= "writing to process" (car (cdr err))) (or (string= "message too long" (car (cdr (cdr err)))) (string= "no more processes" (car (cdr (cdr err))))) (> lyskom-max-packet-size 1)) ;; Seems to be impossible to write too long strings to TCP/IP. ;; This happens on a Sequence Balance with packets longer than ;; 2048 bytes. Decrease lyskom-max-packet-size and retry. (setq lyskom-max-packet-size (/ lyskom-max-packet-size 2)) t) ((and (string= "writing to process" (car (cdr err))) (string= "host is unreachable" (car (cdr (cdr err))))) ;; The net is currently shaky. We try again in a while. (lyskom-message "%s" (lyskom-format 'shaky-tcp (make-string (++ tries) ?.))) (sit-for 4) (lyskom-message "%s" (lyskom-get-string 'retrying-tcp)) t) (t ;; It was some unknown file-error. Pass it down. (signal (car err) (cdr err))))))))) (defun lyskom-process-send-string-2 (process string) "Send PROCESS the contents of STRING as input. PROCESS may be a process name. At most lyskom-max-packet-size bytes is sent with each packet. If STRING is longer it is splitted." (cond ((<= (length string) lyskom-max-packet-size) (process-send-string process (progn (if lyskom-debug-communications-to-buffer (lyskom-debug-insert process "To " string)) string))) (t (let ((i 0)) (while (< i (length string)) (process-send-string process (let ((string (substring string i (min (length string) (+ i lyskom-max-packet-size))))) (if lyskom-debug-communications-to-buffer (save-excursion (set-buffer (get-buffer-create lyskom-debug-communications-to-buffer-buffer)) (save-excursion (goto-char (point-max)) (insert "\n" "To " process ": ")) (set-buffer (process-buffer process)))) string)) (setq i (+ i lyskom-max-packet-size))))))) (defun lyskom-check-call (queue-name) "Check lyskom-call-data and call handlers, multi-handlers and functions. Args: QUEUE-NAME. HALTED -> stop CALL -> stop PARSED -> handle -> -> collect-flag? 'COLLECT -> add on temporary resultlist. 'COLLECT-IGNORE -> add on temporary resultlist if not error. no -> delete from lyskom-call-data. COLLECT -> collect-flag? yes -> error! no -> set collect-flag. COLLECT-IGNORE -> collect-flag? yes -> error! no -> set collect-flag. USE -> call handler. Delete previous parts. LIST-USE -> call handler. Delete previous parts. RUN -> call function. Delete. Not allowed inside COLLECT/USE." (let* ((queue (cdr-safe (assoc queue-name lyskom-call-data))) (type nil) (first-pending (lyskom-queue->first (kom-queue->pending queue)))) (while (and queue (not (or (kom-queue-is-halted queue) (lyskom-queue-isempty (kom-queue->pending queue)) (eq (car first-pending) 'CALL)))) (setq type (car first-pending)) (cond ((eq type 'PARSED) (kom-queue-halt queue) (unwind-protect (lyskom-apply-handler first-pending) (kom-queue-resume queue)) (if (or (eq (kom-queue->collect-flag queue) 'COLLECT) (and (eq (kom-queue->collect-flag queue) 'COLLECT-IGNORE) (car (cdr (cdr first-pending))))) (lyskom-queue-enter (kom-queue->collect-queue queue) (car (cdr (cdr first-pending)))))) ((eq type 'COLLECT) (if (kom-queue->collect-flag queue) (signal 'lyskom-internal-error '("lyskom-check-call COLLECT.")) (set-kom-queue-collect-flag queue 'COLLECT) (lyskom-queue-make-empty (kom-queue->collect-queue queue)))) ((eq type 'COLLECT-IGNORE) (if (kom-queue->collect-flag queue) (signal 'lyskom-internal-error '("lyskom-check-call COLLECT-IGNORE.")) (set-kom-queue-collect-flag queue 'COLLECT-IGNORE) (lyskom-queue-make-empty (kom-queue->collect-queue queue)))) ((eq type 'USE) (if (not (kom-queue->collect-flag queue)) (signal 'lyskom-internal-error '("lyskom-check-call USE."))) (kom-queue-halt queue) (unwind-protect (lyskom-apply-multi-handler first-pending (lyskom-queue->all-entries (kom-queue->collect-queue queue))) (kom-queue-resume queue)) (set-kom-queue-collect-flag queue nil)) ((eq type 'LIST-USE) (if (not (kom-queue->collect-flag queue)) (signal 'lyskom-internal-error '("lyskom-check-call LIST-USE."))) (kom-queue-halt queue) (unwind-protect (lyskom-apply-multi-list-handler first-pending (lyskom-queue->all-entries (kom-queue->collect-queue queue))) (kom-queue-resume queue)) (set-kom-queue-collect-flag queue nil)) ((eq type 'RUN) (if (kom-queue->collect-flag queue) (signal 'lyskom-internal-error '("lyskom-check-call RUN."))) (kom-queue-halt queue) (unwind-protect (lyskom-apply-function first-pending) (kom-queue-resume queue))) (t (signal 'lyskom-internal-error (list 'lyskom-check-call "unknown key:" (car first-pending))))) (lyskom-queue-delete-first (kom-queue->pending queue)) (setq first-pending (lyskom-queue->first (kom-queue->pending queue)))))) ;;; Quit is NOT ok to press while the handler is running. inhibit-quit ;;; should be t when these are called. (defun lyskom-apply-handler (pending) "Apply a handler. Args: PENDING. PENDING is an entry of the list as described in documentation for the variable lyskom-call-data. The car on the list must be a PARSED: ('PARSED RESULT HANDLER HANDLER-DATA)" (if (car (cdr (cdr (cdr pending)))) (apply (car (cdr (cdr (cdr pending)))) ;Handler (car (cdr (cdr pending))) ;Result (car (cdr (cdr (cdr (cdr pending)))))))) ;Handler-data (defun lyskom-apply-multi-handler (pending result-list) "Apply a handler for a lyskom-collect - lyskom-use construct." (apply (car (cdr pending)) ;Multi-handler (nconc result-list (car (cdr (cdr pending)))))) ;Multi-handler-data (defun lyskom-apply-multi-list-handler (pending result-list) "Apply a handler for a lyskom-collect - lyskom-list-use construct." (apply (car (cdr pending)) ;Multi-handler (cons result-list (car (cdr (cdr pending)))))) ;Multi-handler-data (defun lyskom-apply-function (pending) (setcar pending 'HALTED) (apply (car (cdr pending)) ;Function. (car (cdr (cdr pending))))) ;Function-args. ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: services.el,v 44.49 2004/10/28 18:51:55 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; This file contains functions for sending requests to the server ;;;; and parsing the result. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: services.el,v 44.49 2004/10/28 18:51:55 byers Exp $\n")) ;;; ================================================================ ;;; Macro for defining services ;;; (defmacro def-kom-service (name args &rest body) ;;; "Create an initiate call. NAME and ARGS are the name and arguments for the call. ;;; If BODY starts with a string, that is the documentation string. ;;; If BODY consists of (call N PARSER), generate a simple call ;;; for RPC number N, and parse the result with PARSER." ;;; (let ((function-name (intern (concat "initiate-" (symbol-name name)))) ;;; (doc-string nil) ;;; (auto-call nil) ;;; (buffer-save (intern (format "initiate-%s-saved-buffer" name)))) ;;; (when (stringp (car body)) ;;; (setq doc-string (car body)) ;;; (setq body (cdr body))) ;;; ;;; (when (and (listp (car body)) ;;; (eq 'call (car (car body)))) ;;; (setq auto-call (car body)) ;;; (setq body (cdr body))) ;;; ;;; (` (defun (, function-name) (kom-queue handler (,@ args) &rest data) ;;; (, ;;; (or doc-string ;;; (format "Initiate %S on server\nArgs: KOM-QUEUE HANDLER %s &rest DATA" ;;; name (mapconcat ;;; (function ;;; (lambda (x) ;;; (format "%s" (upcase (symbol-name x))))) ;;; args ;;; " ")))) ;;; (let (((, buffer-save) (current-buffer))) ;;; (unwind-protect ;;; (progn ;;; (and (not lyskom-output-queues) (set-buffer lyskom-buffer)) ;;; (,@ (if auto-call ;;; (` ((lyskom-call kom-queue lyskom-ref-no handler data (quote (, (elt auto-call 2)))) ;;; (lyskom-send-packet kom-queue (lyskom-format-objects (, (elt auto-call 1)) (,@ args))))) ;;; body))) ;;; (set-buffer (, buffer-save)))))))) (defmacro lyskom-server-call (&rest body) "Macro to protect initiate-somethings from being called in the wrong buffer." (` (let ((initiate-something-saved-buffer (current-buffer))) (unwind-protect (prog2 (or lyskom-output-queues (set-buffer lyskom-buffer)) lyskom-ref-no (,@ body)) (set-buffer initiate-something-saved-buffer))))) (put 'lyskom-server-call 'lisp-indent-function 0) (put 'lyskom-server-call 'edebug-form-spec t) ;;; ================================================================ ;;; Requests for services (defun initiate-login-old (kom-queue handler pers-no password &rest data) "Log in on server. Args: KOM-QUEUE HANDLER PERS-NO PASSWORD &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 0 pers-no password)))) (defun initiate-login (kom-queue handler pers-no password status &rest data) "Log in on server. Args: KOM-QUEUE HANDLER PERS-NO PASSWORD STATUS &rest DATA. Status is 0 for visible login and 1 for invisible login." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 62 pers-no password status)))) (defun initiate-logout (kom-queue handler &rest data) "Log out from server. Args: KOM-QUEUE HANDLER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 1)))) (defun initiate-pepsi (kom-queue handler conf-no &rest data) "Change working conference. Args: KOM-QUEUE HANDLER CONF-NO &rest DATA." (lyskom-server-call (let ((mship (lyskom-try-get-membership conf-no t))) (when mship (set-membership->last-time-read mship (lyskom-current-client-time)))) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 2 conf-no)))) (defun initiate-change-name (kom-queue handler conf-no new-name &rest data) "Change the name of a conference. Args: KOM-QUEUE HANDLER CONF-NO NEW-NAME &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 3 conf-no new-name)))) (defun initiate-change-what-i-am-doing (kom-queue handler what &rest data) "Tell server what you are doing. Args: KOM-QUEUE HANDLER WHAT &rest DATA. WHAT is a string." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 4 what)))) (defun initiate-create-person (kom-queue handler name password pers-flags aux-items &rest data) "Create a new person. Args: KOM-QUEUE HANDLER NAME PASSWORD &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (if (lyskom-have-call 89) (lyskom-send-packet kom-queue (lyskom-format-objects 89 name password pers-flags (cons 'LIST aux-items))) (lyskom-send-packet kom-queue (lyskom-format-objects 5 name password))))) ;;; Call 6 is get-person-stat-old, and is obsoleted by call 49. (defun initiate-set-priv-bits (kom-queue handler pers-no priv-bits &rest data) "Set priv-bits of a person. Args: KOM-QUEUE HANDLER PERS-NO PRIV-BITS &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 7 pers-no priv-bits)))) (defun initiate-set-passwd (kom-queue handler pers-no old-pw new-pw &rest data) "Set the password of a person. Args: KOM-QUEUE HANDLER PERS-NO OLD-PW NEW-PW &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 8 pers-no old-pw new-pw)))) ;;; ;;; This function has a ridiculous name! It ought to be called ;;; get-membership. Unfortunately this name is already taken ;;; by another call. ;;; (defun initiate-query-read-texts (kom-queue handler pers-no conf-no want-read-ranges max-ranges &rest data) "Get a membership struct describing the membership of PERS-NO in CONF-NO. Args: KOM-QUEUE HANDLER PERS-NO CONF-NO &rest DATA" (lyskom-server-call (cond ((lyskom-have-call 107) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-11) (lyskom-send-packet kom-queue (lyskom-format-objects 107 pers-no conf-no want-read-ranges max-ranges))) ((lyskom-have-call 98) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-10) (lyskom-send-packet kom-queue (lyskom-format-objects 98 pers-no conf-no))) (t (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-old) (lyskom-send-packet kom-queue (lyskom-format-objects 9 pers-no conf-no)))))) (defun initiate-create-conf (kom-queue handler conf-name conf-type aux-items &rest data) "Add a member to a conference. Args: KOM-QUEUE HANDLER CONF-NAME CONF-TYPE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (if (lyskom-have-call 88) (lyskom-send-packet kom-queue (lyskom-format-objects 88 conf-name conf-type (cons 'LIST aux-items))) (lyskom-send-packet kom-queue (lyskom-format-objects 10 conf-name conf-type))))) (defun initiate-delete-conf (kom-queue handler conf-no &rest data) "Delete a conference. Args: KOM-QUEUE HANDLER CONF-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 11 conf-no)))) (defun initiate-lookup-name (kom-queue handler name &rest data) "See what conferences match NAME. Args: KOM-QUEUE HANDLER NAME &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-conf-list) (lyskom-send-packet kom-queue (lyskom-format-objects 12 name)))) ;;; Call 13 is get-conf-stat-old, which is obsoleted by 50. (defun initiate-add-member (kom-queue handler conf-no pers-no priority where type &rest data) "Add a member to a conference. Args: KOM-QUEUE HANDLER CONF-NO PERS-NO PRIORITY WHERE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (if (lyskom-have-call 100) (lyskom-send-packet kom-queue (lyskom-format-objects 100 conf-no pers-no priority where type)) (lyskom-send-packet kom-queue (lyskom-format-objects 14 conf-no pers-no priority where))))) (defun initiate-sub-member (kom-queue handler conf-no pers-no &rest data) "Subtract a member from a conference. Args: KOM-QUEUE HANDLER CONF-NO PERS-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 15 conf-no pers-no)))) (defun initiate-set-presentation (kom-queue handler conf-no text-no &rest data) "Set presentation of a conference. Args: KOM-QUEUE HANDLER CONF-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 16 conf-no text-no)))) (defun initiate-set-conf-motd (kom-queue handler conf-no text-no &rest data) "Set motd of a conference. Args: KOM-QUEUE HANDLER CONF-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 17 conf-no text-no)))) (defun initiate-set-supervisor (kom-queue handler conf-no admin &rest data) "Set supervisor of a conference. Args: KOM-QUEUE HANDLER CONF-NO ADMIN &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 18 conf-no admin)))) (defun initiate-set-permitted-submitters (kom-queue handler conf-no perm-sub &rest data) "Set permitted submitters of a conference. Args: KOM-QUEUE HANDLER CONF-NO PERM-SUB &rest DATA. PERM-SUB is a conference number. All members in that conference might write texts in CONF-NO. If PERM-SUB is zero everyone is allowed to write texts in CONF-NO." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 19 conf-no perm-sub)))) (defun initiate-set-super-conf (kom-queue handler conf-no super-conf &rest data) "Set superconference of a conference. Args: KOM-QUEUE HANDLER CONF-NO SUPER-CONF &rest DATA. Unauthorized attempts to write texts to CONF-NO will bounce to SUPER-CONF." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 20 conf-no super-conf)))) (defun initiate-set-conf-type (kom-queue handler conf-no conf-type &rest data) "Set type of a conference. Args: KOM-QUEUE HANDLER CONF-NO CONF-TYPE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 21 conf-no conf-type)))) (defun initiate-set-garb-nice (kom-queue handler conf-no garb-nice &rest data) "Set garb-nice of a conference. Args: KOM-QUEUE HANDLER CONF-NO GARB-NICE &rest DATA. Texts in CONF-NO will live approximately GARB-NICE days." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 22 conf-no garb-nice)))) (defun initiate-get-marks (kom-queue handler &rest data) "Get all marked texts. Args: KOM-QUEUE HANDLER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-mark-list) (lyskom-send-packet kom-queue (lyskom-format-objects 23)))) (defun initiate-mark-text (kom-queue handler text-no mark-type &rest data) "Mark a text. Args: KOM-QUEUE HANDLER TEXT-NO MARK-TYPE &rest DATA. MARK-TYPE is currently a number, but this should maybe be changed (internally in the elisp-klient) to something similar to a conf-type (with several bits that are 't' or 'nil' that is)." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects (if (lyskom-have-call 72) 72 24) text-no mark-type)))) (defun initiate-unmark-text (kom-queue handler text-no &rest data) "Unmark a text. Args: KOM-QUEUE HANDLER TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (if (lyskom-have-call 73) (lyskom-send-packet kom-queue (lyskom-format-objects 73 text-no))) (lyskom-send-packet kom-queue (lyskom-format-objects 24 text-no 0)))) (defun initiate-get-text (kom-queue handler text-no &rest data) "Get text from LysKOM server. Args: KOM-QUEUE HANDLER TEXT-NO &rest DATA." (lyskom-server-call (let ((text (cache-get-text text-no))) (cond ((null text) ;Cached info? (lyskom-call kom-queue ;No, ask the server. lyskom-ref-no handler data 'lyskom-parse-text text-no) ;(princ text-no (get-buffer-create "text"))+++ ;(terpri (get-buffer-create "text")) (lyskom-send-packet kom-queue (lyskom-format-objects 25 text-no 0 lyskom-max-int))) (t ;Cached info. (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) text handler data) (lyskom-check-call kom-queue)))))) (defun initiate-get-text-stat (kom-queue handler text-no &rest data) "Get text-stat from LysKOM server. Args: KOM-QUEUE HANDLER TEXT-NO &rest DATA." (lyskom-server-call (let ((text-stat (cache-get-text-stat text-no))) (cond ((null text-stat) ;Cached info? (lyskom-call kom-queue ;No, ask the server. lyskom-ref-no handler data (if (lyskom-have-call 90) 'lyskom-parse-text-stat 'lyskom-parse-text-stat-old) text-no) ;;(princ text-no (get-buffer-create "text-stat"))+++ ;;(terpri (get-buffer-create "text-stat")) (lyskom-send-packet kom-queue (lyskom-format-objects (if (lyskom-have-call 90) 90 26) text-no))) (t ;Cached info. (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) text-stat handler data) (lyskom-check-call kom-queue)))))) (defun initiate-mark-as-read (kom-queue handler conf-no text-list &rest data) "Mark all texts in TEXT-LIST as read in CONF-NO. Args: CONF-NO TEXT-LIST." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 27 conf-no (cons 'LIST text-list))))) (defun initiate-create-text (kom-queue handler message misc-list aux-items &rest data) "Create a new text. Args: KOM-QUEUE HANDLER MESSAGE MISC-LIST AUX-ITEMS &rest DATA. MESSAGE is a string. MISC-LIST should be created by lyskom-create-misc-list." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (if (lyskom-have-call 86) (lyskom-send-packet kom-queue (lyskom-format-objects 86 (cons 'STRING message) misc-list (cons 'LIST aux-items))) (lyskom-send-packet kom-queue (lyskom-format-objects 28 (cons 'STRING message) misc-list))))) (defun initiate-delete-text (kom-queue handler text-no &rest data) "Delete a text. Args: KOM-QUEUE HANDLER TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 29 text-no)))) (defun initiate-add-recipient (kom-queue handler text-no conf-no type &rest data) "Add a recipient to a text. Args: KOM-QUEUE HANDLER TEXT-NO CONF-NO TYPE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 30 text-no conf-no (cond ((eq type 'RECPT) 0) ((eq type 'CC-RECPT) 1) ((eq type 'BCC-RECPT) (if (lyskom-have-feature bcc-misc) 15 1))))))) (defun initiate-sub-recipient (kom-queue handler text-no conf-no &rest data) "Subtract a recipient from a text. Args: KOM-QUEUE HANDLER TEXT-NO CONF-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 31 text-no conf-no)))) (defun initiate-add-comment (kom-queue handler comment-text-no text-no &rest data) "Add a comment to a text. Args: KOM-QUEUE HANDLER COMMENT-TEXT-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 32 comment-text-no text-no)))) (defun initiate-sub-comment (kom-queue handler comment-text-no text-no &rest data) "Subtract a comment from a text. Args: KOM-QUEUE HANDLER COMMENT-TEXT-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 33 comment-text-no text-no)))) (defun initiate-get-map (kom-queue handler conf-no first-local no-of-texts &rest data-list) "Get mapping from local to global text-nos for CONF-NO from server. Args: KOM-QUEUE HANDLER CONF-NO FIRST-LOCAL NO-OF-TEXTS DATA-LIST. Use z-initiate-get-map instead. This function has severe performance losses with big maps." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data-list 'lyskom-parse-map) (lyskom-send-packet kom-queue (lyskom-format-objects 34 conf-no first-local no-of-texts)))) (defun z-initiate-get-map (kom-queue handler conf-no first-local no-of-texts &rest data) "Get mapping from local to global text-nos for CONF-NO from server. Args: KOM-QUEUE HANDLER CONF-NO FIRST-LOCAL NO-OF-TEXTS &rest DATA. This function will automatically split fetching of big maps to small chunks of lyskom-fetch-map-nos texts/chunk if KOM-QUEUE is not already used to collect a result. This currently gives a big performance gain. Unfortunately it is impossible (or at least very hard) to do the same thing when a collect is in progress. This will of course be fixed in protocol B." (lyskom-server-call (cond ((kom-queue->collect-flag (cdr-safe (assq kom-queue lyskom-call-data))) ;; Use oldstyle single big map. Sorry. (apply 'initiate-get-map kom-queue handler conf-no first-local no-of-texts data)) (t ;; You win. (initiate-get-map kom-queue 'lyskom-receive-partial-map conf-no first-local lyskom-fetch-map-nos (+ lyskom-fetch-map-nos first-local) (- no-of-texts lyskom-fetch-map-nos) conf-no nil kom-queue data handler))))) (defun lyskom-receive-partial-map (map first-local no-of-texts conf-no map-so-far kom-queue data-list handler) "Receive a partial map and start fetching a new chunk." (lyskom-server-call (let ((map-list (nconc map-so-far (list map)))) (if (<= no-of-texts 0) (apply handler (apply 'lyskom-map-concat map-list) data-list) (initiate-get-map kom-queue 'lyskom-receive-partial-map conf-no first-local lyskom-fetch-map-nos (+ lyskom-fetch-map-nos first-local) (- no-of-texts lyskom-fetch-map-nos) conf-no map-list kom-queue data-list handler))))) (defun initiate-get-time (kom-queue handler &rest data) "Get time from server. Args: KOM-QUEUE HANDLER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-time) (lyskom-send-packet kom-queue (lyskom-format-objects 35)))) (defun initiate-get-server-info (kom-queue handler &rest data) "Get info about the server" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data (if (lyskom-have-call 94) 'lyskom-parse-server-info 'lyskom-parse-server-info-old)) (lyskom-send-packet kom-queue (lyskom-format-objects (if (lyskom-have-call 94) 94 36))))) (defun initiate-add-footnote (kom-queue handler footnote-text-no text-no &rest data) "Add a footnote to a text. Args: KOM-QUEUE HANDLER FOOTNOTE-TEXT-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 37 footnote-text-no text-no)))) (defun initiate-sub-footnote (kom-queue handler footnote-text-no text-no &rest data) "Subtract a footnote from a text. Args: KOM-QUEUE HANDLER FOOTNOTE-TEXT-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 38 footnote-text-no text-no)))) ;;; Call 39, who-is-on-old, is obsoleted by call 63. (defun initiate-set-unread (kom-queue handler conf-no no-of-unread &rest data) "Set number of unread texts in a certain conference. Args: KOM-QUEUE HANDLER CONF-NO NO-OF-UNREAD &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 40 conf-no no-of-unread)))) (defun initiate-set-motd-of-lyskom (kom-queue handler text-no &rest data) "Set message of the day of LysKOM. Args: KOM-QUEUE HANDLER TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 41 text-no)))) (defun initiate-enable (kom-queue handler level &rest data) "Set security level. Args: KOM-QUEUE HANDLER LEVEL &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 42 level)))) ;;; Call 43 is sync. Starting with version 1.9 of lyskomd it is a ;;; privileged operation, so there is no harm in having the function ;;; easily available any more. (defun initiate-sync (kom-queue handler &rest data) "Sync the LysKOM datbase. This is a prioritized call." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 43)))) ;;; Call 44 is shutdown. Use 'kill -HUP' instead. (defun initiate-shutdown (kom-queue handler parameter &rest data) "Shutdown the server. Args: KOM-QUEUE HANDLER PARAMETER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 44 parameter)))) (defun initiate-broadcast (kom-queue handler message &rest data) "Send a broadcast message to all logged in users. Args: KOM-QUEUE HANDLER MESSAGE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 45 message)))) (defun initiate-get-membership (kom-queue handler pers-no &rest data) "Get membership-list for PERS-NO from server. Args: KOM-QUEUE HANDLER PERS-NO &rest DATA." (lyskom-server-call (cond ((lyskom-have-call 108) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-11) (lyskom-send-packet kom-queue (lyskom-format-objects 108 pers-no 0 lyskom-max-int 1 lyskom-max-int))) ((lyskom-have-call 99) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-10) (lyskom-send-packet kom-queue (lyskom-format-objects 99 pers-no 0 lyskom-max-int 1))) (t (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-old) (lyskom-send-packet kom-queue (lyskom-format-objects 46 pers-no 0 lyskom-max-int 1)))))) (defun initiate-get-part-of-membership (kom-queue handler pers-no first length &rest data) "Get membership-list for PERS-NO from server. Args: KOM-QUEUE HANDLER PERS-NO FIRST-IN-LIST LENGHT &rest DATA." (lyskom-server-call (cond ((lyskom-have-call 108) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-11) (lyskom-send-packet kom-queue (lyskom-format-objects 108 pers-no first length 1 1))) ((lyskom-have-call 99) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-10) (lyskom-send-packet kom-queue (lyskom-format-objects 99 pers-no first length 0))) (t (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-membership-list-old) (lyskom-send-packet kom-queue (lyskom-format-objects 46 pers-no first length 0)))))) (defun initiate-get-created-texts (kom-queue handler pers-no first-local no-of-texts &rest data) "Get a part of the list of created texts for a person. Args: KOM-QUEUE HANDLER PERS-NO FIRST-LOCAL NO-OF-TEXTS &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-map) (lyskom-send-packet kom-queue (lyskom-format-objects 47 pers-no first-local no-of-texts)))) (defun initiate-get-members (kom-queue handler conf-no first-local no-of-members &rest data) "Get a part of the list of members in a conference. Args: KOM-QUEUE HANDLER CONF-NO FIRST-LOCAL NO-OF-MEMBERS &rest DATA. Returns a conf-no-list." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data (if (lyskom-have-call 101) 'lyskom-parse-member-list 'lyskom-parse-member-list-old)) (lyskom-send-packet kom-queue (lyskom-format-objects (if (lyskom-have-call 101) 101 48) conf-no first-local no-of-members)))) (defun initiate-get-pers-stat (kom-queue handler pers-no &rest data) "Get status for person PERS-NO. Args: KOM-QUEUE HANDLER PERS-NO &rest DATA." (lyskom-server-call (let ((pers-stat (cache-get-pers-stat pers-no))) (cond ((null pers-stat) ;Cached info? (lyskom-call kom-queue ;No, ask the server. lyskom-ref-no handler data 'lyskom-parse-pers-stat pers-no) ;(princ pers-no (get-buffer-create "pers-stat")) +++ ;(terpri (get-buffer-create "pers-stat")) (lyskom-send-packet kom-queue (lyskom-format-objects 49 pers-no))) (t ;Cached info. (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) pers-stat handler data) (lyskom-check-call kom-queue)))))) (defun initiate-get-conf-stat (kom-queue handler conf-no &rest data) "Get conf-stat from LysKOM server. Args: KOM-QUEUE HANDLER CONF-NO &rest DATA." (lyskom-server-call (let ((conf-stat (cache-get-conf-stat conf-no))) (cond ((zerop conf-no) ;No real user. (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) nil handler data) (lyskom-check-call kom-queue)) ((null conf-stat) ;Cached info? (lyskom-call kom-queue ;No, ask the server. lyskom-ref-no handler data (if (lyskom-have-call 91) 'lyskom-parse-conf-stat 'lyskom-parse-conf-stat-old) conf-no) ;;(princ conf-no (get-buffer-create "conf-stat")) +++ ;;(terpri (get-buffer-create "conf-stat")) (lyskom-send-packet kom-queue (lyskom-format-objects (if (lyskom-have-call 91) 91 50) conf-no))) (t ;Cached info. (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) conf-stat handler data) (lyskom-check-call kom-queue)))))) ;; who-is-on is obsoleted by who-is-on-dynamic (83) i protocol version 9 (defun initiate-who-is-on (kom-queue handler &rest data) "Ask server who is on. Args: KOM-QUEUE HANDLER &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-who-info-list) (lyskom-send-packet kom-queue (lyskom-format-objects 51)))) (defun initiate-get-unread-confs (kom-queue handler pers-no &rest data) "Return a list of confs that may have unread texts. Args: KOM-QUEUE HANDLER PERS-NO &rest DATA. PERS-NO is the number of the person whos confs we are checking." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-conf-no-list) (lyskom-send-packet kom-queue (lyskom-format-objects 52 pers-no)))) (defun initiate-send-message (kom-queue handler recipient message &rest data) "Send a message to one or all logged in users. Args: KOM-QUEUE HANDLER RECIPIENT MESSAGE &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 53 recipient message)))) (defun initiate-get-session-info (kom-queue handler session-no &rest data) "Ask server for info about a session. Args: KOM-QUEUE HANDLER SESSION-NO &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-session-info) (lyskom-send-packet kom-queue (lyskom-format-objects 54 session-no)))) (defun initiate-disconnect (kom-queue handler session-no &rest data) "Disconnect a session. Args: KOM-QUEUE HANDLER SESSION &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 55 session-no)))) (defun initiate-who-am-i (kom-queue handler &rest data) "Ask the server which connection we are using. Args: KOM-QUEUE HANDLER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 56)))) (defun initiate-set-user-area (kom-queue handler pers-no text-no &rest data) "Set user-area of a person. Args: KOM-QUEUE HANDLER PERS-NO TEXT-NO &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 57 pers-no text-no)))) ;; WARNING: If you start using this you have to figure out a way to ;; convert local time (before) to UTC. Since this doesn't work at the ;; moment, I have commented this functoun into oblivion. ;; ;; (defun initiate-get-last-text (kom-queue handler before &rest data) ;; "Get text created before BEFORE. ;; Args: KOM-QUEUE HANDLER BEFORE &rest DATA" ;; (lyskom-server-call ;; (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) ;; (lyskom-send-packet kom-queue (lyskom-format-objects 58 before)))) (defun initiate-create-anonymous-text (kom-queue handler message misc-list aux-items &rest data) "Create a new anonymous text. Args: KOM-QUEUE HANDLER MESSAGE MISC-LIST AUX-ITEMS &rest DATA. MESSAGE is a string. MISC-LIST should be created by lyskom-create-misc-list." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (if (lyskom-have-call 87) (lyskom-send-packet kom-queue (lyskom-format-objects 87 (cons 'STRING message) misc-list (cons 'LIST aux-items))) (lyskom-send-packet kom-queue (lyskom-format-objects 59 (cons 'STRING message) misc-list))))) (defun initiate-find-next-text-no (kom-queue handler text-no &rest data) "Find the text following the text TEXT-NO" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 60 text-no)))) (defun initiate-find-previous-text-no (kom-queue handler text-no &rest data) "Find the text preceding the text TEXT-NO" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 61 text-no)))) ;; Call 62 is above (defun initiate-who-is-on-ident (kom-queue handler &rest data) "Who is logged on. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-who-info-ident-list) (lyskom-send-packet kom-queue (lyskom-format-objects 63)))) (defun initiate-get-session-info-ident (kom-queue handler session-no &rest data) "Get session info. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-session-info-ident) (lyskom-send-packet kom-queue (lyskom-format-objects 64 session-no)))) (defun initiate-re-lookup-person (kom-queue handler regexp &rest data) "Look up person based on regexp. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 65 regexp)))) (defun initiate-re-lookup-conf (kom-queue handler regexp &rest data) "Look up conference based on regexp. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 66 regexp)))) (defun initiate-lookup-person (kom-queue handler regexp &rest data) "Look up person based on abbreviated name. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 67 regexp)))) (defun initiate-lookup-conf (kom-queue handler regexp &rest data) "Look up conference based on abbreviated name. Obsolete." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 68 regexp)))) (defun initiate-set-client-version (kom-queue handler name version &rest data) "Tell the server to set the client name and version of this session." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 69 name version)))) (defun initiate-get-client-name (kom-queue handler session &rest data) "Tell the server to set the highest unread article in conference CONF-NO to TEXT-NO Args: KOM-QUEUE HANDLER CONF-NO TEXT-NO &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-string) (lyskom-send-packet kom-queue (lyskom-format-objects 70 session)))) (defun initiate-get-client-version (kom-queue handler session &rest data) "Tell the server to set the highest unread article in conference CONF-NO to TEXT-NO Args: KOM-QUEUE HANDLER CONF-NO TEXT-NO &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-string) (lyskom-send-packet kom-queue (lyskom-format-objects 71 session)))) (defun initiate-re-z-lookup (kom-queue handler regexp want-persons want-confs &rest data) "Perform a regexp lookup. Args: KOM-QUEUE HANDLER REGEXP WANT-PERSONS WANT-CONFS &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-conf-z-info-list) (lyskom-send-packet kom-queue (lyskom-format-objects 74 regexp want-persons want-confs)))) (defun initiate-get-version-info (kom-queue handler &rest data) "Perform a get-version-info vall. Args: KOM-QUEUE HANDLER &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-version-info) (lyskom-send-packet kom-queue (lyskom-format-objects 75)))) (defun initiate-lookup-z-name (kom-queue handler name want-persons want-confs &rest data) "Perform a z-lookup. Args: KOM-QUEUE HANDLER NAME WANT-PERSONS WANT-CONFS &rest DATA" (lyskom-server-call (if (lyskom-have-call 76) (progn (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-conf-z-info-list) (lyskom-send-packet kom-queue (lyskom-format-objects 76 name want-persons want-confs))) (let ((ref-no lyskom-ref-no)) (lyskom-fake-call kom-queue ref-no handler data) (++ lyskom-ref-no) (initiate-lookup-name 'compat 'initiate-compat-lookup-z-name-2 name kom-queue ref-no want-persons want-confs))))) (defun initiate-compat-lookup-z-name-2 (result kom-queue ref-no want-persons want-confs) (lyskom-server-call (if (null result) (lyskom-complete-call kom-queue ref-no nil)) (let ((conf-nos (listify-vector (conf-list->conf-nos result))) (conf-types (listify-vector (conf-list->conf-types result)))) (lyskom-collect 'follow) (while conf-nos (if (or (and want-persons (conf-type->letterbox (car conf-types))) (and want-confs (not (conf-type->letterbox (car conf-types))))) (initiate-get-conf-stat 'follow nil (car conf-nos))) (setq conf-nos (cdr conf-nos)) (setq conf-types (cdr conf-types))) (lyskom-list-use 'follow 'initiate-compat-lookup-z-name-3 kom-queue ref-no)))) (defun initiate-compat-lookup-z-name-3 (conf-list kom-queue ref-no) (lyskom-server-call (lyskom-complete-call kom-queue ref-no (lyskom-create-conf-z-info-list (mapcar (function (lambda (conf-stat) (lyskom-create-conf-z-info (conf-stat->name conf-stat) (conf-stat->conf-type conf-stat) (conf-stat->conf-no conf-stat)))) conf-list))))) (defun initiate-set-last-read (kom-queue handler conf-no text-no &rest data) "Tell the server to set the highest unread article in conference CONF-NO to TEXT-NO Args: KOM-QUEUE HANDLER CONF-NO TEXT-NO &rest DATA" (lyskom-server-call (if (lyskom-have-call 77) (progn (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 77 conf-no text-no))) (initiate-get-conf-stat kom-queue 'initiate-set-last-read-2 conf-no kom-queue handler conf-no text-no data)))) (defun initiate-set-last-read-2 (conf-stat kom-queue handler conf-no text-no data) (lyskom-server-call (let ((no-of-unread (- (1- (+ (conf-stat->first-local-no conf-stat) (conf-stat->no-of-texts conf-stat))) text-no))) (if (< no-of-unread 0) (setq no-of-unread 0)) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 40 conf-no no-of-unread))))) (defun initiate-get-uconf-stat (kom-queue handler conf-no &rest data) "Get an uconf-stat from LysKOM server. Args: KOM-QUEUE HANDLER CONF-NO &rest DATA." (lyskom-server-call (let ((conf-stat (cache-get-uconf-stat conf-no))) (cond ((zerop conf-no) (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) nil handler data) (lyskom-check-call kom-queue)) ((null conf-stat) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-uconf-stat conf-no) (lyskom-send-packet kom-queue (lyskom-format-objects 78 conf-no))) (t (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) conf-stat handler data) (lyskom-check-call kom-queue)))))) (defun initiate-set-info (kom-queue handler conf-pres-conf pers-pres-conf motd-conf kom-news-conf motd-of-lyskom &rest data) "Set server info." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 79 0 conf-pres-conf pers-pres-conf motd-conf kom-news-conf motd-of-lyskom)))) (defun initiate-accept-async (kom-queue handler list &rest data) "Request asynchronous messages in LIST Args: KOM-QUEUE HANDLER LIST &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 80 (cons 'LIST list))))) (defun initiate-query-async (kom-queue handler &rest data) "Request information on which async messages are being sent. Args: KOM-QUEUE HANDLER &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 81)))) (defun initiate-user-active (kom-queue handler &rest data) "Notify the server that the user is active Args: KOM-QUEUE HANDLER &rest DATA." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 82)))) (defun initiate-who-is-on-dynamic (kom-queue handler want-visible want-invisible active-last &rest data) "Ask server who is on. Args: KOM-QUEUE HANDLER WANT-VISIBLE WANT-INVISIBLE ACTIVE_LAST &rest DATA" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-dynamic-session-info-list) (lyskom-send-packet kom-queue (lyskom-format-objects 83 want-visible want-invisible active-last)))) (defun initiate-get-static-session-info (kom-queue handler session-no &rest data) "Ask server for info about a session. Args: KOM-QUEUE HANDLER SESSION-NO &rest DATA" (lyskom-server-call (let ((info (cache-get-static-session-info session-no))) (cond ((null info) ; Not cached (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-static-session-info session-no) (lyskom-send-packet kom-queue (lyskom-format-objects 84 session-no))) (t ; Cached (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) info handler data) (lyskom-check-call kom-queue)))))) ;This might call the handler. (defun initiate-get-collate-table (kom-queue handler &rest data) "Get the collate table from the server." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-string) (lyskom-send-packet kom-queue (lyskom-format-objects 85)))) (defun initiate-modify-text-info (kom-queue handler text-no delete-items add-items &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 92 text-no (cons 'LIST delete-items) (cons 'LIST add-items))))) (defun initiate-modify-conf-info (kom-queue handler conf-no delete-items add-items &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 93 conf-no (cons 'LIST delete-items) (cons 'LIST add-items))))) (defun initiate-modify-server-info (kom-queue handler delete-items add-items &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 95 (cons 'LIST delete-items) (cons 'LIST add-items))))) (defun initiate-query-predefined-aux-items (kom-queue handler &rest data) "Send query-predefined-aux-items to the server" (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-number-array) (lyskom-send-packet kom-queue (lyskom-format-objects 96)))) (defun initiate-set-expire (kom-queue handler conf-no expire &rest data) "Send set-expire to server." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 97 conf-no expire)) (cache-del-conf-stat conf-no))) (defun initiate-set-membership-type (kom-queue handler pers-no conf-no type &rest data) "Send set-membership-type to the server." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 102 pers-no conf-no type)))) (defun initiate-local-to-global (kom-queue handler conf-no first-local-no no-of-texts &rest data) "Send local-to-global to server." (lyskom-server-call (cond ((lyskom-have-call 103) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-text-mapping no-of-texts) (lyskom-send-packet kom-queue (lyskom-format-objects 103 conf-no first-local-no no-of-texts))) (t (lyskom-call kom-queue lyskom-ref-no 'lyskom-l2g-fake-callback (cons handler data) 'lyskom-parse-map) (lyskom-send-packet kom-queue (lyskom-format-objects 34 conf-no first-local-no no-of-texts)))))) (defun lyskom-l2g-fake-callback (map handler &rest data) (let ((mapping (and map (lyskom-create-text-mapping (map->first-local map) (+ (map->first-local map) (length (map->text-nos map))) (length (map->text-nos map)) t 'dense map)))) (apply handler mapping data))) (defun initiate-map-created-texts (kom-queue handler author first-local-no no-of-texts &rest data) "Send map-created-texts to the server." (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-text-mappinng no-of-texts) (lyskom-send-packet kom-queue (lyskom-format-objects 104 author first-local-no no-of-texts)))) (defun initiate-set-keep-commented (kom-queue handler conf-no keep &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 105 conf-no keep)) (cache-del-conf-stat conf-no))) (defun initiate-set-pers-flags (kom-queue handler pers-no flags &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 106 pers-no flags)) (cache-del-pers-stat pers-no))) (defun initiate-mark-as-unread (kom-queue handler conf-no text &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 109 conf-no text)))) (defun initiate-get-stats-description (kom-queue handler &rest data) (lyskom-server-call (if lyskom-stats-description (progn (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) lyskom-stats-description handler data) (lyskom-check-call kom-queue)) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-stats-description) (lyskom-send-packet kom-queue (lyskom-format-objects 111))))) (defun initiate-get-stats (kom-queue handler what &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-stats-array) (lyskom-send-packet kom-queue (lyskom-format-objects 112 what)))) (defun initiate-get-boottime-info (kom-queue handler &rest data) (lyskom-server-call (if lyskom-static-server-info (progn (lyskom-call-add kom-queue 'PARSED (lyskom-ref-no) lyskom-static-server-info handler data) (lyskom-check-call kom-queue)) (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-static-server-info) (lyskom-send-packet kom-queue (lyskom-format-objects 113))))) (defun initiate-first-unused-conf-no (kom-queue handler &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 114)))) (defun initiate-first-unused-text-no (kom-queue handler &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 115)))) (defun initiate-find-next-conf-no (kom-queue handler conf-no &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 116 conf-no)))) (defun initiate-find-previous-conf-no (kom-queue handler conf-no &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-num) (lyskom-send-packet kom-queue (lyskom-format-objects 117 conf-no)))) (defun initiate-get-scheduling (kom-queue handler session-no &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-scheduling-info) (lyskom-send-packet kom-queue (lyskom-format-objects 118 (or session-no 0))))) (defun initiate-set-scheduling (kom-queue handler session-no priority weight &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 119 (or session-no 0) priority weight)))) (defun initiate-set-connection-time-format (kom-queue handler use-utc &rest data) (lyskom-server-call (lyskom-call kom-queue lyskom-ref-no handler data 'lyskom-parse-void) (lyskom-send-packet kom-queue (lyskom-format-objects 120 use-utc)))) ;;; ================================================================ ;; Blocking reading from server: (defvar lyskom-blocking-return nil "Return from blocking-do.") (defun blocking-return (retval) "Sets blocking variable." (setq lyskom-blocking-return retval lyskom-ok-to-send-new-calls nil)) (defun blocking-do (command &rest data) "Does the COMMAND agains the lyskom-server and returns the result. COMMAND is one lyskom-command \(like the initiate-* but the initiate- is stripped. DATA is the args to command. The cache is consulted when command is get-conf-stat, get-pers-stat or get-text-stat." ;; Here we could check if lyskom-blocking-return is non-nil, in ;; which case there is a bug in the code (save-excursion (set-buffer (or lyskom-buffer (process-buffer lyskom-proc))) ;; If this happens, we're in trouble (if lyskom-is-parsing (lyskom-really-serious-bug)) (let ((lyskom-blocking-return 'not-yet-gotten)) ;; This should not be necessary, but for robustness sake... ;; There are occasions when it is needed. (setq lyskom-ok-to-send-new-calls t) (apply (intern-soft (concat "initiate-" (symbol-name command))) 'blocking 'blocking-return data) (unwind-protect (while (and (eq lyskom-blocking-return 'not-yet-gotten) (memq (process-status lyskom-proc) '(open run)) ;; The following test should probably be removed (not lyskom-quit-flag)) (lyskom-accept-process-output)) ;; OK to continue with prefetch and stuff again (setq lyskom-ok-to-send-new-calls t) (lyskom-check-output-queues)) (if (or lyskom-quit-flag quit-flag) (signal 'quit nil)) (setq lyskom-quit-flag nil) lyskom-blocking-return))) (defun lyskom-wait-queue (queue) "Waits until all data on QUEUE has been processed" (save-excursion (set-buffer (or lyskom-buffer (process-buffer lyskom-proc))) (let ((collector (make-collector))) (lyskom-run queue (lambda (c) (set-collector->value c t)) collector) (unwind-protect (while (and (null (collector->value collector)) (not lyskom-quit-flag)) (lyskom-accept-process-output)) (setq lyskom-ok-to-send-new-calls t) (lyskom-check-output-queues)) (if (or lyskom-quit-flag quit-flag) (progn (lyskom-insert-before-prompt (lyskom-get-string 'interrupted)) (signal 'quit nil))) (setq lyskom-quit-flag nil) (collector->value collector)))) (defvar lyskom-multiple-blocking-return nil "Return from blocking-do-multiple") (defun lyskom-blocking-do-multiple (call-list) (save-excursion (set-buffer (or lyskom-buffer (process-buffer lyskom-proc))) ;; If this happens, we're in trouble (if lyskom-is-parsing (lyskom-really-serious-bug)) (let ((lyskom-multiple-blocking-return 'not-yet-gotten)) (setq lyskom-ok-to-send-new-calls t) (lyskom-collect 'blocking) (while call-list (apply (intern-soft (concat "initiate-" (symbol-name (car (car call-list))))) 'blocking nil (cdr (car call-list))) (setq call-list (cdr call-list))) (lyskom-use 'blocking 'lyskom-blocking-do-multiple-1) (unwind-protect (while (and (eq lyskom-multiple-blocking-return 'not-yet-gotten) (memq (process-status lyskom-proc) '(open run)) (not lyskom-quit-flag)) (lyskom-accept-process-output)) ;; OK to continue with prefetch and stuff again (setq lyskom-ok-to-send-new-calls t) (lyskom-check-output-queues)) (if lyskom-quit-flag (progn (setq lyskom-quit-flag nil) (lyskom-insert-before-prompt (lyskom-get-string 'interrupted)) (signal 'quit nil))) lyskom-multiple-blocking-return))) (defun lyskom-blocking-do-multiple-1 (&rest data) (setq lyskom-multiple-blocking-return data lyskom-ok-to-send-new-calls nil)) (defun lyskom-cancel-call (queue-name ref-nos) "Attempt to cancel calls in queue QUEUE-NAME with ref-no in REF-NOS. There is no guarantee that the call will be canceled. In particular, if the call is not on QUEUE-NAME or has been sent to the server, it will probably not be canceled." (let ((found nil)) ;; Delete the call from the pending queue (let* ((queue (cdr (assq queue-name lyskom-call-data))) (calls (and queue (lyskom-queue->all-entries (kom-queue->pending queue))))) (when queue (lyskom-queue-make-empty (kom-queue->pending queue)) (lyskom-traverse el calls (if (memq (elt el 1) ref-nos) (setq found t) (lyskom-queue-enter (kom-queue->pending queue) el))))) ;; Delete the call from the output queue (let* ((queue (aref lyskom-output-queues (lyskom-queue-priority queue-name)))) (when (and queue found) (let ((calls (lyskom-queue->all-entries queue))) (lyskom-queue-make-empty queue) (lyskom-traverse el calls (unless (memq (car el) ref-nos) (lyskom-queue-enter queue el)))))))) (put 'blocking-do-multiple 'edebug-form-spec '(sexp body)) (eval-and-compile (provide 'lyskom-services)) ;;; services.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: parse.el,v 44.59 2004/06/26 13:32:32 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: parse.el ;;;; ;;;; This file contains functions which parse replies from the ;;;; server. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: parse.el,v 44.59 2004/06/26 13:32:32 byers Exp $\n")) ;;; ================================================================ ;;; Errors that are handled of use while parsing (put 'lyskom-parse-incomplete 'error-conditions '(error lyskom-error lyskom-parse-incomplete)) (put 'lyskom-parse-incomplete 'error-message "LysKOM internal error: Parse incomplete.") ;;; ================================================================ ;;; Low-level parsing. (defun lyskom-string-skip-whitespace (string) "Return STRING omitting any leading whitespace." (let ((start (string-match "[^ \t\n\r]" string))) (cond ((null start) "") (t (substring string start))))) (defun lyskom-parse-skip-rest-of-token () "Skip to the next whitespace" (let ((c (lyskom-parse-char))) (while (not (or (= c ?\ ) (= c ?\n))) (setq c (lyskom-parse-char))))) (defun lyskom-parse-nonwhite-char () "Get next character, skipping whitespace, from lyskom-unparsed-buffer and increase lyskom-parse-pos. Signal lyskom-parse-incomplete if the buffer lyskom-unparsed-buffer is exhausted." (let ((char (lyskom-parse-char))) (while (or (= char ?\ ) (= char ?\n)) (setq char (lyskom-parse-char))) char)) (defun lyskom-parse-char () "Get next character from lyskom-unparsed-buffer and increase lyskom-parse-pos. Signal lyskom-parse-incomplete if the buffer lyskom-unparsed-buffer is exhausted." (cond ((< lyskom-parse-pos (point-max)) (prog1 (char-after lyskom-parse-pos) (++ lyskom-parse-pos))) (t (signal 'lyskom-parse-incomplete nil)))) (defun lyskom-expect-char (char) "Read past next non-white character, which must be equal to CHAR. Return nil, or signal lyskom-protocol-error if the first non-white character was not equal to CHAR." (if (/= char (lyskom-parse-nonwhite-char)) (lyskom-protocol-error 'lyskom-expect-char "Expecting %S but got %S" char (char-after (1- lyskom-parse-pos))) nil)) (defun lyskom-char-p (char) "Check if next token is CHAR (a character)." (let* ((lyskom-parse-pos lyskom-parse-pos) (c (lyskom-parse-nonwhite-char))) (eq char c))) (defun lyskom-string-to-parse () "Return unparsed data as a string." (lyskom-string-skip-whitespace (buffer-substring lyskom-parse-pos (point-max)))) (defun lyskom-parse-num () "Parse the next token as a number. Signal lyskom-parse-incomplete if the number is not followed by whitespace. Signal lyskom-protocol-error if the next token is not a number." (goto-char lyskom-parse-pos) (cond ((looking-at "[ \n]*[0-9]+") (if (char-after (match-end 0)) (progn (setq lyskom-parse-pos (goto-char (match-end 0))) (string-to-int (match-string 0))) (signal 'lyskom-parse-incomplete nil))) ((looking-at "[ \n]*\\'") (goto-char (point-max)) (signal 'lyskom-parse-incomplete nil)) (t (lyskom-protocol-error 'lyskom-parse-num "Expected number, got %S" (lyskom-string-to-parse)))) ) (defun lyskom-parse-float () "Parse the next token as a float. Signal lyskom-parse-incomplete if the number is not followed by whitespace. Signal lyskom-protocol-error if the next token is not a number." (goto-char lyskom-parse-pos) (cond ((looking-at "[ \n]*[-+]?[0-9]*\\(\\.\\([0-9]*\\([eE]\\([-+]?[0-9]*\\)?\\)?\\)?\\)?") (if (char-after (match-end 0)) (progn (setq lyskom-parse-pos (goto-char (match-end 0))) (string-to-number (match-string 0))) (signal 'lyskom-parse-incomplete nil))) ((looking-at "[ \n]*\\'") (goto-char (point-max)) (signal 'lyskom-parse-incomplete nil)) (t (lyskom-protocol-error 'lyskom-parse-num "Expected float, got %S" (lyskom-string-to-parse))))) (defun lyskom-parse-string () "Parse the next token as a string in the server coding system. Signal lyskom-parse-incomplete if the string is not complete. Signal lyskom-protocol-error if the next token is not a string." (lyskom-decode-coding-string (lyskom-parse-raw-string) lyskom-server-coding-system)) (defun lyskom-parse-raw-string () "Parse next token as a raw string. Signal lyskom-parse-incomplete if the string is not complete. Signal lyskom-protocol-error if the next token is not a string." ;; Kludge to deal with leading spaces. (lyskom-parse-nonwhite-char) (setq lyskom-parse-pos (1- lyskom-parse-pos)) ;; End kludge. (goto-char lyskom-parse-pos) (cond ((looking-at "[0-9]*\\(\\|H\\)\\'") (signal 'lyskom-parse-incomplete nil)) ((null (looking-at "[0-9]+H")) (lyskom-protocol-error 'lyskom-parse-string "Expected hollerith, got %S" (lyskom-string-to-parse))) ;Not a legal string. (t (let* ((num (match-string 0)) (end (match-end 0)) (len (string-to-int num))) (setq lyskom-parse-pos end) (cond ((< (point-max) (+ lyskom-parse-pos len)) (lyskom-setq-default lyskom-string-bytes-missing (- (+ lyskom-parse-pos len) (point-max))) (signal 'lyskom-parse-incomplete nil)) (t (prog1 (buffer-substring lyskom-parse-pos (+ lyskom-parse-pos len)) (lyskom-setq-default lyskom-string-bytes-missing 0) (setq lyskom-parse-pos (+ lyskom-parse-pos len))))))))) ;;(defun lyskom-parse-raw-string () ;; "Parse next token as a raw string. ;;Signal lyskom-parse-incomplete if the string is not complete. ;;Signal lyskom-protocol-error if the next token is not a string." ;; ;; Kludge to deal with leading spaces. ;; (lyskom-parse-nonwhite-char) ;; (setq lyskom-parse-pos (1- lyskom-parse-pos)) ;; ;; End kludge. ;; (let ((to-parse (lyskom-string-to-parse))) ;; (cond ;; ((string-match "\\`[0-9]*\\(\\|H\\)\\'" to-parse) ;; (signal 'lyskom-parse-incomplete nil)) ;; ((null (string-match "\\`[0-9]+H" to-parse)) ;; (lyskom-protocol-error 'lyskom-parse-string ;; "Expected hollerith, got %S" ;; to-parse)) ;Not a legal string. ;; (t ;; (let ((end (match-end 0)) ;; (len (string-to-int to-parse))) ;; (setq lyskom-parse-pos (+ lyskom-parse-pos end)) ;; (cond ;; ((< (point-max) (+ lyskom-parse-pos len)) ;; (lyskom-setq-default lyskom-string-bytes-missing ;; (- (+ lyskom-parse-pos len) ;; (point-max))) ;; (signal 'lyskom-parse-incomplete nil)) ;; (t ;; (prog1 (buffer-substring lyskom-parse-pos ;; (+ lyskom-parse-pos len)) ;; (lyskom-setq-default lyskom-string-bytes-missing 0) ;; (setq lyskom-parse-pos (+ lyskom-parse-pos len)))))))))) (defun lyskom-parse-coding () "Parse next token as a raw string. Signal lyskom-parse-incomplete if the string is not complete. Signal lyskom-protocol-error if the next token is not a string." ;; Kludge to deal with leading spaces. (lyskom-parse-nonwhite-char) (setq lyskom-parse-pos (1- lyskom-parse-pos)) ;; End kludge. (let ((to-parse (lyskom-string-to-parse))) (cond ((string-match "\\`[0-9]*\\(\\|C\\)\\'" to-parse) (signal 'lyskom-parse-incomplete nil)) ((null (string-match "\\`[0-9]+C" to-parse)) (lyskom-protocol-error 'lyskom-parse-string "Expected hollerith, got %S" to-parse)) ;Not a legal string. (t (let ((end (match-end 0)) (len (string-to-int to-parse))) (setq lyskom-parse-pos (+ lyskom-parse-pos end)) (cond ((< (point-max) (+ lyskom-parse-pos len)) (lyskom-setq-default lyskom-string-bytes-missing (- (+ lyskom-parse-pos len) (point-max))) (signal 'lyskom-parse-incomplete nil)) (t (prog1 (buffer-substring lyskom-parse-pos (+ lyskom-parse-pos len)) (lyskom-setq-default lyskom-string-bytes-missing 0) (setq lyskom-parse-pos (+ lyskom-parse-pos len)))))))))) ;;UNUSED: lyskom-parse-coded-string (defun lyskom-parse-coded-string () "Parse a string with explicit coding." (let ((coding (intern (lyskom-parse-coding))) (data (lyskom-parse-raw-string))) (condition-case nil (progn (lyskom-check-coding-system coding) (lyskom-decode-coding-string data coding)) (nil data)))) (defun lyskom-parse-1-or-0 () "Parse next nonwhite char and return t if it was 1, nil if it was 0. Signal lyskom-protocol-error if it was neither 1 nor 0. Signal lyskom-parse-incomplete if there is no nonwhite char to parse." (let ((char (lyskom-parse-nonwhite-char))) (cond ((= char ?0) nil) ((= char ?1) t) (t (lyskom-protocol-error 'lyskom-parse-1-or-0 "Expected boolean, got %S" char))))) (defun lyskom-parse-bitstring (default) "Parse a generic bit string" (let ((result nil) (char (lyskom-parse-nonwhite-char)) (continue t)) (while (and continue default) (cond ((eq char ?0) (setq result (cons nil result) default (cdr default) char (lyskom-parse-char))) ((eq char ?1) (setq result (cons t result) default (cdr default) char (lyskom-parse-char))) ((or (= char ?\ ) (= char ?\n)) ;; This occurs when the received string is shorter than ;; expected. (setq continue nil)) (t (lyskom-protocol-error 'lyskom-parse-bitstring "Expected bool or space, got %S" char)))) (if (not (memq char '(?\ ?\n))) ;; This occurs when the received string is longer than ;; expected. (progn (lyskom-parse-skip-rest-of-token) (nreverse result)) (nconc (nreverse result) (copy-sequence default))))) (defun lyskom-parse-time () "Parse a time from server. Args: none." (lyskom-create-time-from-utc (lyskom-parse-num) ;sec (lyskom-parse-num) ;min (lyskom-parse-num) ;hour (lyskom-parse-num) ;mday (1+ (lyskom-parse-num)) ;mon (+ 1900 (lyskom-parse-num)) ;year (lyskom-parse-num) ;wday (1+ (lyskom-parse-num)) ;yday (lyskom-parse-num))) ;isdst ;;; ================================================================ ;;; Skip tokens. (Used e g to skip unknown asynchronous messages.) (defun lyskom-skip-tokens (to-skip) "Skip next TO-SKIP tokens" (while (not (zerop to-skip)) (lyskom-skip-one-token) (-- to-skip))) (defun lyskom-skip-one-token () (let ((to-parse (lyskom-string-to-parse))) (cond ((string-match "\\`{" to-parse) ;Array/list? (lyskom-parse-nonwhite-char) (lyskom-skip-array)) ((string-match "\\`*" to-parse) ;Empty array/list? (lyskom-parse-nonwhite-char)) ;Simply skip it. ((string-match "\\`[0-9]+H" to-parse) ;Hollerith string? (lyskom-parse-string)) ((string-match "\\`[0-9]+[ \t\n\r]" to-parse) ;Number? (lyskom-parse-num)) ((string-match "\\`[0-9]\\'" to-parse) ;Incomplete number? (signal 'lyskom-parse-incomplete nil)) (t (lyskom-protocol-error 'lyskom-skip-one-token "Unrecognized token"))))) (defun lyskom-skip-array () (let ((to-parse (lyskom-string-to-parse))) (cond ((string-match "\\`}" to-parse) (lyskom-parse-nonwhite-char)) (t (lyskom-skip-one-token) (lyskom-skip-array))))) ;;; ================================================================ ;;; Medium level parsing. Parse arrays, misc-info-lists ;;; and other complex LysKOM types. (defun lyskom-parse-vector (len parser) "Parse a vector with LEN elements. Each element is parsed by PARSER, a function that takes no arguments." (cond ((zerop len) (if (lyskom-char-p ?*) (lyskom-expect-char ?*) (lyskom-expect-char ?\{) (lyskom-expect-char ?\}))) ((lyskom-char-p ?*) (lyskom-expect-char ?*)) (t (lyskom-expect-char ?{) (prog1 (lyskom-fill-vector (make-vector len nil) parser) (lyskom-expect-char ?}))))) (defun lyskom-parse-list (len parser) "Parse a vector with LEN elements and return it as a list. Each element is parsed by PARSER, a function that takes no arguments." (cond ((zerop len) (if (lyskom-char-p ?*) (lyskom-expect-char ?*) (lyskom-expect-char ?\{) (lyskom-expect-char ?\})) nil) ((lyskom-char-p ?*) (lyskom-expect-char ?*) nil) (t (lyskom-expect-char ?{) (let ((result nil)) (while (> len 0) (setq result (cons (funcall parser) result)) (setq len (1- len))) (prog1 (nreverse result) (lyskom-expect-char ?})))))) (defun lyskom-fill-vector (vector parser) "Fill a vector. Args: VECTOR PARSER. Fills in all elements in VECTOR. PARSER is called for each element and the result is assigned to the element." (let ((index 0) (len (length vector))) (while (< index len) (aset vector index (funcall parser)) (setq index (1+ index)))) vector) (defun lyskom-parse-conf-type () "Parse a conf-type. No args." (apply 'lyskom-create-conf-type (lyskom-parse-bitstring '(nil nil nil nil t nil nil nil)))) (defun lyskom-parse-privs () "Parse privileges. No args." (apply 'lyskom-create-privs (lyskom-parse-bitstring '(nil nil nil t t t nil nil nil nil nil nil nil nil nil nil)))) (defun lyskom-parse-flags () "Parse Personal_flags. No args." (apply 'lyskom-create-flags (lyskom-parse-bitstring '(nil nil nil nil nil nil nil nil)))) (defun lyskom-parse-misc-info-list () "Parse a misc-info-list." (let ((n (lyskom-parse-num)) ;Number of misc-items to parse. (char (lyskom-parse-nonwhite-char))) (cond ((= char ?*) ;Empty list. nil) ((= char ?{) ;Start of list. (prog1 (lyskom-parse-misc-info-list-sub n) (lyskom-expect-char ?}))) (t (lyskom-protocol-error 'lyskom-parse-misc-info-list "Expected * or {, got %S" char))))) (defun lyskom-parse-misc-info-list-sub (n) "Parse a misc-info list with N items." (let* ((result (list 'dummy)) (last result) (next-key (lyskom-parse-num)) (res)) (while (> n 0) (cond ((eq next-key 0) ;recpt (setq res (lyskom-parse-misc-recipient 'RECPT last n))) ((eq next-key 1) ;cc-recpt (setq res (lyskom-parse-misc-recipient 'CC-RECPT last n))) ((eq next-key 2) ;comm-to (setq res (lyskom-parse-misc-comm-to last n))) ((eq next-key 3) ;comm-in (setq res (lyskom-parse-misc-comm-in last n))) ((eq next-key 4) ;footn-to (setq res (lyskom-parse-misc-footn-to last n))) ((eq next-key 5) ;footn-in (setq res (lyskom-parse-misc-footn-in last n))) ((eq next-key 15) ;bcc-recpt (setq res (lyskom-parse-misc-recipient 'BCC-RECPT last n))) (t (lyskom-protocol-error 'lyskom-parse-misc-info-list-sub "Unknown misc-info type %S" next-key))) (setq n (car res)) (setq next-key (cdr res)) (setq last (cdr last))) (cdr result))) ;Don't return the dummy element. (defun lyskom-parse-misc-recipient (type last n) "Parse a recipient. Args: TYPE LAST N. TYPE is either RECPT, CC-RECPT or BCC-RECPT. LAST is a pointer to the last element on a misc-info-list. N is number of misc-items left to parse. Returns (cons n next-key)." (setcdr last (cons (lyskom-create-empty-misc-info) nil)) (let ((info (car (cdr last))) (next-key nil)) (set-misc-info->type info type) (set-misc-info->recipient-no info (lyskom-parse-num)) (setq n (1- n)) ;; A loc-no should follow. (if (/= 6 (lyskom-next-num n nil)) (lyskom-protocol-error 'lyskom-parse-misc-recipient "Expected 6, got something else")) (set-misc-info->local-no info (lyskom-parse-num)) (setq n (1- n)) ;; A rec-time might follow. (if (= 7 (setq next-key (lyskom-next-num n nil))) (progn (set-misc-info->rec-time info (lyskom-parse-time)) (setq n (1- n)) (setq next-key nil))) ;; A sent-by might follow. (if (= 8 (setq next-key (lyskom-next-num n next-key))) (progn (set-misc-info->sender info (lyskom-parse-num)) (setq n (1- n)) (setq next-key nil))) ;; A sent-at might follow. (if (= 9 (setq next-key (lyskom-next-num n next-key))) (progn (set-misc-info->sent-at info (lyskom-parse-time)) (setq n (1- n)) (setq next-key nil))) ;; Return n and next-key. (cons n (lyskom-next-num n next-key)))) (defun lyskom-parse-misc-comm-to (last n) "Parse a comm-to. Args: LAST N. LAST is a pointer to the last element on a misc-info-list. N is number of misc-items left to parse. Returns (cons n next-key)." (setcdr last (cons (lyskom-create-empty-misc-info) nil)) (let ((info (car (cdr last))) (next-key nil)) (set-misc-info->type info 'COMM-TO) (set-misc-info->comm-to info (lyskom-parse-num)) (setq n (1- n)) ;; A sent-by might follow. (if (= 8 (setq next-key (lyskom-next-num n nil))) (progn (set-misc-info->sender info (lyskom-parse-num)) (setq n (1- n)) (setq next-key nil))) ;; A sent-at might follow. (if (= 9 (setq next-key (lyskom-next-num n next-key))) (progn (set-misc-info->sent-at info (lyskom-parse-time)) (setq n (1- n)) (setq next-key nil))) ;; Return n and next-key. (cons n (lyskom-next-num n next-key)))) (defun lyskom-parse-misc-footn-to (last n) "Parse a footn-to. Args: LAST N. LAST is a pointer to the last element on a misc-info-list. N is number of misc-items left to parse. Returns (cons n next-key)." (setcdr last (cons (lyskom-create-empty-misc-info) nil)) (let ((info (car (cdr last))) (next-key nil)) (set-misc-info->type info 'FOOTN-TO) (set-misc-info->footn-to info (lyskom-parse-num)) (setq n (1- n)) ;; A sent-at might follow. (if (= 9 (setq next-key (lyskom-next-num n nil))) (progn (set-misc-info->sent-at info (lyskom-parse-time)) (setq n (1- n)) (setq next-key nil))) ;; Return n and next-key. (cons n (lyskom-next-num n next-key)))) (defun lyskom-parse-misc-comm-in (last n) "Parse a comm-in. Args: LAST N. LAST is a pointer to the last element on a misc-info-list. N is number of misc-items left to parse. Returns (cons n next-key)." (setcdr last (cons (lyskom-create-empty-misc-info) nil)) (let ((info (car (cdr last)))) (set-misc-info->type info 'COMM-IN) (set-misc-info->comm-in info (lyskom-parse-num)) (setq n (1- n)) ;; Return n and next-key. (cons n (lyskom-next-num n nil)))) (defun lyskom-parse-misc-footn-in (last n) "Parse a footn-in. Args: LAST N. LAST is a pointer to the last element on a misc-info-list. N is number of misc-items left to parse. Returns (cons n next-key)." (setcdr last (cons (lyskom-create-empty-misc-info) nil)) (let ((info (car (cdr last)))) (set-misc-info->type info 'FOOTN-IN) (set-misc-info->footn-in info (lyskom-parse-num)) (setq n (1- n)) ;; Return n and next-key. (cons n (lyskom-next-num n nil)))) (defun lyskom-next-num (items-to-parse pre-fetched) "Parse next number if PRE-FETCHED is nil and ITEMS-TO-PARSE is greater than 0. Args: ITEMS-TO-PARSE PRE-FETCHED. Returns -1 if ITEMS-TO-PARSE is 0." (cond ((zerop items-to-parse) -1) (pre-fetched) (t (lyskom-parse-num)))) ;;; ================================================================ ;;; High level parsing. Parsing of entire datatypes. (defun lyskom-parse-number-array () "Parse an array of integers." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-num)) (defun lyskom-parse-membership-type () "Parse a membership type" (let ((type (apply 'lyskom-create-membership-type (lyskom-parse-bitstring '(nil nil nil nil nil nil nil nil))))) (set-membership-type->message-flag type (eq (membership-type->passive type) (membership-type->message-flag type))) type)) (defun lyskom-parse-member-old () "Parse an old-style member record." (lyskom-create-member (lyskom-parse-num) 0 (lyskom-current-client-time) (lyskom-create-membership-type nil nil nil nil nil nil nil nil))) (defun lyskom-parse-member () "Parse a member record" (lyskom-create-member (lyskom-parse-num) ;conf-no (lyskom-parse-num) ;added-by (lyskom-parse-time) ;added-at (lyskom-parse-membership-type) ;type )) (defun lyskom-parse-member-list () "Parse a list of members" (lyskom-create-member-list (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-member))) (defun lyskom-convert-read-ranges-to-map (read-ranges) (let ((result nil) a b) (while read-ranges (setq a (car (car read-ranges)) b (cdr (car read-ranges)) read-ranges (cdr read-ranges)) (while (<= a b) (setq result (cons a result) a (1+ a)))) (and result (apply 'vector (nreverse result))))) (defun lyskom-parse-membership-11 () "Parse a membership, converting read-ranges to the old style." (let ((read-ranges nil)) (lyskom-create-membership (lyskom-parse-num) ;position (lyskom-parse-time) ;last-time-read (lyskom-parse-num) ;conf-no (lyskom-parse-num) ;priority (progn (setq read-ranges (listify-vector (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-read-range))) (if (eq (car (car read-ranges)) 1) (prog1 (cdr (elt read-ranges 0)) (setq read-ranges (cdr read-ranges))) 0)) (lyskom-convert-read-ranges-to-map read-ranges) (lyskom-parse-num) ;added-by (lyskom-parse-time) ;added-at (lyskom-parse-membership-type)))) (defun lyskom-parse-membership-10 () "Parse a membership." (lyskom-create-membership (lyskom-parse-num) ;position (lyskom-parse-time) ;last-time-read (lyskom-parse-num) ;conf-no (lyskom-parse-num) ;priority (lyskom-parse-num) ;last-text-read (lyskom-parse-vector ;read-texts (lyskom-parse-num) 'lyskom-parse-num) (lyskom-parse-num) ;added-by (lyskom-parse-time) ;added-at (lyskom-parse-membership-type))) (defun lyskom-parse-membership-old () "Parse a membership." (lyskom-create-membership nil (lyskom-parse-time) ;last-time-read (lyskom-parse-num) ;conf-no (lyskom-parse-num) ;priority (lyskom-parse-num) ;last-text-read (lyskom-parse-vector ;read-texts (lyskom-parse-num) 'lyskom-parse-num) 0 (lyskom-current-client-time) (lyskom-create-membership-type nil nil nil nil nil nil nil nil))) (defun lyskom-parse-version-info () "Parse info about the server and protocol." (lyskom-create-version-info (lyskom-parse-num) (lyskom-parse-string) (lyskom-parse-string))) (defun lyskom-parse-server-info () "Parse info about the server." (lyskom-create-server-info (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-aux-item-list))) (defun lyskom-parse-server-info-old () "Parse info about the server." (lyskom-create-server-info (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num))) (defun lyskom-parse-map () "Parse a text-list (also known as map)." (lyskom-create-map (lyskom-parse-num) ;first-local (lyskom-parse-vector ;text-nos (lyskom-parse-num) 'lyskom-parse-num))) (defun lyskom-parse-who-info () "Parse a who-info." (lyskom-create-who-info (lyskom-parse-num) ;pers-no (lyskom-parse-num) ;working-conf (lyskom-parse-num) ;connection (lyskom-parse-string) ;doing-what (lyskom-parse-string))) ;userid@host (defun lyskom-parse-who-info-ident () "Parse a who-info-ident" (lyskom-create-who-info (lyskom-parse-num) ;pers-no (lyskom-parse-num) ;working-conf (lyskom-parse-num) ;connection (lyskom-parse-string) ;doing-what (lyskom-parse-string) ;userid@host (lyskom-parse-string) ;hostname (lyskom-parse-string) ;ident-user )) (defun lyskom-parse-session-info () "Parse a session-info." (lyskom-create-session-info (lyskom-parse-num) ;pers-no (lyskom-parse-num) ;working-conf (lyskom-parse-num) ;connection (lyskom-parse-string) ;doing (lyskom-parse-string) ;userid@host nil ;username nil ;ident-user (lyskom-parse-num) ;idletime (lyskom-parse-time))) ;connect-time (defun lyskom-parse-session-info-ident () "Parse a session-info." (lyskom-create-session-info (lyskom-parse-num) ;pers-no (lyskom-parse-num) ;working-conf (lyskom-parse-num) ;connection (lyskom-parse-string) ;doing (lyskom-parse-string) ;userid@host (lyskom-parse-string) ;username (lyskom-parse-string) ;ident-user (lyskom-parse-num) ;idletime (lyskom-parse-time))) ;connect-time ;; prot-A.txt says that this should allow more or less flags than ;; specified, but I can't figure out how. /davidk (defun lyskom-parse-session-flags () "Parse session-flags." (apply 'lyskom-create-session-flags (lyskom-parse-bitstring '(nil nil nil nil nil nil nil nil)))) (defun lyskom-parse-dynamic-session-info () "Parse a dynamic-session-info." (lyskom-create-dynamic-session-info (lyskom-parse-num) ;session-no (lyskom-parse-num) ;pers-no (lyskom-parse-num) ;working-conf (lyskom-parse-num) ;idle-time (lyskom-parse-session-flags) ;session-flags (lyskom-parse-string))) ;doing ;;; High level parsing. Parsing of complete replies. (defun lyskom-parse-void () "Parse result from functions that only return an OK/FAILURE." t) ;Needn't do anything. (defun lyskom-parse-conf-no-list () "Parse result from functions that return conf-no-list" (lyskom-create-conf-no-list (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-num))) (defun lyskom-parse-conf-list () "Parse result from functions that return a conf-list." (let* ((list-len (lyskom-parse-num))) (lyskom-create-conf-list (lyskom-parse-vector list-len 'lyskom-parse-num) (lyskom-parse-vector list-len 'lyskom-parse-conf-type)))) (defun lyskom-parse-member-list-old () "Parse result from functions that return a conf-no-list." (lyskom-create-member-list (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-member-old))) (defun lyskom-parse-mark-list () "Parser result from functions that returns a mark-list." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-mark)) (defun lyskom-parse-mark () "Parse a marked text." (lyskom-create-mark (lyskom-parse-num) ;Text-no (lyskom-parse-num))) ;Mark-type (defun lyskom-parse-aux-item-list () "Parse an aux-item list" (listify-vector (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-aux-item))) (defun lyskom-parse-aux-item () "Parse an aux-item" (lyskom-aux-item-after-parse (lyskom-create-aux-item (lyskom-parse-num) ; aux-no (lyskom-parse-num) ; tag (lyskom-parse-num) ; creator (lyskom-parse-time) ; sent-at (lyskom-parse-aux-item-flags) (lyskom-parse-num) ; inherit-limit (lyskom-parse-raw-string) ; data ))) (defun lyskom-parse-aux-item-flags () "Parse aux-item flags" (apply 'lyskom-create-aux-item-flags (lyskom-parse-bitstring '(nil nil nil nil nil nil nil nil)))) ;;;================================================================ ;;; Parsing of datatypes with cache (defun lyskom-parse-static-session-info (session) "Parse a static-session-info and add it to the cache." (let ((info (lyskom-create-static-session-info (lyskom-parse-string) ;username (lyskom-parse-string) ;hostname (lyskom-parse-string) ;ident-user (lyskom-parse-time)))) ;connection-time (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-static-session-info session info)) info)) (defun lyskom-parse-conf-stat-old (conf-no) "Parse a conf-stat, add add it in the cache. Retuns the conf-stat. Args: CONF-NO." (let ((conf-stat (lyskom-create-conf-stat conf-no ;conf-no (supplied by ; initiate-get-conf-stat) (lyskom-parse-string) ;name (lyskom-parse-conf-type) ;conf-type (lyskom-parse-time) ;creation-time (lyskom-parse-time) ;last-written (lyskom-parse-num) ;creator (lyskom-parse-num) ;presentation (lyskom-parse-num) ;supervisor (lyskom-parse-num) ;permitted-submitters (lyskom-parse-num) ;super-conf (lyskom-parse-num) ;msg-of-day (lyskom-parse-num) ;garb-nice 77 ;fake keep-commented (lyskom-parse-num) ;no-of-members (lyskom-parse-num) ;first-local-no (lyskom-parse-num)))) ;no-of-texts (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-conf-stat conf-stat)) conf-stat)) (defun lyskom-parse-conf-stat (conf-no) "Parse a conf-stat, add add it in the cache. Retuns the conf-stat. Args: CONF-NO." (let ((conf-stat (lyskom-create-conf-stat conf-no ;conf-no (supplied by ; initiate-get-conf-stat) (lyskom-parse-string) ;name (lyskom-parse-conf-type) ;conf-type (lyskom-parse-time) ;creation-time (lyskom-parse-time) ;last-written (lyskom-parse-num) ;creator (lyskom-parse-num) ;presentation (lyskom-parse-num) ;supervisor (lyskom-parse-num) ;permitted-submitters (lyskom-parse-num) ;super-conf (lyskom-parse-num) ;msg-of-day (lyskom-parse-num) ;garb-nice (lyskom-parse-num) ;keep-commented (lyskom-parse-num) ;no-of-members (lyskom-parse-num) ;first-local-no (lyskom-parse-num) ;no-of-texts (lyskom-parse-num) ;expire (lyskom-parse-aux-item-list) ))) (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-conf-stat conf-stat)) conf-stat)) (defun lyskom-parse-uconf-stat (conf-no) "Parse a uconf-stat, and add it to the cache. Returns the conf-stat. Args CONF-NO." (let ((conf-stat (lyskom-create-uconf-stat conf-no (lyskom-parse-string) (lyskom-parse-conf-type) (lyskom-parse-num) (lyskom-parse-num)))) (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-uconf-stat conf-stat)) conf-stat)) (defun lyskom-parse-pers-stat (pers-no) "Parse a pers-stat, add add it in the cache. Retuns the pers-stat. Args: PERS-NO." (let ((pers-stat (lyskom-create-pers-stat pers-no ;pers-no (lyskom-parse-string) ;username (lyskom-parse-privs) ;privileges (lyskom-parse-flags) ;flags (lyskom-parse-time) ;last-login (lyskom-parse-num) ;user-area (lyskom-parse-num) ;total-time-present (lyskom-parse-num) ;sessions (lyskom-parse-num) ;created-lines (lyskom-parse-num) ;created-bytes (lyskom-parse-num) ;read-texts (lyskom-parse-num) ;no-of-text-fetches (lyskom-parse-num) ;created-persons (lyskom-parse-num) ;created-confs (lyskom-parse-num) ;first-created-text (lyskom-parse-num) ;no-of-created-texts (lyskom-parse-num) ;no-of-marks (lyskom-parse-num)))) ;no-of-confs (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-pers-stat pers-stat)) pers-stat)) (defun lyskom-parse-text-stat-old (text-no) "Parse a text-stat and add it in the cache. Args: TEXT-NO. Value: text-stat." (let ((text-stat (lyskom-create-text-stat text-no (lyskom-parse-time) ;creation-time (lyskom-parse-num) ;author (lyskom-parse-num) ;no-of-lines (lyskom-parse-num) ;no-of-chars (lyskom-parse-num) ;no-of-marks (lyskom-parse-misc-info-list)))) ;misc-info-list (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-text-stat text-stat)) text-stat)) (defun lyskom-parse-text-stat (text-no) "Parse a text-stat and add it in the cache. Args: TEXT-NO. Value: text-stat." (let ((text-stat (lyskom-create-text-stat text-no (lyskom-parse-time) ;creation-time (lyskom-parse-num) ;author (lyskom-parse-num) ;no-of-lines (lyskom-parse-num) ;no-of-chars (lyskom-parse-num) ;no-of-marks (lyskom-parse-misc-info-list) ;misc-info-list (lyskom-parse-aux-item-list) ))) (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-text-stat text-stat)) text-stat)) (defun lyskom-parse-text (text-no) "Parse a text and add it to the cache. Args: TEXT-NO. Result: text-stat." (let ((text (lyskom-create-text text-no (lyskom-parse-raw-string)))) ;The text. (lyskom-save-excursion (set-buffer lyskom-buffer) (cache-add-text text)) text)) (defun lyskom-parse-conf-z-info-list () "Parse result from functions that return a conf-z-info-list." (let* ((list-len (lyskom-parse-num))) (lyskom-create-conf-z-info-list (lyskom-parse-vector list-len 'lyskom-parse-conf-z-info)))) (defun lyskom-parse-conf-z-info () "Parse a conf-z-info." (lyskom-create-conf-z-info (lyskom-parse-string) ;name (lyskom-parse-conf-type) ;conf-type (lyskom-parse-num))) ;conf-no (defun lyskom-parse-text-mapping (existing) "Parse a Text-Mapping" (let ((block-type nil)) (lyskom-create-text-mapping (lyskom-parse-num) (lyskom-parse-num) existing (lyskom-parse-1-or-0) (let ((val (lyskom-parse-num))) (cond ((= val 0) (setq block-type 'sparse)) ((= val 1) (setq block-type 'dense))) block-type) (lyskom-parse-local-to-global-block block-type)))) (defun lyskom-parse-local-to-global-block (block-type) "Parse a Local-To-Global-Block" (cond ((eq block-type 'sparse) (let ((len (lyskom-parse-num))) (lyskom-parse-list len 'lyskom-parse-text-number-pair))) ((eq block-type 'dense) (lyskom-parse-map)))) (defun lyskom-parse-text-number-pair () "Parse a Text-Number-Pair" (lyskom-create-text-pair (lyskom-parse-num) (lyskom-parse-num))) (defun lyskom-parse-read-range () "Parse a Read-Range" (lyskom-create-text-pair (lyskom-parse-num) (lyskom-parse-num))) (defun lyskom-parse-stats-description () "Parse a Stats-Description" (let ((tmp (lyskom-create-stats-description (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-string) (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-num)))) (lyskom-save-excursion (set-buffer lyskom-buffer) (setq lyskom-stats-description tmp)))) (defun lyskom-parse-stats () "Parse a Stats" (lyskom-create-stats (lyskom-parse-float) (lyskom-parse-float) (lyskom-parse-float))) (defun lyskom-parse-stats-array () "Parse an array of Stats" (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-stats)) (defun lyskom-parse-static-server-info () "Parse a static-server-info" (let ((tmp (lyskom-create-static-server-info (lyskom-parse-time) (lyskom-parse-time) (lyskom-parse-string) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num) (lyskom-parse-num)))) (lyskom-save-excursion (set-buffer lyskom-buffer) (setq lyskom-static-server-info tmp)))) (defun lyskom-parse-scheduling-info () "Parse a scheduling-info" (lyskom-create-scheduling-info (lyskom-parse-num) (lyskom-parse-num))) ;;; ================================================================ ;;; Parsing of complex datatypes without cache. (defun lyskom-parse-membership-list-11 () "Parse a membership-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-membership-11)) (defun lyskom-parse-membership-list-10 () "Parse a membership-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-membership-10)) (defun lyskom-parse-membership-list-old () "Parse a membership-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-membership-old)) (defun lyskom-parse-who-info-list () "Parse a who-info-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-who-info)) (defun lyskom-parse-who-info-ident-list () "Parse a who-info-ident-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-who-info-ident)) (defun lyskom-parse-dynamic-session-info-list () "Parse a who-info-list. Returns a vector." (lyskom-parse-vector (lyskom-parse-num) 'lyskom-parse-dynamic-session-info)) (defun lyskom-init-parse (buffer) "Does all initialization of the parsing routines. i.e creates the buffer, sets all markers and pointers." (setq lyskom-is-parsing nil) (setq lyskom-unparsed-buffer (lyskom-generate-new-buffer (concat (if lyskom-debug-communications-to-buffer "" " ") (buffer-name) "-replies"))) (lyskom-set-buffer-parent lyskom-unparsed-buffer lyskom-buffer) (lyskom-update-inherited-variables lyskom-unparsed-buffer) (save-excursion (set-buffer lyskom-unparsed-buffer) (lyskom-set-buffer-multibyte nil)) (setq lyskom-unparsed-marker (lyskom-save-excursion (let ((proc lyskom-proc)) (set-buffer lyskom-unparsed-buffer) (make-local-variable 'lyskom-proc) (make-local-variable 'lyskom-string-bytes-missing) (setq lyskom-proc proc) (make-local-variable 'lyskom-buffer) (setq lyskom-buffer buffer) (lyskom-setq-default lyskom-string-bytes-missing 0) (goto-char (point-max)) (point-marker))))) ;;; ================================================================ ;;; Functions that call the other parsing functions. (defun lyskom-parse-success (ref-no buffer) "Parse the results of a successful call and call the handler." (lyskom-save-excursion (set-buffer buffer) (let* ((kom-queue (cdr (assq ref-no lyskom-pending-calls))) (call-info (lyskom-locate-ref-no kom-queue ref-no))) (set-buffer lyskom-unparsed-buffer) (if call-info (apply-parser call-info)) (set-buffer buffer) (lyskom-decrease-pending-calls) (setq lyskom-pending-calls (lyskom-assoc-dremove ref-no lyskom-pending-calls)) (lyskom-check-call kom-queue)))) (defun lyskom-locate-ref-no (kom-queue ref-no) (let ((pending (lyskom-queue->all-entries (kom-queue->pending (cdr (assoc kom-queue lyskom-call-data))))) (result nil)) (while (and (null result) (not (null pending))) (cond ((and (eq (car (car pending)) 'CALL) (eq (car (cdr (car pending))) ref-no)) (setq result (car pending))) (t (setq pending (cdr pending))))) result)) (defun lyskom-assoc-dremove (elt list) "Args: ELT LIST. Return a copy of LIST, but exclude any elements whose car is equal to ELT." (let* ((head (cons nil list)) (tail head)) (while (not (null (cdr tail))) (cond ((equal elt (car (car (cdr tail)))) (setcdr tail (cdr (cdr tail)))) (t (setq tail (cdr tail))))) (cdr head))) (defun apply-parser (call-info) "Try to parse a reply from the server. CALL-INFO looks like this: (See lyskom-call-data). ('CALL REF-NO PARSER PARSER-DATA HANDLER HANDLER-DATA) PARSER is called, and if it succeeds CALL-INFO is destructively changed to ('PARSED RESULT HANDLER HANDLER-DATA)" (let ((result (apply (car (cdr (cdr call-info))) ;Parser (car (cdr (cdr (cdr call-info))))))) ;Parser-data ;; If some part of the reply has not yet arrived ;; the parser will signal lyskom-parse-incomplete ;; and execution will not continue here. ;; The parse is complete. Change the call-info. (lyskom-tr-call-to-parsed call-info result))) (defun lyskom-tr-call-to-parsed (call-info result) "Transform a CALL to a PARSED." (setcar call-info 'PARSED) (setcar (cdr (cdr call-info)) result) (setcdr (cdr (cdr call-info)) (cdr (cdr (cdr (cdr call-info)))))) (defun lyskom-parse-error (ref-no buffer) "Parse the result of an unsuccessful call and call the handler." (lyskom-save-excursion (set-buffer buffer) (let* ((kom-queue (cdr (assq ref-no lyskom-pending-calls))) (call-info (lyskom-locate-ref-no kom-queue ref-no)) errno err-stat) (set-buffer lyskom-unparsed-buffer) (setq errno (lyskom-parse-num)) (setq err-stat (lyskom-parse-num)) ;Skip ref_no. (set-buffer buffer) (setq lyskom-errno errno) (setq lyskom-err-stat err-stat) (setq lyskom-pending-calls (lyskom-assoc-dremove ref-no lyskom-pending-calls)) (lyskom-decrease-pending-calls) (when call-info (lyskom-tr-call-to-parsed call-info nil)) (lyskom-check-call kom-queue)))) (defun lyskom-parse-unparsed () "Parse all complete replies in lyskom-unparsed-buffer. All parsing is to take place in this buffer but calling the functions: lyskom-parse-success, lyskom-parse-error and lyskom-parse-async calls functions and variables that are connected with the lyskom-buffer." (let ((lyskom-buffer (current-buffer)) (match-data (match-data))) ;; Was the server saving? (if lyskom-is-saving (progn (setq mode-line-process (lyskom-get-string (if lyskom-executing-command 'mode-line-working 'mode-line-waiting)) lyskom-is-saving nil) ;; I guess the following two lines could be replaced by ;; force-mode-line-update in a modern emacs. (set-buffer-modified-p (buffer-modified-p)) (sit-for 0) ;; Removed check for kom-presence-messages (if (and (not (lyskom-is-in-minibuffer))) (message "")))) (if lyskom-parser-recovering (lyskom-save-excursion (set-buffer lyskom-unparsed-buffer) (goto-char (point-min)) (if (re-search-forward "^[:%=]" nil t) (progn (delete-region (point-min) (match-beginning 0)) (lyskom-set-default 'lyskom-parser-recovering nil)) (when (> (point-max) (point-min)) (delete-region (point-min) (1- (point-max)))))) (lyskom-save-excursion (set-buffer lyskom-unparsed-buffer) (while (not (zerop (1- (point-max)))) ;Parse while replies. (let* ((lyskom-parse-pos 1) (key (lyskom-parse-nonwhite-char)) (endpos nil)) (unwind-protect (condition-case err (let ((inhibit-quit t)) ; Used to be nil, but that can ; cause hard-to-repair ; problems (cond ((= key ?=) ;The call succeeded. (lyskom-parse-success (lyskom-parse-num) lyskom-buffer)) ((= key ?%) ;The call was not successful. (lyskom-parse-error (lyskom-parse-num) lyskom-buffer)) ((= key ?:) ;An asynchronous message. (lyskom-parse-async (lyskom-parse-num) lyskom-buffer)) (t (lyskom-protocol-error 'lyskom-parse-unparsed "Expected =, %% or :, got %S" (lyskom-string-to-parse)))) (setq endpos lyskom-parse-pos)) ;; One reply is now parsed. (lyskom-protocol-error (setq endpos (min (point-max) (1+ lyskom-parse-pos))) (signal 'lyskom-protocol-error err)) (lyskom-parse-incomplete (setq endpos (point-min)) (signal (car err) (cdr err)))) (delete-region (point-min) (or endpos lyskom-parse-pos))) (goto-char (point-min)) (if (looking-at "[ \n]+") (delete-region (match-beginning 0) (match-end 0))) )))) (store-match-data match-data))) (defun lyskom-protocol-error (function format-string &rest args) (when lyskom-debug-communications-to-buffer (setq lyskom-debug-communications-limit nil) (lyskom-debug-insert lyskom-proc (format " Protocol error in %S: " function) (apply 'format format-string args)) (lyskom-debug-insert lyskom-proc " Backtrace:" "") (let ((standard-output (get-buffer-create lyskom-debug-communications-to-buffer-buffer))) (backtrace)) (lyskom-debug-insert lyskom-proc (format " Current string: ") (buffer-substring lyskom-parse-pos (point-max)))) (lyskom-save-backtrace (lyskom-string-to-parse)) (lyskom-parse-recover) (signal 'lyskom-protocol-error (format "Protocol error in %S: %s" function (apply 'format format-string args)))) (defun lyskom-parse-recover () "Initiate parser recovery." (lyskom-save-excursion (set-buffer lyskom-buffer) (setq lyskom-parser-recovering t) (initiate-get-time 'main nil))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: cache.el,v 44.14 2003/11/17 21:03:48 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: cache.el ;;;; ;;;; This file contains all functions which have to do with ;;;; caching various data types in the LysKOM client. ;;;; ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: cache.el,v 44.14 2003/11/17 21:03:48 byers Exp $\n")) ;;; ================================================================ ;;; UConf-stat cache (defun cache-get-uconf-stat (conf-no) "Get uconf-stat for conference CONF-NO, or nil if nothing is cached. If full conf-stat is cached, construct an uconf-stat from that data and cache it." (or (cache-assoc conf-no lyskom-uconf-cache) (and (lyskom-have-feature long-conf-types) (cache-construct-uconf-stat (cache-get-conf-stat conf-no))))) (defun cache-construct-uconf-stat (conf) "If conf is non-nil, create an uconf-stat from conf and cache it. Return the new uconf-stat or nil" (let ((tmp nil)) (and conf (cache-add-uconf-stat (setq tmp (lyskom-create-uconf-stat (conf-stat->conf-no conf) (conf-stat->name conf) (conf-stat->conf-type conf) (+ (conf-stat->first-local-no conf) (conf-stat->no-of-texts conf)) (conf-stat->garb-nice conf))))) tmp)) (defun cache-add-uconf-stat (uconf-stat) "Insert a UCONF-STAT in the cache." (cache-add (uconf-stat->conf-no uconf-stat) uconf-stat 'lyskom-uconf-cache)) (defun cache-del-uconf-stat (conf-no) "Delete a conf-stat from the cache. Args: CONF-NO." (cache-del conf-no 'lyskom-uconf-cache) (cache-del conf-no 'lyskom-conf-cache)) ;;; ================================================================ ;;; Conf-stat cache. (defun cache-get-conf-stat (conf-no) "Get conf-stat for conference CONF-NO, or nil if nothing is cached." (cache-assoc conf-no lyskom-conf-cache)) (defun cache-add-conf-stat (conf-stat) "Insert a CONF-STAT in the cache." (cache-add (conf-stat->conf-no conf-stat) conf-stat 'lyskom-conf-cache)) (defun cache-del-conf-stat (conf-no) "Delete a conf-stat from the cache. Args: CONF-NO." (cache-del conf-no 'lyskom-conf-cache) (cache-del conf-no 'lyskom-uconf-cache)) ;;; ================================================================ ;;; Pers-stat cache. (defun cache-get-pers-stat (pers-no) "Get pers-stat for person PERS-NO, or nil if nothing is cached." (cache-assoc pers-no lyskom-pers-cache)) (defun cache-add-pers-stat (pers-stat) "Insert a PERS-STAT in the cache." (cache-add (pers-stat->pers-no pers-stat) pers-stat 'lyskom-pers-cache)) (defun cache-del-pers-stat (pers-no) "Delete a pers-stat from the cache. Args: PERS-NO." (cache-del pers-no 'lyskom-pers-cache)) ;;; ================================================================ ;;; Text-stat cache. (defun cache-get-text-stat (text-no) "Get text-stat for texton TEXT-NO, or nil if nothing is cached." (cache-assoc text-no lyskom-text-cache)) (defun cache-add-text-stat (text-stat) "Insert a TEXT-STAT in the cache." (cache-add (text-stat->text-no text-stat) text-stat 'lyskom-text-cache)) (defun cache-del-text-stat (text-no) "Delete a text-stat from the cache. Args: TEXT-NO." (cache-del text-no 'lyskom-text-cache)) ;;; ================================================================ ;;; Text cache (the text strings). (defun cache-get-text (text-no) "Get text for textno TEXT-NO, or nil if nothing is cached." (let ((tx (cache-assoc text-no lyskom-text-mass-cache))) (cond ((lyskom-text-p tx) tx)))) (defun cache-add-text (text) "Insert a TEXT in the cache." (cache-add (text->text-no text) text 'lyskom-text-mass-cache)) (defun cache-del-text (text-no) "Delete a text from the cache. Args: TEXT-NO." (cache-del text-no 'lyskom-text-mass-cache)) ;;; ================================================================ ;;; Marked texts cache. (defun cache-get-marked-texts () "Return the a list of marks for all marked texts." lyskom-marked-text-cache) (defun cache-set-marked-texts (mark-array) "Sets the marks for all marked texts. A mark-list is an array, but we want a list in the cache, so this remakes it into a list." (setq lyskom-marked-text-cache (listify-vector mark-array))) (defun cache-text-is-marked (text-no) "Return the mark if the text text-no is marked by the current user, otherwise return nil" (let ((marks lyskom-marked-text-cache) (mark nil)) (while (and (not (null marks)) (null mark)) (if (equal text-no (mark->text-no (car marks))) (setq mark (car marks)) (setq marks (cdr marks)))) mark)) (defun cache-add-marked-text (text-no mark-type) "Insert a mark into the cache. If it is already there, replace it." (let ((marks lyskom-marked-text-cache) (found nil) (mark (lyskom-create-mark text-no mark-type))) (while (and (not found) (not (null marks))) (if (and (car marks) (equal text-no (mark->text-no (car marks)))) (progn (setcar marks mark) (setq found t)) (setq marks (cdr marks)))) (if (not found) (setq lyskom-marked-text-cache (cons mark lyskom-marked-text-cache))))) (defun cache-del-marked-text (text-no) "Remove the mark from the cache of marked texts if it is there. +++BUG: A mark is replaced with a nil and not removed." (let ((marks lyskom-marked-text-cache) (found nil)) (while (and (not found) (not (null marks))) (if (equal text-no (mark->text-no (car marks))) (progn (setcar marks nil) (setq found t)) (setq marks (cdr marks)))))) ;;; ================================================================ ;;; Static-session-info cache (defun cache-get-static-session-info (session) "Get static-session-info for session SESSION, or nil if nothing is cached." (let ((tx (cache-assoc session lyskom-static-session-info-cache))) (cond ((lyskom-static-session-info-p tx) tx)))) (defun cache-add-static-session-info (session info) "Insert INFO in the cache." (cache-add session info 'lyskom-static-session-info-cache)) ;; NOTUSED: cache-del-static-session-info (defun cache-del-static-session-info (session) "Delete a text from the cache. Args: SESSION." (cache-del session 'lyskom-static-session-info-cache)) ;;; ================================================================ ;;; Generic cache routines (defvar lyskom-caches nil "A list of all the caches in use. This is used to clear all caches with `clear-all-caches'") (defun cache-create (cache) (set cache nil) (setq lyskom-caches (cons cache lyskom-caches))) (defun cache-assoc (key cache) "Get data for item with key KEY from CACHE. CACHE is an assoc-list in this implementation." (cdr-safe (assoc key cache))) (defun cache-add (key data cache) "Add DATA to CACHE under the key KEY. Args: KEY DATA CACHE. CACHE is a (the only one) quoted variable pointing to the cache (an alist). The variable might be changed." (if (null (symbol-value cache)) (cache-create cache)) (let ((oldval (assoc key (symbol-value cache)))) (cond ((null oldval) (set cache (cons (cons key data) (symbol-value cache)))) (t (setcdr oldval data))))) (defun cache-del (key cache) "Delete item with key KEY from CACHE. CACHE is the name of the variable that points to the cache." (let ((oldval (assoc key (symbol-value cache)))) (if oldval (setcdr oldval nil)))) ;A pair (key . nil) will remain. ;Fix this bug someday. +++ (defun cache-clear (cache) (set cache nil) (setq lyskom-caches (delete cache lyskom-caches))) (defun clear-all-caches () (mapcar (function (lambda (cache) (set cache nil))) lyskom-caches) (setq lyskom-caches nil)) ;;; ================================================================ ;;; lyskom-tell-server (this is also a sort of cache) (def-kom-var lyskom-what-i-am-doing nil "What the client thinks the server thinks the user is doing." local) (defun lyskom-tell-server (string) "Tell the server what the user is doing. Args: STRING." (unless lyskom-is-anonymous (save-excursion (when lyskom-buffer (set-buffer lyskom-buffer)) (cond ((equal string lyskom-what-i-am-doing)) (t (setq lyskom-what-i-am-doing string) (initiate-change-what-i-am-doing 'background nil (or string ""))))))) (provide 'lyskom-cache) ;;;;; -*-coding: raw-text;-*- ;;;;; ;;;;; $Id: view-mode.el,v 44.9 2003/08/16 16:58:47 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: view-mode.el ;;;; ;;;; LysKOM view mode, a simple move for viewing buffers. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: view-mode.el,v 44.9 2003/08/16 16:58:47 byers Exp $\n")) (defvar lyskom-view-mode-map nil "Keymap for LysKOM view mode") (eval-when-compile (defvar view-mode-map nil)) (lyskom-external-function view-major-mode) (defun lyskom-view-base-mode () (cond ((fboundp 'view-major-mode) (view-major-mode)) ((assq 'view-mode minor-mode-alist) (let* ((keymap (copy-keymap lyskom-view-mode-map))) (make-variable-buffer-local 'minor-mode-map-alist) (lyskom-set-keymap-parent keymap view-mode-map) (setq minor-mode-map-alist (cons (cons 'view-mode keymap) minor-mode-map-alist)) (view-mode))) (t (view-mode)))) (if lyskom-view-mode-map nil (setq lyskom-view-mode-map (make-sparse-keymap)) (define-key lyskom-view-mode-map "*" 'kom-button-press) (define-key lyskom-view-mode-map "=" 'kom-menu-button-press) (define-key lyskom-view-mode-map "\t" 'kom-next-link) (define-key lyskom-view-mode-map [(meta tab)] 'kom-previous-link) (define-key lyskom-view-mode-map (kbd (lyskom-keys 'button2up)) 'kom-button-click) (define-key lyskom-view-mode-map (kbd (lyskom-keys 'button3)) 'kom-popup-menu) (define-key lyskom-view-mode-map "q" 'lyskom-view-mode-quit)) (defun lyskom-view-mode-quit () (interactive) (let ((buf (current-buffer))) (lyskom-undisplay-buffer buf) (kill-buffer buf))) (define-derived-mode lyskom-view-mode lyskom-view-base-mode "LysKOM View" "Major mode for viewing buffers") ;;;;; -*-coding: x-ctext;-*- ;;;;; ;;;;; ================================================================ ;;;;; _ _____ ____ _ _______ ________ ;;;;; | | / / | / __ \/ | / / _/ | / / ____/ ;;;;; | | /| / / /| | / /_/ / |/ // // |/ / / __ ;;;;; | |/ |/ / ___ |/ _, _/ /| // // /| / /_/ / ;;;;; |__/|__/_/ |_/_/ |_/_/ |_/___/_/ |_/\____/ ;;;;; ;;;;; This file is coded using x-ctext, since it contains both ;;;;; iso-8859-1 and iso-8859-2. If you open the file using any ;;;;; other coding, you'll probably screw it up. ;;;;; ;;;;; Look for the little x at the bottom-left of your Emacs frame! ;;;;; ;;;;; ================================================================ ;;;;; ;;;;; $Id: names.el,v 44.10 2003/07/02 19:10:02 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: names.el ;;;; ;;;; This file contains code to deal with namedays ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: names.el,v 44.10 2003/07/02 19:10:02 byers Exp $\n")) (def-komtype nameday-data ((code :read-only t) (name :read-only t) (description :read-only t) (data :read-only t))) (defvar lyskom-namedays nil) (defun lyskom-define-namedays (code name description data) "Define a new collection of namedays. CODE is the unique code for the nameday collection. NAME is a short name for the collection, in the language of the collection DESCRIPTION is a longer description of the collection, in the langauge of the collection. DATA is nameday data" (setq lyskom-namedays (cons (cons code (lyskom-create-nameday-data code name description data)) lyskom-namedays))) (defun lyskom-nameday (&optional now) (cond ((eq kom-show-namedays t) (lyskom-nameday-2 lyskom-language now)) ((symbolp kom-show-namedays) (lyskom-nameday-2 kom-show-namedays now)) ((listp kom-show-namedays) (mapconcat (lambda (x) (lyskom-nameday-2 x now t)) kom-show-namedays "\n")) (t nil))) (defun lyskom-nameday-2 (sym now &optional show-list-name) (let* ((time (or now (lyskom-current-server-time))) (data (cdr (assq sym lyskom-namedays))) (alist (and data (nameday-data->data data))) (mlist (cdr (assq (time->mon time) alist))) (dlist (cdr (assq (time->mday time) mlist)))) (if data (cond ((null dlist) (lyskom-format 'no-nameday nil (and show-list-name (nameday-data->name data)))) ((eq 1 (length dlist)) (lyskom-format 'has-nameday-1 (car dlist) (and show-list-name (nameday-data->name data)))) ((eq 2 (length dlist)) (lyskom-format 'has-nameday-2 (elt dlist 0) (elt dlist 1) (and show-list-name (nameday-data->name data)))) (t (lyskom-format 'has-nameday-2 (mapconcat 'identity (lyskom-butlast dlist 1) ", ") (elt dlist (1- (length dlist))) (and show-list-name (nameday-data->name data))))) ""))) (lyskom-define-namedays 'sv "Sverige" "\ Namnsdagar enligt svenska språknämndens nya namnlängd (2001)." '((1 . ((1 . ()) (2 . ("Svea")) (3 . ("Alfred" "Alfrida")) (4 . ("Rut")) (5 . ("Hanna" "Hannele")) (6 . ("Kasper" "Melker" "Baltsar")) (7 . ("August" "Augusta")) (8 . ("Erland")) (9 . ("Gunnar" "Gunder")) (10 . ("Sigurd" "Sigbritt")) (11 . ("Jan" "Jannike")) (12 . ("Frideborg" "Fridolf")) (13 . ("Knut")) (14 . ("Felix" "Felicia")) (15 . ("Laura" "Lorentz")) (16 . ("Hjalmar" "Helmer")) (17 . ("Anton" "Tony")) (18 . ("Hilda" "Hildur")) (19 . ("Henrik")) (20 . ("Fabian" "Sebastian")) (21 . ("Agnes" "Agneta")) (22 . ("Vincent" "Viktor")) (23 . ("Frej" "Freja")) (24 . ("Erika")) (25 . ("Paul" "Pål")) (26 . ("Bodil" "Boel")) (27 . ("Göte" "Göta")) (28 . ("Karl" "Karla")) (29 . ("Diana")) (30 . ("Gunilla" "Gunhild")) (31 . ("Ivar" "Joar")))) (2 . ((1 . ("Max" "Maximilian")) (2 . ()) (3 . ("Disa" "Hjördis")) (4 . ("Ansgar" "Anselm")) (5 . ("Agata" "Agda")) (6 . ("Dorotea" "Doris")) (7 . ("Rikard" "Dick")) (8 . ("Berta" "Bert")) (9 . ("Fanny" "Franciska")) (10 . ("Iris")) (11 . ("Yngve" "Inge")) (12 . ("Evelina" "Evy")) (13 . ("Agne" "Ove")) (14 . ("Valentin")) (15 . ("Sigfrid")) (16 . ("Julia" "Julius")) (17 . ("Alexandra" "Sandra")) (18 . ("Frida" "Fritiof")) (19 . ("Gabriella" "Ella")) (20 . ("Vivianne")) (21 . ("Hilding")) (22 . ("Pia")) (23 . ("Torsten" "Torun")) (24 . ("Mattias" "Mats")) (25 . ("Sigvard" "Sivert")) (26 . ("Torgny" "Torkel")) (27 . ("Lage")) (28 . ("Maria")))) (3 . ((1 . ("Albin" "Elvira")) (2 . ("Ernst" "Erna")) (3 . ("Gunborg" "Gunvor")) (4 . ("Adrian" "Adriana")) (5 . ("Tora" "Tove")) (6 . ("Ebba" "Ebbe")) (7 . ("Camilla")) (8 . ("Siv")) (9 . ("Torbjörn" "Torleif")) (10 . ("Edla" "Ada")) (11 . ("Edvin" "Egon")) (12 . ("Viktoria")) (13 . ("Greger")) (14 . ("Matilda" "Maud")) (15 . ("Kristoffer" "Christel")) (16 . ("Herbert" "Gilbert")) (17 . ("Gertrud")) (18 . ("Edvard" "Edmund")) (19 . ("Josef" "Josefina")) (20 . ("Joakim" "Kim")) (21 . ("Bengt")) (22 . ("Kennet" "Kent")) (23 . ("Gerda" "Gerd")) (24 . ("Gabriel" "Rafael")) (25 . ()) (26 . ("Emanuel")) (27 . ("Rudolf" "Ralf")) (28 . ("Malkolm" "Morgan")) (29 . ("Jonas" "Jens")) (30 . ("Holger" "Holmfrid")) (31 . ("Ester")))) (4 . ((1 . ("Harald" "Hervor")) (2 . ("Gudmund" "Ingesund")) (3 . ("Ferdinand" "Nanna")) (4 . ("Marianne" "Marlene")) (5 . ("Irene" "Irja")) (6 . ("Vilhelm" "Helmi")) (7 . ("Irma" "Irmelin")) (8 . ("Nadja" "Tanja")) (9 . ("Otto" "Ottilia")) (10 . ("Ingvar" "Ingvor")) (11 . ("Ulf" "Ylva")) (12 . ("Liv")) (13 . ("Artur" "Douglas")) (14 . ("Tiburtius")) (15 . ("Olivia" "Oliver")) (16 . ("Patrik" "Patricia")) (17 . ("Elias" "Elis")) (18 . ("Valdemar" "Volmar")) (19 . ("Olaus" "Ola")) (20 . ("Amalia" "Amelie")) (21 . ("Anneli" "Annika")) (22 . ("Allan" "Glenn")) (23 . ("Georg" "Göran")) (24 . ("Vega")) (25 . ("Markus")) (26 . ("Teresia" "Terese")) (27 . ("Engelbrekt")) (28 . ("Ture" "Tyra")) (29 . ("Tyko")) (30 . ("Mariana")))) (5 . ((1 . ("Valborg")) (2 . ("Filip" "Filippa")) (3 . ("John" "Jane")) (4 . ("Monika" "Mona")) (5 . ("Gotthard" "Erhard")) (6 . ("Marit" "Rita")) (7 . ("Carina" "Carita")) (8 . ("Åke")) (9 . ("Reidar" "Reidun")) (10 . ("Esbjörn" "Styrbjörn")) (11 . ("Märta" "Märit")) (12 . ("Charlotta" "Lotta")) (13 . ("Linnea" "Linn")) (14 . ("Halvard" "Halvar")) (15 . ("Sofia" "Sonja")) (16 . ("Ronald" "Ronny")) (17 . ("Rebecka" "Ruben")) (18 . ("Erik")) (19 . ("Maj" "Majken")) (20 . ("Karolina" "Carola")) (21 . ("Konstantin" "Conny")) (22 . ("Hemming" "Henning")) (23 . ("Desideria" "Desiree")) (24 . ("Ivan" "Vanja")) (25 . ("Urban")) (26 . ("Vilhelmina" "Vilma")) (27 . ("Beda" "Blenda")) (28 . ("Ingeborg" "Borghild")) (29 . ("Yvonne" "Jeanette")) (30 . ("Vera" "Veronika")) (31 . ("Petronella" "Pernilla")))) (6 . ((1 . ("Gun" "Gunnel")) (2 . ("Rutger" "Roger")) (3 . ("Ingemar" "Gudmar")) (4 . ("Solbritt" "Solveig")) (5 . ("Bo")) (6 . ("Gustav" "Gösta")) (7 . ("Robert" "Robin")) (8 . ("Eivor" "Majvor")) (9 . ("Börje" "Birger")) (10 . ("Svante" "Boris")) (11 . ("Bertil" "Berthold")) (12 . ("Eskil")) (13 . ("Aina" "Aino")) (14 . ("Håkan" "Hakon")) (15 . ("Margit" "Margot")) (16 . ("Axel" "Axelina")) (17 . ("Torborg" "Torvald")) (18 . ("Björn" "Bjarne")) (19 . ("Germund" "Görel")) (20 . ("Linda")) (21 . ("Alf" "Alvar")) (22 . ("Paulina" "Paula")) (23 . ("Adolf" "Alice")) (24 . ()) (25 . ("David" "Salomon")) (26 . ("Rakel" "Lea")) (27 . ("Selma" "Fingal")) (28 . ("Leo")) (29 . ("Peter" "Petra")) (30 . ("Elof" "Leif")))) (7 . ((1 . ("Aron" "Mirjam")) (2 . ("Rosa" "Rosita")) (3 . ("Aurora")) (4 . ("Ulrika" "Ulla")) (5 . ("Laila" "Ritva")) (6 . ("Esaias" "Jessika")) (7 . ("Klas")) (8 . ("Kjell")) (9 . ("Jörgen" "Örjan")) (10 . ("Andre" "Andrea")) (11 . ("Eleonora" "Ellinor")) (12 . ("Herman" "Hermine")) (13 . ("Joel" "Judit")) (14 . ("Folke")) (15 . ("Ragnhild" "Ragnvald")) (16 . ("Reinhold" "Reine")) (17 . ("Bruno")) (18 . ("Fredrik" "Fritz")) (19 . ("Sara")) (20 . ("Margareta" "Greta")) (21 . ("Johanna")) (22 . ("Magdalena" "Madeleine")) (23 . ("Emma")) (24 . ("Kristina" "Kerstin")) (25 . ("Jakob")) (26 . ("Jesper")) (27 . ("Marta")) (28 . ("Botvid" "Seved")) (29 . ("Olof")) (30 . ("Algot")) (31 . ("Helena" "Elin")))) (8 . ((1 . ("Per")) (2 . ("Karin" "Kajsa")) (3 . ("Tage")) (4 . ("Arne" "Arnold")) (5 . ("Ulrik" "Alrik")) (6 . ("Alfons" "Inez")) (7 . ("Dennis" "Denise")) (8 . ("Silvia" "Sylvia")) (9 . ("Roland")) (10 . ("Lars")) (11 . ("Susanna")) (12 . ("Klara")) (13 . ("Kaj")) (14 . ("Uno")) (15 . ("Stella" "Estelle")) (16 . ("Brynolf")) (17 . ("Verner" "Valter")) (18 . ("Ellen" "Lena")) (19 . ("Magnus" "Måns")) (20 . ("Bernhard" "Bernt")) (21 . ("Jon" "Jonna")) (22 . ("Henrietta" "Henrika")) (23 . ("Signe" "Signhild")) (24 . ("Bartolomeus")) (25 . ("Lovisa" "Louise")) (26 . ("Östen")) (27 . ("Rolf" "Raoul")) (28 . ("Gurli" "Leila")) (29 . ("Hans" "Hampus")) (30 . ("Albert" "Albertina")) (31 . ("Arvid" "Vidar")))) (9 . ((1 . ("Samuel")) (2 . ("Justus" "Justina")) (3 . ("Alfhild" "Alva")) (4 . ("Gisela")) (5 . ("Adela" "Heidi")) (6 . ("Lilian" "Lilly")) (7 . ("Regina" "Roy")) (8 . ("Alma" "Hulda")) (9 . ("Anita" "Annette")) (10 . ("Tord" "Turid")) (11 . ("Dagny" "Helny")) (12 . ("Åsa" "Åslög")) (13 . ("Sture")) (14 . ("Ida")) (15 . ("Sigrid" "Siri")) (16 . ("Dag" "Daga")) (17 . ("Hildegard" "Magnhild")) (18 . ("Orvar")) (19 . ("Fredrika")) (20 . ("Elise" "Lisa")) (21 . ("Matteus")) (22 . ("Maurits" "Moritz")) (23 . ("Tekla" "Tea")) (24 . ("Gerhard" "Gert")) (25 . ("Tryggve")) (26 . ("Enar" "Einar")) (27 . ("Dagmar" "Rigmor")) (28 . ("Lennart" "Leonard")) (29 . ("Mikael" "Mikaela")) (30 . ("Helge")))) (10 . ((1 . ("Ragnar" "Ragna")) (2 . ("Ludvig" "Love")) (3 . ("Evald" "Osvald")) (4 . ("Frans" "Frank")) (5 . ("Bror")) (6 . ("Jenny" "Jennifer")) (7 . ("Birgitta" "Britta")) (8 . ("Nils")) (9 . ("Ingrid" "Inger")) (10 . ("Harry" "Harriet")) (11 . ("Erling" "Jarl")) (12 . ("Valfrid" "Manfred")) (13 . ("Berit" "Birgit")) (14 . ("Stellan")) (15 . ("Hedvig" "Hillevi")) (16 . ("Finn")) (17 . ("Antonia" "Toini")) (18 . ("Lukas")) (19 . ("Tore" "Tor")) (20 . ("Sibylla")) (21 . ("Ursula" "Yrsa")) (22 . ("Marika" "Marita")) (23 . ("Severin" "Sören")) (24 . ("Evert" "Eilert")) (25 . ("Inga" "Ingalill")) (26 . ("Amanda" "Rasmus")) (27 . ("Sabina")) (28 . ("Simon" "Simone")) (29 . ("Viola")) (30 . ("Elsa" "Isabella")) (31 . ("Edit" "Edgar")))) (11 . ((1 . ()) (2 . ("Tobias")) (3 . ("Hubert" "Hugo")) (4 . ("Sverker")) (5 . ("Eugen" "Eugenia")) (6 . ("Gustav" "Adolf")) (7 . ("Ingegerd" "Ingela")) (8 . ("Vendela")) (9 . ("Teodor" "Teodora")) (10 . ("Martin" "Martina")) (11 . ("Mårten")) (12 . ("Konrad" "Kurt")) (13 . ("Kristian" "Krister")) (14 . ("Emil" "Emilia")) (15 . ("Leopold")) (16 . ("Vibeke" "Viveka")) (17 . ("Naemi" "Naima")) (18 . ("Lillemor" "Moa")) (19 . ("Elisabet" "Lisbet")) (20 . ("Pontus" "Marina")) (21 . ("Helga" "Olga")) (22 . ("Cecilia" "Sissela")) (23 . ("Klemens")) (24 . ("Gudrun" "Rune")) (25 . ("Katarina" "Katja")) (26 . ("Linus")) (27 . ("Astrid" "Asta")) (28 . ("Malte")) (29 . ("Sune")) (30 . ("Andreas" "Anders")))) (12 . ((1 . ("Oskar" "Ossian")) (2 . ("Beata" "Beatrice")) (3 . ("Lydia")) (4 . ("Barbara" "Barbro")) (5 . ("Sven")) (6 . ("Nikolaus" "Niklas")) (7 . ("Angela" "Angelika")) (8 . ("Virginia")) (9 . ("Anna")) (10 . ("Malin" "Malena")) (11 . ("Daniel" "Daniela")) (12 . ("Alexander" "Alexis")) (13 . ("Lucia")) (14 . ("Sten" "Sixten")) (15 . ("Gottfrid")) (16 . ("Assar")) (17 . ("Stig")) (18 . ("Abraham")) (19 . ("Isak")) (20 . ("Israel" "Moses")) (21 . ("Tomas")) (22 . ("Natanael" "Jonatan")) (23 . ("Adam")) (24 . ("Eva")) (25 . ()) (26 . ("Stefan" "Staffan")) (27 . ("Johannes" "Johan")) (28 . ("Benjamin")) (29 . ("Natalia" "Natalie")) (30 . ("Abel" "Set")) (31 . ("Sylvester")))))) (lyskom-define-namedays 'sv-pre-1901 "Sverige, före 1901" "\ Namnsdagar enligt namnlängd från före 1901, med uppenbara helgdagar borttagna." '((1 . ((1 . ()) (2 . ("Abel" "Set")) (3 . ("Enoch")) (4 . ("Titus")) (5 . ("Simeon")) (6 . ("Epifania")) (7 . ("Knut")) (8 . ("Erhard")) (9 . ("Julianus")) (10 . ("Nikanor")) (11 . ("Hyginus")) (12 . ("Arcadius")) (13 . ("Knut")) (14 . ("Felix")) (15 . ("Maurus")) (16 . ("Hjalmar")) (17 . ("Anton")) (18 . ("Prisca")) (19 . ("Henrik")) (20 . ("Fabianus")) (21 . ("Agneta")) (22 . ("Vincentius")) (23 . ("Emerentia")) (24 . ("Ericus Translatus")) (25 . ("Paulus")) (26 . ("Polykarpus")) (27 . ("Göte")) (28 . ("Karl")) (29 . ("Valerius")) (30 . ("Adelgunda")) (31 . ("Vigilius")) )) (2 . ( (1 . ("Maximiliana")) (2 . ()) (3 . ("Blasius")) (4 . ("Ansgar (Ansgarius)")) (5 . ("Agatha")) (6 . ("Dorothea")) (7 . ("Rikard")) (8 . ("Malakias")) (9 . ("Apollonia")) (10 . ("Eugenia")) (11 . ("Eufrosyne")) (12 . ("Eulalia")) (13 . ("Agabus")) (14 . ("Valentin")) (15 . ("Sigfrid")) (16 . ("Juliana")) (17 . ("Alexandra")) (18 . ("Concordia")) (19 . ("Gabinus")) (20 . ("Eukarius" "Hulda")) (21 . ("Hilarius")) (22 . ("Petter Katt")) (23 . ("Tertullianus")) (24 . ("Mattias")) (25 . ("Victorinus")) (26 . ("Nestor")) (27 . ("Leander")) (28 . ("Makarius")) )) (3 . ( (1 . ("Albin")) (2 . ("Ernst")) (3 . ("Kunigunda")) (4 . ("Adrian")) (5 . ("Conon")) (6 . ("Fulgentius")) (7 . ("Felicitas")) (8 . ("Philemon")) (9 . ()) (10 . ("Apollonius")) (11 . ("Vindicianus")) (12 . ("Victoria")) (13 . ("Gregorius")) (14 . ("Matilda")) (15 . ("Kristofer")) (16 . ("Herbert")) (17 . ("Gertrud")) (18 . ("Edvard")) (19 . ("Josef")) (20 . ("Joakim")) (21 . ("Bengt")) (22 . ("Viktor")) (23 . ("Axel")) (24 . ("Gabriel")) (25 . ()) (26 . ("Emanuel")) (27 . ("Rupert")) (28 . ("Malchus")) (29 . ("Jonas")) (30 . ("Qvirinus")) (31 . ("Amos")) )) (4 . ( (1 . ("Hugo")) (2 . ("Teodosius")) (3 . ("Ferdinand")) (4 . ("Ambrosius")) (5 . ("Irene")) (6 . ("Vilhelm")) (7 . ("Hegesippus")) (8 . ("Perpetuus")) (9 . ("Otto")) (10 . ("Hezekiel")) (11 . ("Antipas")) (12 . ("Julius")) (13 . ("Artur")) (14 . ("Tiburtius")) (15 . ("Olympias")) (16 . ("Patrik")) (17 . ("Elias")) (18 . ("Valerianus")) (19 . ("Bernhard")) (20 . ("Amalia")) (21 . ("Anselm")) (22 . ("Bernhardina")) (23 . ("Georg")) (24 . ("Vega")) (25 . ("Markus")) (26 . ("Kletus")) (27 . ("Antimus" "Teresia")) (28 . ("Theodora")) (29 . ("Tycho")) (30 . ("Mariana")) )) (5 . ( (1 . ("Valborg")) (2 . ("Athanasius")) (3 . ()) (4 . ("Monika")) (5 . ("Gotthard")) (6 . ("Sigismund")) (7 . ("Stanislaus")) (8 . ("Achatius")) (9 . ("Timotheus")) (10 . ("Epimachus")) (11 . ("Mamertus")) (12 . ("Charlotta")) (13 . ("Linnea")) (14 . ("Corona")) (15 . ("Sophia")) (16 . ("Peregrinus")) (17 . ("Rebecka")) (18 . ("Erik")) (19 . ("Potentiana" "Potentia")) (20 . ("Karolina")) (21 . ("Konstantin")) (22 . ("Hemming")) (23 . ("Desideria" "Deriree")) (24 . ("Rogatius")) (25 . ("Urban")) (26 . ("Vilhelmina")) (27 . ("Beda")) (28 . ("Germanus")) (29 . ("Maximinus")) (30 . ("Basilius")) (31 . ("Petronella")) )) (6 . ( (1 . ("Nikodemus")) (2 . ("Marcellinus")) (3 . ("Erasmus")) (4 . ("Optatus")) (5 . ("Bonifacius")) (6 . ("Gustaf")) (7 . ("Robert")) (8 . ("Salomon")) (9 . ("Primus")) (10 . ("Svante")) (11 . ("Barnabas")) (12 . ("Eskil")) (13 . ("Akvilina")) (14 . ("Elisa")) (15 . ("Vitus")) (16 . ("Justina")) (17 . ("Botolf")) (18 . ("Leontius")) (19 . ("Gervasius")) (20 . ("Florentin")) (21 . ("Albanus")) (22 . ("Paulinus")) (23 . ("Adold")) (24 . ()) (25 . ("David")) (26 . ("Jeremias")) (27 . ("Crescens")) (28 . ("Leo")) (29 . ("Petrus" "Paulus")) (30 . ("Martialis")) )) (7 . ( (1 . ("Aron")) (2 . ()) (3 . ("Anatolius")) (4 . ("Ulrika")) (5 . ("Melker")) (6 . ("Esaias")) (7 . ("Klas")) (8 . ("Kilian")) (9 . ("Cyrillus")) (10 . ("Knut")) (11 . ("Eleonora")) (12 . ("Herman")) (13 . ("Joel")) (14 . ("Fokas")) (15 . ()) (16 . ("Reinhold")) (17 . ("Alexius")) (18 . ("Fredrik")) (19 . ("Sara")) (20 . ("Margareta")) (21 . ("Johanna")) (22 . ("Maria Magdalena")) (23 . ("Emma")) (24 . ("Kristina")) (25 . ("Jakob")) (26 . ("Martha")) (27 . ()) (28 . ("Botvid")) (29 . ("Olof")) (30 . ("Abdon")) (31 . ("Helena")) )) (8 . ( (1 . ()) (2 . ("Karin")) (3 . ("Stefanus")) (4 . ("Aristarchus")) (5 . ("Dominikus")) (6 . ("Sixtus")) (7 . ("Donatus")) (8 . ("Cyriacus")) (9 . ("Romanus")) (10 . ("Lars")) (11 . ("Susanna")) (12 . ("Klara")) (13 . ("Hippolytus")) (14 . ("Eusebius")) (15 . ()) (16 . ("Brynolf")) (17 . ("Verner")) (18 . ("Agapetus")) (19 . ("Magnus")) (20 . ("Samuel")) (21 . ("Josefina")) (22 . ("Henrietta")) (23 . ("Zacheus")) (24 . ("Bartolomeus")) (25 . ("Lovisa")) (26 . ("Zefyrinus")) (27 . ("Rufus")) (28 . ("Augustinus")) (29 . ()) (30 . ("Albert")) (31 . ("Arvid")) )) (9 . ( (1 . ("Egidius")) (2 . ("Justus")) (3 . ("Seraphia")) (4 . ("Moses")) (5 . ("Eudoxus")) (6 . ("Zacharias" "Sakarias")) (7 . ("Regina")) (8 . ()) (9 . ("Augusta")) (10 . ("Teodard")) (11 . ("Protus")) (12 . ("Cyrus")) (13 . ("Amatus")) (14 . ()) (15 . ("Nicetas")) (16 . ("Eufemia")) (17 . ("Lambertus")) (18 . ("Methodius")) (19 . ("Fredrika")) (20 . ("Fausta")) (21 . ("Matteus")) (22 . ("Mauritz")) (23 . ("Tekla")) (24 . ("Gerhard")) (25 . ("KLeofas")) (26 . ("Cyprianus")) (27 . ("Damianus")) (28 . ("Leonard")) (29 . ("Mikael")) (30 . ("Hieronymus")) )) (10 . ( (1 . ("Remigius")) (2 . ("Ludvig")) (3 . ("Evald")) (4 . ("Frans")) (5 . ("Placidus")) (6 . ("Bruno")) (7 . ("Birgitta")) (8 . ("Demetrius")) (9 . ("Dionysius")) (10 . ("Gereon")) (11 . ("Probus")) (12 . ("Valfrid")) (13 . ("Theophilus")) (14 . ("Calixtus")) (15 . ("Hedvig")) (16 . ("Gallus")) (17 . ("Antoinetta")) (18 . ("Lukas")) (19 . ("Ptolemeus")) (20 . ("Kasper")) (21 . ("Ursula" "Ursila")) (22 . ("Severus")) (23 . ("Severin")) (24 . ("Evergistus")) (25 . ("Crispinus")) (26 . ("Amandus")) (27 . ("Sabina")) (28 . ("Simon" "Judas")) (29 . ("Narcissus")) (30 . ("Zenobia")) (31 . ("Quintinus")) )) (11 . ( (1 . ()) (2 . ("Tobias")) (3 . ("Eustachius")) (4 . ("Amatius")) (5 . ("Eugen")) (6 . ("Gustaf Adolf")) (7 . ("Engelbert")) (8 . ("Willehad")) (9 . ("Teodor")) (10 . ("Martin Luther")) (11 . ("Mårten")) (12 . ("Konrad")) (13 . ("Kristian")) (14 . ("Hypatius")) (15 . ("Leopold")) (16 . ("Edmund")) (17 . ("Napoleon")) (18 . ("Maximus")) (19 . ("Elisabet")) (20 . ("Pontus")) (21 . ("Heliodorus")) (22 . ("Cecilia")) (23 . ("Klemens")) (24 . ("Kristogonus")) (25 . ("Katarina")) (26 . ("Linus")) (27 . ("Vitalis")) (28 . ("Sten")) (29 . ("Saturninus")) (30 . ("Anders")) )) (12 . ( (1 . ("Oscar")) (2 . ("Beata")) (3 . ("Zephanias")) (4 . ("Barbro")) (5 . ("Crispina")) (6 . ("Nikolaus")) (7 . ("Agaton")) (8 . ()) (9 . ("Anna")) (10 . ("Judit")) (11 . ("Daniel")) (12 . ("Alexander")) (13 . ("Lucia")) (14 . ("Isidor")) (15 . ("Ireneus")) (16 . ("Lazarus")) (17 . ("Ignatius")) (18 . ("Abraham")) (19 . ("Isak")) (20 . ("Jakob")) (21 . ("Tomas")) (22 . ("Josef")) (23 . ("Israel")) (24 . ("Adam" "Eva")) (25 . ()) (26 . ("Stefan")) (27 . ("Johannes")) (28 . ()) (29 . ()) (30 . ("David")) (31 . ("Sylvester")) )))) (lyskom-define-namedays 'sv-1901 "Sverige, 1901 års namnlängd" "\ Namnsdagar enligt namnlängd från 1901, med uppenbara helgdagar borttagna." '((1 . ( (1 . ()) (2 . ("Svea")) (3 . ("Alfred")) (4 . ("Rut")) (5 . ("Hanna")) (6 . ()) (7 . ("August")) (8 . ("Erland")) (9 . ("Gunnar")) (10 . ("Sigurd")) (11 . ("Hugo")) (12 . ("Frideborg")) (13 . ("Knut")) (14 . ("Felix")) (15 . ("Laura")) (16 . ("Hjalmar")) (17 . ("Anton")) (18 . ("Hilda")) (19 . ("Henrik")) (20 . ("Fabian")) (21 . ("Agnes")) (22 . ("Vincent")) (23 . ("Emilia")) (24 . ("Erika")) (25 . ("Paulus")) (26 . ("Botilda")) (27 . ("Göte")) (28 . ("Karl")) (29 . ("Valter")) (30 . ("Gunhild")) (31 . ("Ivar")) )) (2 . ( (1 . ("Max")) (2 . ()) (3 . ("Disa")) (4 . ("Ansgar")) (5 . ("Agata")) (6 . ("Dorotea")) (7 . ("Rikard")) (8 . ("Berta")) (9 . ("Fanny")) (10 . ("Eugenia")) (11 . ("Yngve")) (12 . ("Evelina")) (13 . ("Agne")) (14 . ("Valentin")) (15 . ("Sigfrid")) (16 . ("Julia")) (17 . ("Alexandra")) (18 . ("Frida")) (19 . ("Gabriella")) (20 . ("Hulda")) (21 . ("Hilding")) (22 . ("Martina")) (23 . ("Torsten")) (24 . ("Mattias")) (25 . ("Sigvard")) (26 . ("Torgny")) (27 . ("Lage")) (28 . ("Maria")) )) (3 . ( (1 . ("Albin")) (2 . ("Ernst")) (3 . ("Gunborg")) (4 . ("Adrian")) (5 . ("Tora")) (6 . ("Ebba")) (7 . ("Ottilia")) (8 . ("Filippa")) (9 . ("Torbjörn")) (10 . ("Edla")) (11 . ("Edvin")) (12 . ("Viktoria")) (13 . ("Greger")) (14 . ("Matilda")) (15 . ("Kristofer")) (16 . ("Herbert")) (17 . ("Gertrud")) (18 . ("Edvard")) (19 . ("Josef")) (20 . ("Joakim")) (21 . ("Bengt")) (22 . ("Viktor")) (23 . ("Gerda")) (24 . ("Gabriel")) (25 . ()) (26 . ("Emanuel")) (27 . ("Rudolf")) (28 . ("Malkolm")) (29 . ("Jonas")) (30 . ("Holger")) (31 . ("Ester")) )) (4 . ( (1 . ("Harald")) (2 . ("Gudmund")) (3 . ("Ferdinand")) (4 . ("Ambrosius")) (5 . ("Nanna")) (6 . ("Vilhelm")) (7 . ("Ingemund")) (8 . ("Hemming")) (9 . ("Otto")) (10 . ("Ingvar")) (11 . ("Ulf")) (12 . ("Julius")) (13 . ("Artur")) (14 . ("Tiburtius")) (15 . ("Olivia")) (16 . ("Patrik")) (17 . ("Elias")) (18 . ("Valdemar")) (19 . ("Olavus Petri")) (20 . ("Amalia")) (21 . ("Anselm")) (22 . ("Albertina")) (23 . ("Georg")) (24 . ("Vega")) (25 . ("Markus")) (26 . ("Teresia")) (27 . ("Engelbrekt")) (28 . ("Ture")) (29 . ("Tyko")) (30 . ("Mariana")) )) (5 . ( (1 . ("Valborg")) (2 . ("Filip")) (3 . ("Göta")) (4 . ("Monika")) (5 . ("Gotthard")) (6 . ("Sigmund")) (7 . ("Gustava")) (8 . ("Åke")) (9 . ("Jonatan")) (10 . ("Esbjörn")) (11 . ("Märta")) (12 . ("Charlotta")) (13 . ("Linnea")) (14 . ("Halvard")) (15 . ("Sofia")) (16 . ("Hilma")) (17 . ("Rebecka")) (18 . ("Erik")) (19 . ("Alrik")) (20 . ("Karolina")) (21 . ("Konstantin")) (22 . ("Henning")) (23 . ("Desideria")) (24 . ("Ragnvald")) (25 . ("Urban")) (26 . ("Vilhelmina")) (27 . ("Blenda")) (28 . ("Ingeborg")) (29 . ("Baltsar")) (30 . ("Fritjof")) (31 . ("Isabella")) )) (6 . ( (1 . ("Nikodemus")) (2 . ("Rutger")) (3 . ("Ingemar")) (4 . ("Holmfrid")) (5 . ("Bo")) (6 . ("Gustav")) (7 . ("Robert")) (8 . ("Salomon")) (9 . ("Börje")) (10 . ("Svante")) (11 . ("Barnabas" "Bertil")) (12 . ("Eskil")) (13 . ("Aina")) (14 . ("Håkan")) (15 . ("Justina")) (16 . ("Axel")) (17 . ("Torborg")) (18 . ("Björn")) (19 . ("Germund")) (20 . ("Flora")) (21 . ("Alf")) (22 . ("Paulina")) (23 . ("Adolf")) (24 . ()) (25 . ("David")) (26 . ("Rakel")) (27 . ("Selma")) (28 . ("Leo")) (29 . ("Petrus")) (30 . ("Elof")) )) (7 . ( (1 . ("Aron")) (2 . ("Rosa")) (3 . ("Aurora")) (4 . ("Ulrika")) (5 . ("Melker")) (6 . ("Esaias")) (7 . ("Klas")) (8 . ("Kjell")) (9 . ("Götilda")) (10 . ("Anund")) (11 . ("Eleonora")) (12 . ("Herman")) (13 . ("Joel")) (14 . ("Folke")) (15 . ("Ragnhild")) (16 . ("Reinhold")) (17 . ("Alexis")) (18 . ("Fredrik")) (19 . ("Sara")) (20 . ("Margareta")) (21 . ("Johanna")) (22 . ("Magdalena")) (23 . ("Emma")) (24 . ("Kristina")) (25 . ("Jakob")) (26 . ("Jesper")) (27 . ("Marta")) (28 . ("Botvid")) (29 . ("Olof")) (30 . ("Algot")) (31 . ("Elin")) )) (8 . ( (1 . ("Per")) (2 . ("Karin")) (3 . ("Tage")) (4 . ("Arne")) (5 . ("Ulrik")) (6 . ("Sixten")) (7 . ("Arnold")) (8 . ("Sylvia")) (9 . ("Roland")) (10 . ("Lars")) (11 . ("Susanna")) (12 . ("Klara")) (13 . ("Hillevi")) (14 . ("Ebbe")) (15 . ("Stella")) (16 . ("Brynolf")) (17 . ("Verner")) (18 . ("Helena")) (19 . ("Magnus")) (20 . ("Bernhard")) (21 . ("Josefina")) (22 . ("Henrietta")) (23 . ("Signe")) (24 . ("Bartolomeus")) (25 . ("Lovisa")) (26 . ("Östen")) (27 . ("Rolf")) (28 . ("Augustin")) (29 . ("Hans")) (30 . ("Albert")) (31 . ("Arvid")) )) (9 . ( (1 . ("Samuel")) (2 . ("Justus")) (3 . ("Alfhild")) (4 . ("Moses")) (5 . ("Adela")) (6 . ("Sakarias")) (7 . ("Regina")) (8 . ("Alma")) (9 . ("Augusta")) (10 . ("Tord")) (11 . ("Dagny")) (12 . ("Tyra")) (13 . ("Ambjörn")) (14 . ("Ida")) (15 . ("Sigrid")) (16 . ("Eufemia")) (17 . ("Hildegard")) (18 . ("Alvar")) (19 . ("Fredrika")) (20 . ("Agda")) (21 . ("Matteus")) (22 . ("Maurits")) (23 . ("Tekla")) (24 . ("Gerhard")) (25 . ("Signild")) (26 . ("Enar")) (27 . ("Dagmar")) (28 . ("Lennart")) (29 . ("Mikael")) (30 . ("Helge")) )) (10 . ( (1 . ("Ragnar")) (2 . ("Ludvig")) (3 . ("Evald")) (4 . ("Frans")) (5 . ("Bror")) (6 . ("Jenny")) (7 . ("Birgitta")) (8 . ("Nils")) (9 . ("Ingrid")) (10 . ("Helmer")) (11 . ("Erling")) (12 . ("Valfrid")) (13 . ("Teofil")) (14 . ("Manfred")) (15 . ("Hedvig")) (16 . ("Fingal")) (17 . ("Antoinetta")) (18 . ("Lukas")) (19 . ("Tore")) (20 . ("Kasper" "Sibylla")) (21 . ("Birger")) (22 . ("Seved")) (23 . ("Sören")) (24 . ("Evert")) (25 . ("Inga")) (26 . ("Amanda")) (27 . ("Sabina")) (28 . ("Simon")) (29 . ("Viola")) (30 . ("Elsa")) (31 . ("Edit")) )) (11 . ( (1 . ()) (2 . ("Tobias")) (3 . ("Hubert")) (4 . ("Sverker")) (5 . ("Eugen")) (6 . ("Gustav Adolf")) (7 . ("Ingegerd")) (8 . ("Vendela")) (9 . ("Teodor")) (10 . ("Martin Luther")) (11 . ("Mårten")) (12 . ("Konrad")) (13 . ("Kristian")) (14 . ("Emil")) (15 . ("Leopold")) (16 . ("Edmund")) (17 . ("Napoleon")) (18 . ("Magnhild")) (19 . ("Elisabet")) (20 . ("Pontus")) (21 . ("Helga")) (22 . ("Cecilia")) (23 . ("Klemens")) (24 . ("Gudrun")) (25 . ("Katarina")) (26 . ("Torkel")) (27 . ("Astrid")) (28 . ("Malte")) (29 . ("Sune")) (30 . ("Anders")) )) (12 . ( (1 . ("Oskar")) (2 . ("Beata")) (3 . ("Lydia")) (4 . ("Barbro")) (5 . ("Sven")) (6 . ("Nikolaus")) (7 . ("Agaton")) (8 . ("Virginia")) (9 . ("Anna")) (10 . ("Malin")) (11 . ("Daniel")) (12 . ("Alexander")) (13 . ("Lucia")) (14 . ("Sten")) (15 . ("Gottfrid")) (16 . ("Assar")) (17 . ("Inge")) (18 . ("Abraham")) (19 . ("Isak")) (20 . ("Israel")) (21 . ("Tomas")) (22 . ("Natanael")) (23 . ("Adam")) (24 . ("Eva")) (25 . ()) (26 . ("Stefan")) (27 . ("Johannes")) (28 . ()) (29 . ("Abel")) (30 . ("Set")) (31 . ("Sylvester")) )))) (lyskom-define-namedays 'sv-1986 "Sverige, 1986 års namnlängd" "\ Namnsdagar enligt namnlängd från 1986, med uppenbara helgdagar borttagna." '((1 . ( (1 . ()) (2 . ("Svea" "Bore" "Sverre")) (3 . ("Alfred" "Alfrida" "Annefrid")) (4 . ("Rut" "Ritva" "Roger")) (5 . ("Hanna" "Hannele" "Hanny")) (6 . ()) (7 . ("August" "Öjar" "Örjan")) (8 . ("Erland" "Erhard" "Erla")) (9 . ("Gunnar" "Gun" "Gunno")) (10 . ("Sigurd" "Sigrun" "Sigyn")) (11 . ("Hugo" "Hagar")) (12 . ("Frideborg" "Fridolf" "Fridolin")) (13 . ("Knut" "Kennet" "Kent")) (14 . ("Felix" "Felicia" "Fritz")) (15 . ("Laura" "Lauritz" "Lotten")) (16 . ("Hjalmar" "Herdis" "Hjördis")) (17 . ("Anton" "Anja" "Antonia")) (18 . ("Hilda" "Hildor" "Hildur")) (19 . ("Henrik" "Henrika" "Henry")) (20 . ("Fabian" "Lina" "Linus")) (21 . ("Agnes" "Agnar" "Agneta")) (22 . ("Vincent" "Vanja" "Veine")) (23 . ("Emilia" "Emilie" "Mildred")) (24 . ("Erika" "Jarl" "Jarla")) (25 . ("Paulus" "Paul" "Paula")) (26 . ("Botilda" "Tilda" "Tilly")) (27 . ("Göte" "Götar" "Jöns")) (28 . ("Karl" "Kally" "Karla")) (29 . ("Valter" "Valerie" "Volter")) (30 . ("Gunhild" "Gunilla" "Gunnel")) (31 . ("Ivar" "Iva" "Ivan")) )) (2 . ( (1 . ("Max" "Marielle" "Marietta")) (2 . ()) (3 . ("Disa" "Dick" "Didrik")) (4 . ("Ansgar" "Anneli" "Ansa")) (5 . ("Agata" "Aili" "Alvi")) (6 . ("Dorotea" "Dora" "Doris")) (7 . ("Rikard" "Ricky" "Rigmor")) (8 . ("Berta" "Bert" "Bertram")) (9 . ("Fanny" "Sanny" "Sonny")) (10 . ("Eugenia" "Egon" "Eira")) (11 . ("Yngve" "Yvette" "Yvonne")) (12 . ("Evelina" "Elaine" "Evelyn")) (13 . ("Agne" "Alin" "Alina")) (14 . ("Valentin" "Valentina" "Vally")) (15 . ("Sigfrid" "Sigbert" "Sigbritt")) (16 . ("Julia" "Juliana" "Juliette")) (17 . ("Alexandra" "Sandor" "Sandra")) (18 . ("Frida" "Fride" "Frode")) (19 . ("Gabriella" "Ella" "Elna")) (20 . ("Hulda" "Haldis" "Haldo")) (21 . ("Hilding" "Hildeborg" "Hildemar")) (22 . ("Martina" "Tim" "Tina")) (23 . ("Torsten" "Toivo" "Torun")) (24 . ("Mattias" "Matti" "Mats")) (25 . ("Sigvard" "Sigvald" "Sigvor")) (26 . ("Torgny" "Torvald")) (27 . ("Lage" "Laila" "Lave")) (28 . ("Maria" "Marie" "Mary")) )) (3 . ( (1 . ("Albin" "Alba" "Alban")) (2 . ("Ernst" "Erna" "Ernfrid")) (3 . ("Gunborg" "Gunbritt" "Gunvald")) (4 . ("Adrian" "Adrienne" "Astor")) (5 . ("Tora" "Toini" "Tor")) (6 . ("Ebba" "Ebon" "Yvonne")) (7 . ("Ottilia" "Petra" "Petronella")) (8 . ("Filippa" "Gunlög" "Åslög")) (9 . ("Torbjörn" "Torben" "Torgun")) (10 . ("Edla" "Edling" "Ethel")) (11 . ("Edvin" "Diana" "Edna")) (12 . ("Viktoria" "Vibeke" "Viking")) (13 . ("Greger" "Grels" "Greta")) (14 . ("Matilda" "Maud" "Moa")) (15 . ("Kristofer" "Christel" "Christer")) (16 . ("Herbert" "Herta" "Hervor")) (17 . ("Gertrud" "Gertie" "Gölin")) (18 . ("Edvard" "Eda" "Eddie")) (19 . ("Josef" "James" "Janet")) (20 . ("Joakim" "Jockum" "Kim")) (21 . ("Bengt" "Bengta" "Benita")) (22 . ("Viktor" "Vimar" "Våge")) (23 . ("Gerda" "Anngerd" "Gerd")) (24 . ("Gabriel" "Gabrielle" "Gunni")) (25 . ()) (26 . ("Emanuel" "Emanuella" "Immanuel")) (27 . ("Rudolf" "Rode" "Rudi")) (28 . ("Malkolm" "Elma" "Elmer")) (29 . ("Jonas" "Jon" "Jonna")) (30 . ("Holger" "Olga")) (31 . ("Ester" "Estrid" "Vasti")) )) (4 . ( (1 . ("Harald" "Hadar" "Hardy")) (2 . ("Gudmund" "Gudmar" "Gunder")) (3 . ("Ferdinand" "Gunvi" "Gunvor")) (4 . ("Ambrosius" "Irene" "Irina")) (5 . ("Nanna" "Nancy" "Nanny")) (6 . ("Vilhelm" "William" "Willy")) (7 . ("Ingemund" "Ingemo" "Irma")) (8 . ("Hemming" "Heimir" "Helmut")) (9 . ("Otto" "Orvar" "Ottar")) (10 . ("Ingvar" "Ingvald" "Ingvor")) (11 . ("Ulf" "Ylva" "Yrsa")) (12 . ("Julius" "Gillis")) (13 . ("Artur" "Aldor" "Atle")) (14 . ("Tiburtius" "Ellen" "Elly")) (15 . ("Olivia" "Oliver" "Ove")) (16 . ("Patrik" "Patricia" "Percy")) (17 . ("Elias" "Elis" "Elise")) (18 . ("Valdemar" "Valdis" "Volmar")) (19 . ("Olavus Petri" "Olaus" "Olavi")) (20 . ("Amalia" "Amelie" "Amy")) (21 . ("Anselm" "Annevi" "Annvor")) (22 . ("Albertina" "Alida" "Allan")) (23 . ("Georg" "Georgina" "Jörgen")) (24 . ("Vega" "Viggo" "Viveka")) (25 . ("Markus" "Marika" "Mark")) (26 . ("Teresia" "Terese" "Tessy")) (27 . ("Engelbrekt" "Engelbert" "Enok")) (28 . ("Ture" "Turid" "Tuve")) (29 . ("Tyko" "Toralf" "Torulf")) (30 . ("Mariana" "Marianne" "Marina")) )) (5 . ( (1 . ("Valborg" "Maj" "Maja")) (2 . ("Filip" "Åsa" "Åse")) (3 . ("Göta" "Görel" "Götmar")) (4 . ("Monika" "Majne" "Mona")) (5 . ("Gotthard" "Gotthild" "Gotty")) (6 . ("Sigmund" "Sigge")) (7 . ("Gustava" "Gullvi" "Gullbritt")) (8 . ("Åke" "Åge" "Ågot")) (9 . ("Jonatan" "John" "Johnny")) (10 . ("Esbjörn" "Elvy" "Essy")) (11 . ("Märta" "Meta" "Märit")) (12 . ("Charlotta" "Charlotte" "Lotta")) (13 . ("Linnea" "Linn" "Lis")) (14 . ("Halvard" "Halvor" "Halvar")) (15 . ("Sofia" "Sia" "Sofie")) (16 . ("Hilma" "Helvi" "Hilmer")) (17 . ("Rebecka" "Renee" "Rosita")) (18 . ("Erik" "Erk" "Jerker")) (19 . ("Alrik" "Alda" "Altea")) (20 . ("Karolina" "Carola" "Caroline")) (21 . ("Konstantin" "Conny" "Konstantia")) (22 . ("Henning" "Henny" "Pål")) (23 . ("Desideria" "Dennis" "Desiree")) (24 . ("Ragnvald" "Ragnvi" "Ragnvor")) (25 . ("Urban" "Una" "Uno")) (26 . ("Vilhelmina" "Vilma" "Vilmar")) (27 . ("Blenda" "Beda" "Britten")) (28 . ("Ingeborg" "Ingabritt" "Ingbritt")) (29 . ("Baltsar" "Bill" "Billy")) (30 . ("Fritjof" "Majny" "Majvi")) (31 . ("Isabella" "Iris" "Isa")) )) (6 . ( (1 . ("Nikodemus" "Nina" "Ninni")) (2 . ("Rutger" "Runa" "Rune")) (3 . ("Ingemar" "Ingar" "Ingmarie")) (4 . ("Holmfrid" "Helfrid" "Helfrida")) (5 . ("Bo" "Bodil" "Boel")) (6 . ("Gustav" "Gusten" "Gösta")) (7 . ("Robert" "Robin" "Ruben")) (8 . ("Salomon" "Sally")) (9 . ("Börje" "Belinda" "Björg")) (10 . ("Svante" "Sante" "Sjunne")) (11 . ("Bertil" "Berit" "Berthold")) (12 . ("Eskil" "Eje" "Evan")) (13 . ("Aina" "Aino" "Roine")) (14 . ("Håkan" "Hakon" "Hakvin")) (15 . ("Justina" "Jim" "Jimmy")) (16 . ("Axel" "Axelia" "Axelina")) (17 . ("Torborg" "Torhild" "Toril")) (18 . ("Björn" "Bjarne" "Björne")) (19 . ("Germund" "Jerry" "Jill")) (20 . ("Flora" "Florence" "Florentin")) (21 . ("Alf" "Alvin" "Alvina")) (22 . ("Paulina" "Pamela" "Paulette")) (23 . ("Adolf" "Adolfina" "Ally")) (24 . ()) (25 . ("David" "Davida" "Daisy")) (26 . ("Rakel" "Rafael" "Ralf")) (27 . ("Selma" "Selim" "Selmer")) (28 . ("Leo" "Lola" "Liselott")) (29 . ("Petrus" "Peter" "Petter")) (30 . ("Elof" "Elvira" "Viran")) )) (7 . ( (1 . ("Aron" "Arent" "Arild")) (2 . ("Rosa" "Rose" "Rosmarie")) (3 . ("Aurora" "Andre" "Aurelia")) (4 . ("Ulrika" "Ellika" "Ulla")) (5 . ("Melker" "Marja" "Mirjam")) (6 . ("Esaias" "Elisiv" "Esse")) (7 . ("Klas" "Claudia" "Klaus")) (8 . ("Kjell" "Katja" "Kettil")) (9 . ("Götilda" "Göran" "Jörn")) (10 . ("Anund" "Anita" "Ante")) (11 . ("Eleonora" "Eleonor" "Ellinor")) (12 . ("Herman" "Hanne" "Hermine")) (13 . ("Joel" "Joar" "Jorunn")) (14 . ("Folke" "Fale" "Fylgia")) (15 . ("Ragnhild" "Ragni" "Runo")) (16 . ("Reinhold" "Reine" "Reino")) (17 . ("Alexis" "Alex" "Alice")) (18 . ("Fredrik" "Fred" "Freddy")) (19 . ("Sara" "Charles" "Saga")) (20 . ("Margareta" "Margit" "Margret")) (21 . ("Johanna" "Jean" "Jeanette")) (22 . ("Magdalena" "Magda" "Madeleine")) (23 . ("Emma" "Elena" "Emmy")) (24 . ("Kristina" "Kerstin" "Kristin")) (25 . ("Jakob" "Jack")) (26 . ("Jesper" "Jessika" "Jesse")) (27 . ("Marta" "Marit" "Marita")) (28 . ("Botvid" "Reidar" "Reidun")) (29 . ("Olof" "Ola" "Olle")) (30 . ("Algot" "Margot" "Vilgot")) (31 . ("Elin" "Elon" "Elina")) )) (8 . ( (1 . ("Per" "Peder" "Pernilla")) (2 . ("Karin" "Karen" "Kåre")) (3 . ("Tage" "Tanja" "Truls")) (4 . ("Arne" "Arna" "Arnevi")) (5 . ("Ulrik" "Unn" "Unni")) (6 . ("Sixten" "Säve" "Sölve")) (7 . ("Arnold" "Annika" "Annmari")) (8 . ("Sylvia" "Silja" "Silvia")) (9 . ("Roland" "Ronald" "Ronny")) (10 . ("Lars" "Lasse" "Lorentz")) (11 . ("Susanna" "Sanna" "Susanne")) (12 . ("Klara" "Clarence" "Clary")) (13 . ("Hillevi" "Hilja" "Ilja")) (14 . ("Ebbe" "Eberhard" "Efraim")) (15 . ("Stella" "Estelle" "Stefan")) (16 . ("Brynolf" "Benjamin" "Benny")) (17 . ("Verner" "Verna" "Veronika")) (18 . ("Helena" "Helen" "Helny")) (19 . ("Magnus" "Mogens" "Måns")) (20 . ("Bernhard" "Berna" "Bernt")) (21 . ("Josefina" "Josefin")) (22 . ("Henrietta" "Harriet" "Harry")) (23 . ("Signe" "Signar" "Signy")) (24 . ("Bartolomeus" "Carita" "Rita")) (25 . ("Lovisa" "Louis" "Louise")) (26 . ("Östen" "Ejvind" "Öjvind")) (27 . ("Rolf" "Raoul" "Rasmus")) (28 . ("Augustin" "Gusti" "Gurli")) (29 . ("Hans" "Hampus" "Hasse")) (30 . ("Albert" "Albrekt" "Aste")) (31 . ("Arvid" "Arvida" "Vidar")) )) (9 . ( (1 . ("Samuel" "Sam" "Solveig")) (2 . ("Justus" "Jane" "Judit")) (3 . ("Alfhild" "Alfons" "Arja")) (4 . ("Moses" "Molly" "My")) (5 . ("Adela" "Adele" "Adin")) (6 . ("Sakarias" "Siv" "Sivert")) (7 . ("Regina" "Gilbert" "Gisela")) (8 . ("Alma" "Adils" "Almar")) (9 . ("Augusta" "Gunda" "Gunde")) (10 . ("Tord" "Tordis" "Torgil")) (11 . ("Dagny" "Dag" "Daga")) (12 . ("Tyra" "Tyr")) (13 . ("Ambjörn" "Stig" "Styrbjörn")) (14 . ("Ida" "Idar" "Vida")) (15 . ("Sigrid" "Siri" "Solbritt")) (16 . ("Eufemia" "Cornelia" "Cornelius")) (17 . ("Hildegard" "Hilbert" "Hildebrand")) (18 . ("Alvar" "Alve" "Alva")) (19 . ("Fredrika" "Frej" "Freja")) (20 . ("Agda" "Jan" "Jannika")) (21 . ("Matteus" "Majbritt" "Majlis")) (22 . ("Maurits" "Marlene" "Moritz")) (23 . ("Tekla" "Trond" "Tryggve")) (24 . ("Gerhard" "Gert" "Glenn")) (25 . ("Signild" "Sanfrid" "Signhild")) (26 . ("Enar" "Einar" "Eja")) (27 . ("Dagmar" "Donald" "Douglas")) (28 . ("Lennart" "Lena" "Leonard")) (29 . ("Mikael" "Majken" "Mikaela")) (30 . ("Helge" "Heidi" "Härje")) )) (10 . ( (1 . ("Ragnar" "Ragna" "Ragne")) (2 . ("Ludvig" "Levi" "Liv")) (3 . ("Evald" "Eila" "Eilert")) (4 . ("Frans" "Franciska" "Frank")) (5 . ("Bror" "Brage" "Bruno")) (6 . ("Jenny" "Jennifer" "Jens")) (7 . ("Birgitta" "Birgit" "Britt")) (8 . ("Nils" "Nilla" "Nelly")) (9 . ("Ingrid" "Inger" "Ingolf")) (10 . ("Helmer" "Helmina" "Helmy")) (11 . ("Erling" "Elvin" "Elvina")) (12 . ("Valfrid" "Ina" "Inez")) (13 . ("Teofil" "Terje" "Tjelvar")) (14 . ("Manfred" "Mandor" "Manne")) (15 . ("Hedvig" "Hartvig" "Hedda")) (16 . ("Fingal" "Finn" "Flemming")) (17 . ("Antoinetta" "Annette" "Tony")) (18 . ("Lukas" "Lillemor" "Lilly")) (19 . ("Tore" "Bojan" "Borghild")) (20 . ("Sibylla" "Camilla" "Kasper")) (21 . ("Birger" "Brita" "Britta")) (22 . ("Seved" "Sigvid" "Ursula")) (23 . ("Sören" "Severin")) (24 . ("Evert" "Eivor" "Elving")) (25 . ("Inga" "Ingalill" "Ingert")) (26 . ("Amanda" "Manda" "Mandy")) (27 . ("Sabina" "Sebastian" "Sussy")) (28 . ("Simon" "Simeon" "Simone")) (29 . ("Viola" "Vivi" "Vivianne")) (30 . ("Elsa" "Elsie" "Ilse")) (31 . ("Edit" "Edgar" "Edor")) )) (11 . ( (1 . ()) (2 . ("Tobias" "Tova" "Tove")) (3 . ("Hubert" "Raymond" "Roy")) (4 . ("Sverker" "Nore" "Nora")) (5 . ("Eugen" "Ebert" "Egil")) (6 . ("Gustav Adolf" "Gull" "Gulli")) (7 . ("Ingegerd" "Ingel" "Ingela")) (8 . ("Vendela" "Vanda" "Ville")) (9 . ("Teodor" "Tea" "Ted")) (10 . ("Martin Luther" "Mait" "Martin")) (11 . ("Mårten" "Marion" "Morgan")) (12 . ("Konrad" "Kuno" "Kurt")) (13 . ("Kristian" "Karsten" "Kersti")) (14 . ("Emil" "Milly" "Mimmi")) (15 . ("Leopold" "Leif" "Lilian")) (16 . ("Edmund" "Elida" "Elisa")) (17 . ("Napoleon" "Naemi" "Naima")) (18 . ("Magnhild" "Magna" "Magne")) (19 . ("Elisabet" "Lisa" "Lisbet")) (20 . ("Pontus" "Polly" "Povel")) (21 . ("Helga" "Helle" "Hilde")) (22 . ("Cecilia" "Cilla" "Cissi")) (23 . ("Klemens" "Ketty" "Kitty")) (24 . ("Gudrun" "Gullan" "Gullvor")) (25 . ("Katarina" "Carina" "Katrin")) (26 . ("Torkel" "Torleif")) (27 . ("Astrid" "Asta" "Astri")) (28 . ("Malte" "Malvina" "Mia")) (29 . ("Sune" "Sonja" "Synnöve")) (30 . ("Anders" "Andrea" "Andreas")) )) (12 . ( (1 . ("Oskar" "Ole" "Ossian")) (2 . ("Beata" "Beatrice" "Betty")) (3 . ("Lydia" "Linda" "Love")) (4 . ("Barbro" "Barbara" "Boris")) (5 . ("Sven" "Svend" "Svenning")) (6 . ("Nikolaus" "Niklas" "Nikolina")) (7 . ("Agaton" "Angela" "Angelika")) (8 . ("Virginia" "Vera" "Vesta")) (9 . ("Anna" "Ann" "Annie")) (10 . ("Malin" "Majvor" "Malena")) (11 . ("Daniel" "Dan" "Daniela")) (12 . ("Alexander" "Pia" "Pierre")) (13 . ("Lucia" "Lisen" "Lisette")) (14 . ("Sten" "Stina" "Sture")) (15 . ("Gottfrid" "Kaj" "Kajsa")) (16 . ("Assar" "Odd" "Osvald")) (17 . ("Inge" "Ilona" "Irmeli")) (18 . ("Abraham" "Abdon" "Gideon")) (19 . ("Isak" "Isidor" "Isidora")) (20 . ("Israel" "Gina" "Gitte")) (21 . ("Tomas" "Tom" "Tommy")) (22 . ("Natanael" "Natalia" "Natan")) (23 . ("Adam" "Ada" "Adina")) (24 . ("Eva" "Evita" "Evy")) (25 . ()) (26 . ("Stefan" "Staffan" "Stefanie")) (27 . ("Johannes" "Hannes" "Johan")) (28 . ()) (29 . ("Abel" "Abbe")) (30 . ("Set" "Viva" "Vivan")) (31 . ("Sylvester" "Sylve" "Sylvi")) )))) (lyskom-define-namedays 'sv-1993 "Sverige, 1993 års namnlängd" "\ Namnsdagar enligt namnlängd från 1993, med uppenbara helgdagar borttagna." '((1 . ( (1 . ("")) (2 . ("Svea" "Sverker")) (3 . ("Alfred" "Alfrida")) (4 . ("Rut" "Ritva")) (5 . ("Hanna" "Hannele")) (6 . ("Baltsar" "Kasper")) (7 . ("August" "Augusta")) (8 . ("Erland" "Erhard")) (9 . ("Gunnar" "Gunder")) (10 . ("Sigurd" "Sigmund")) (11 . ("Hugo" "Hagar")) (12 . ("Frideborg" "Fridolf")) (13 . ("Knut")) (14 . ("Felix" "Felicia")) (15 . ("Laura" "Liv")) (16 . ("Hjalmar" "Hervor")) (17 . ("Anton" "Tony")) (18 . ("Hilda" "Hildur")) (19 . ("Henrik" "Henry")) (20 . ("Fabian" "Sebastian")) (21 . ("Agnes" "Agneta")) (22 . ("Vincent" "Veine")) (23 . ("Emilia" "Emilie")) (24 . ("Erika" "Eira")) (25 . ("Paul" "Pål")) (26 . ("Bodil" "Boel")) (27 . ("Göte" "Göta")) (28 . ("Karl" "Karla")) (29 . ("Valter" "Vilma")) (30 . ("Gunhild" "Gunilla")) (31 . ("Ivar" "Joar")) )) (2 . ( (1 . ("Max" "Magda")) (2 . ("Marja" "Mia")) (3 . ("Disa" "Hjördis")) (4 . ("Ansgar" "Anselm")) (5 . ("Lisa" "Elise")) (6 . ("Dorotea" "Dora")) (7 . ("Rikard" "Dick")) (8 . ("Berta" "Berthold")) (9 . ("Fanny" "Betty")) (10 . ("Egon" "Egil")) (11 . ("Yngve" "Ingolf")) (12 . ("Evelina" "Evy")) (13 . ("Agne" "Agnar")) (14 . ("Valentin" "Tina")) (15 . ("Sigfrid" "Sigbritt")) (16 . ("Julia" "Jill")) (17 . ("Alexandra" "Sandra")) (18 . ("Frida" "Fritz")) (19 . ("Gabriella" "Ella")) (20 . ("Rasmus" "Ruben")) (21 . ("Hilding" "Hulda")) (22 . ("Marina" "Marlene")) (23 . ("Torsten" "Torun")) (24 . ("Mattias" "Mats")) (25 . ("Sigvard" "Sivert")) (26 . ("Torgny" "Torkel")) (27 . ("Lage" "Laila")) (28 . ("Maria" "Maja")) )) (3 . ( (1 . ("Albin" "Inez")) (2 . ("Ernst" "Erna")) (3 . ("Gunborg" "Gunvor")) (4 . ("Adrian" "Ada")) (5 . ("Tora" "Tor")) (6 . ("Ebba" "Ebbe")) (7 . ("Isidor" "Doris")) (8 . ("Siv" "Saga")) (9 . ("Torbjörn" "Ambjörn")) (10 . ("Edla" "Ethel")) (11 . ("Edvin" "Elon")) (12 . ("Viktoria" "Viktor")) (13 . ("Greger" "Iris")) (14 . ("Matilda" "Maud")) (15 . ("Kristofer" "Christel")) (16 . ("Herbert" "Gilbert")) (17 . ("Gertrud" "Görel")) (18 . ("Edvard" "Eddie")) (19 . ("Josef" "Josefina")) (20 . ("Joakim" "Kim")) (21 . ("Bengt" "Benny")) (22 . ("Viking" "Vilgot")) (23 . ("Gerda" "Gerd")) (24 . ("Gabriel" "Rafael")) (25 . ("Mary" "Marion")) (26 . ("Emanuel" "Manne")) (27 . ("Ralf" "Raymond")) (28 . ("Elma" "Elmer")) (29 . ("Jonas" "Jens")) (30 . ("Holger" "Reidar")) (31 . ("Ester" "Estrid")) )) (4 . ( (1 . ("Harald" "Halvar")) (2 . ("Gunnel" "Gun")) (3 . ("Ferdinand" "Florence")) (4 . ("Irene" "Irja")) (5 . ("Nanna" "Nanny")) (6 . ("Vilhelm" "Willy")) (7 . ("Irma" "Mimmi")) (8 . ("Vanja" "Ronja")) (9 . ("Otto" "Ottilia")) (10 . ("Ingvar" "Ingvor")) (11 . ("Ulf" "Ylva")) (12 . ("Julius" "Gillis")) (13 . ("Artur" "Douglas")) (14 . ("Tiburtius" "Tim")) (15 . ("Olivia" "Oliver")) (16 . ("Patrik" "Patricia")) (17 . ("Elias" "Elis")) (18 . ("Valdemar" "Volmar")) (19 . ("Olaus" "Ola")) (20 . ("Amalia" "Amelie")) (21 . ("Annika" "Anneli")) (22 . ("Allan" "Alida")) (23 . ("Georg" "Göran")) (24 . ("Vega" "Viveka")) (25 . ("Markus" "Mark")) (26 . ("Teresia" "Terese")) (27 . ("Engelbrekt" "Enok")) (28 . ("Ture" "Tyko")) (29 . ("Kennet" "Kent")) (30 . ("Mariana" "Marianne")) )) (5 . ( (1 . ("Valborg" "Maj")) (2 . ("Filip" "Filippa")) (3 . ("John" "Jack")) (4 . ("Monika" "Mona")) (5 . ("Vivianne" "Vivan")) (6 . ("Marit" "Rita")) (7 . ("Lilian" "Lilly")) (8 . ("Åke" "Ove")) (9 . ("Jonatan" "Gideon")) (10 . ("Elvira" "Elvy")) (11 . ("Märta" "Märit")) (12 . ("Charlotta" "Lotta")) (13 . ("Linnea" "Nina")) (14 . ("Lillemor" "Lill")) (15 . ("Sofia" "Sonja")) (16 . ("Hilma" "Hilmer")) (17 . ("Nore" "Nora")) (18 . ("Erik" "Jerker")) (19 . ("Majken" "Majvor")) (20 . ("Karolina" "Lina")) (21 . ("Konstantin" "Conny")) (22 . ("Henning" "Hemming")) (23 . ("Desiree" "Renee")) (24 . ("Ivan" "Yvonne")) (25 . ("Urban" "Ursula")) (26 . ("Vilhelmina" "Helmy")) (27 . ("Blenda" "Beda")) (28 . ("Ingeborg" "Borghild")) (29 . ("Jean" "Jeanette")) (30 . ("Fritiof" "Frej")) (31 . ("Isabella" "Isa")) )) (6 . ( (1 . ("Rune" "Runa")) (2 . ("Rutger" "Roger")) (3 . ("Ingemar" "Gudmar")) (4 . ("Solveig" "Solbritt")) (5 . ("Bo" "Boris")) (6 . ("Gustav" "Gösta")) (7 . ("Robert" "Robin")) (8 . ("Eivor" "Elaine")) (9 . ("Petra" "Petronella")) (10 . ("Kerstin" "Karsten")) (11 . ("Bertil" "Berit")) (12 . ("Eskil" "Esbjörn")) (13 . ("Aina" "Eila")) (14 . ("Håkan" "Heidi")) (15 . ("Margit" "Mait")) (16 . ("Axel" "Axelina")) (17 . ("Torborg" "Torvald")) (18 . ("Björn" "Bjarne")) (19 . ("Germund" "Jerry")) (20 . ("Linda" "Linn")) (21 . ("Alf" "Alva")) (22 . ("Paulina" "Paula")) (23 . ("Adolf" "Adela")) (24 . ("Johan" "Jan")) (25 . ("David" "Salomon")) (26 . ("Gunni" "Jim")) (27 . ("Selma" "Herta")) (28 . ("Leo" "Leopold")) (29 . ("Petrus" "Peter")) (30 . ("Elof" "Leif")) )) (7 . ( (1 . ("Aron" "Mirjam")) (2 . ("Rosa" "Rosita")) (3 . ("Aurora" "Adina")) (4 . ("Ulrika" "Ulla")) (5 . ("Melker" "Agaton")) (6 . ("Ronald" "Ronny")) (7 . ("Klas" "Kaj")) (8 . ("Kjell" "Tjelvar")) (9 . ("Jörgen" "Örjan")) (10 . ("Anund" "Gunda")) (11 . ("Eleonora" "Ellinor")) (12 . ("Herman" "Hermine")) (13 . ("Joel" "Judit")) (14 . ("Folke" "Odd")) (15 . ("Ragnhild" "Ragnvald")) (16 . ("Reinhold" "Reine")) (17 . ("Alexis" "Alice")) (18 . ("Fredrik" "Fred")) (19 . ("Sara" "Sally")) (20 . ("Margareta" "Greta")) (21 . ("Johanna" "Jane")) (22 . ("Magdalena" "Madeleine")) (23 . ("Emma" "Emmy")) (24 . ("Kristina" "Stina")) (25 . ("Jakob" "James")) (26 . ("Jesper" "Jessika")) (27 . ("Marta" "Moa")) (28 . ("Botvid" "Seved")) (29 . ("Olof" "Olle")) (30 . ("Algot" "Margot")) (31 . ("Elin" "Elna")) )) (8 . ( (1 . ("Per" "Pernilla")) (2 . ("Karin" "Kajsa")) (3 . ("Tage" "Tanja")) (4 . ("Arne" "Arnold")) (5 . ("Ulrik" "Alrik")) (6 . ("Sixten" "Sölve")) (7 . ("Dennis" "Donald")) (8 . ("Silvia" "Sylvia")) (9 . ("Roland" "Roine")) (10 . ("Lars" "Lorentz")) (11 . ("Susanna" "Sanna")) (12 . ("Klara" "Clary")) (13 . ("Hillevi" "Gullvi")) (14 . ("William" "Bill")) (15 . ("Stella" "Stellan")) (16 . ("Brynolf" "Sigyn")) (17 . ("Verner" "Veronika")) (18 . ("Helena" "Lena")) (19 . ("Magnus" "Måns")) (20 . ("Bernhard" "Bernt")) (21 . ("Jon" "Jonna")) (22 . ("Henrietta" "Henny")) (23 . ("Signe" "Signhild")) (24 . ("Bartolomeus" "Bert")) (25 . ("Lovisa" "Louise")) (26 . ("Östen" "Ejvind")) (27 . ("Rolf" "Rudolf")) (28 . ("Gurli" "Gull")) (29 . ("Hans" "Hampus")) (30 . ("Albert" "Albertina")) (31 . ("Arvid" "Vidar")) )) (9 . ( (1 . ("Samuel" "Sam")) (2 . ("Justus" "Justina")) (3 . ("Alfhild" "Alfons")) (4 . ("Gisela" "Glenn")) (5 . ("Harry" "Harriet")) (6 . ("Sakarias" "Esaias")) (7 . ("Regina" "Roy")) (8 . ("Alma" "Ally")) (9 . ("Anita" "Anja")) (10 . ("Tord" "Tove")) (11 . ("Dagny" "Daniela")) (12 . ("Tyra" "Åsa")) (13 . ("Sture" "Styrbjörn")) (14 . ("Ida" "Ellida")) (15 . ("Sigrid" "Siri")) (16 . ("Dag" "Daga")) (17 . ("Hildegard" "Magnhild")) (18 . ("Alvar" "Orvar")) (19 . ("Fredrika" "Carita")) (20 . ("Agda" "Agata")) (21 . ("Ellen" "Elly")) (22 . ("Maurits" "Morgan")) (23 . ("Tekla" "Tea")) (24 . ("Gerhard" "Gert")) (25 . ("Kåre" "Tryggve")) (26 . ("Einar" "Enar")) (27 . ("Dagmar" "Rigmor")) (28 . ("Lennart" "Leonard")) (29 . ("Mikael" "Mikaela")) (30 . ("Helge" "Helny")) )) (10 . ( (1 . ("Ragnar" "Ragna")) (2 . ("Ludvig" "Louis")) (3 . ("Evald" "Osvald")) (4 . ("Frans" "Frank")) (5 . ("Bror" "Bruno")) (6 . ("Jenny" "Jennifer")) (7 . ("Birgitta" "Britta")) (8 . ("Nils" "Nelly")) (9 . ("Ingrid" "Inger")) (10 . ("Helmer" "Hadar")) (11 . ("Erling" "Jarl")) (12 . ("Valfrid" "Ernfrid")) (13 . ("Birgit" "Britt")) (14 . ("Manfred" "Helfrid")) (15 . ("Hedvig" "Hedda")) (16 . ("Fingal" "Finn")) (17 . ("Antonia" "Annette")) (18 . ("Lukas" "Matteus")) (19 . ("Tore" "Torleif")) (20 . ("Sibylla" "Camilla")) (21 . ("Birger" "Börje")) (22 . ("Marika" "Marita")) (23 . ("Sören" "Severin")) (24 . ("Evert" "Eilert")) (25 . ("Inga" "Ingvald")) (26 . ("Amanda" "My")) (27 . ("Sabina" "Ina")) (28 . ("Simon" "Simone")) (29 . ("Viola" "Vivi")) (30 . ("Elsa" "Elsie")) (31 . ("Edit" "Edgar")) )) (11 . ( (1 . ("Andre" "Andrea")) (2 . ("Tobias" "Toini")) (3 . ("Hubert" "Diana")) (4 . ("Uno" "Unn")) (5 . ("Eugen" "Eugenia")) (6 . ("Gustav Adolf")) (7 . ("Ingegerd" "Ingela")) (8 . ("Vendela" "Vanda")) (9 . ("Teodor" "Ted")) (10 . ("Martin" "Martina")) (11 . ("Mårten")) (12 . ("Konrad" "Kurt")) (13 . ("Kristian" "Krister")) (14 . ("Emil" "Mildred")) (15 . ("Katja" "Nadja")) (16 . ("Edmund" "Gudmund")) (17 . ("Naemi" "Nancy")) (18 . ("Pierre" "Percy")) (19 . ("Elisabet" "Lisbeth")) (20 . ("Pontus" "Pia")) (21 . ("Helga" "Olga")) (22 . ("Cecilia" "Cornelia")) (23 . ("Klemens" "Clarence")) (24 . ("Gudrun" "Runar")) (25 . ("Katarina" "Carina")) (26 . ("Linus" "Love")) (27 . ("Astrid" "Asta")) (28 . ("Malte" "Malkolm")) (29 . ("Sune" "Synnöve")) (30 . ("Anders" "Andreas")) )) (12 . ( (1 . ("Oskar" "Ossian")) (2 . ("Beata" "Beatrice")) (3 . ("Lydia" "Carola")) (4 . ("Barbro" "Barbara")) (5 . ("Sven" "Svante")) (6 . ("Nikolaus" "Niklas")) (7 . ("Angelika" "Angela")) (8 . ("Virginia" "Vera")) (9 . ("Anna" "Annie")) (10 . ("Malin" "Malena")) (11 . ("Daniel" "Dan")) (12 . ("Alexander" "Alex")) (13 . ("Lucia")) (14 . ("Sten" "Stig")) (15 . ("Gottfrid" "Gotthard")) (16 . ("Assar" "Astor")) (17 . ("Inge" "Ingemund")) (18 . ("Abraham" "Efraim")) (19 . ("Isak" "Rebecka")) (20 . ("Israel" "Moses")) (21 . ("Tomas" "Tom")) (22 . ("Natanael" "Natalia")) (23 . ("Adam")) (24 . ("Eva")) (25 . ()) (26 . ("Stefan" "Staffan")) (27 . ("Johannes" "Hannes")) (28 . ("Rakel" "Benjamin")) (29 . ("Abel" "Set")) (30 . ("Gunlög" "Åslög")) (31 . ("Sylvester")) )))) (lyskom-define-namedays 'fi "Finska" "\ Namnsdagar ur någon finsk namnlängd. Eftersom utvecklarna inte kan finska är beskrivningen på svenska, med förhoppningen att någon som kan finska kommer att reta sig på den och skriva om texten på rätt språk." '((1 . ((1 . ()) (2 . ("Aapeli")) (3 . ("Elmeri" "Elmer" "Elmo")) (4 . ("Ruut")) (5 . ("Lea" "Leea")) (6 . ("Harri")) (7 . ("Aukusti" "Aku" "August")) (8 . ("Hilppa" "Titta")) (9 . ("Veikko" "Veli" "Veijo")) (10 . ("Nyyrikki")) (11 . ("Kari" "Karri")) (12 . ("Toini")) (13 . ("Nuutti")) (14 . ("Sakari" "Saku")) (15 . ("Solja")) (16 . ("Ilmari" "Ilmo")) (17 . ("Toni" "Anttoni" "Antto" "Anton")) (18 . ("Laura")) (19 . ("Heikki" "Henrik" "Henrikki" "Henri")) (20 . ("Henna" "Henni" "Henriikka")) (21 . ("Aune" "Oona" "Auni")) (22 . ("Visa")) (23 . ("Eine" "Eini" "Enni")) (24 . ("Senja")) (25 . ("Paavo" "Pauli" "Paavali" "Paul")) (26 . ("Joonatan")) (27 . ("Viljo")) (28 . ("Kaarlo" "Kalle" "Kaarle" "Mies")) (29 . ("Valtteri")) (30 . ("Irja")) (31 . ("Alli")) )) (2 . ( (1 . ("Riitta")) (2 . ("Aamu" "Jemina")) (3 . ("Valo")) (4 . ("Armi" "Ronja")) (5 . ("Asser")) (6 . ("Terhi" "Teija" "Tiia" "Tea" "Terhikki")) (7 . ("Riku" "Rikhard")) (8 . ("Laina")) (9 . ("Raija" "Raisa")) (10 . ("Elina" "Elna" "Ella" "Ellen")) (11 . ("Talvikki")) (12 . ("Elma" "Elmi")) (13 . ("Sulo" "Sulho")) (14 . ("Voitto" "Valentin" "Tino")) (15 . ("Sipi" "Sippo")) (16 . ("Kai")) (17 . ("Väinö" "Väonämö")) (18 . ("Kaino")) (19 . ("Eija")) (20 . ("Heli" "Helinä" "Heljä" "Hely")) (21 . ("Keijo")) (22 . ("Tuulikki" "Tuuli" "Tuulia")) (23 . ("Aslak")) (24 . ("Matti" "Matias")) (25 . ("Tuija" "Tuire")) (26 . ("Nestori")) (27 . ("Torsti")) (28 . ("Onni")) )) (3 . ( (1 . ("Alpo" "Alvi" "Alpi")) (2 . ("Virve" "Virva")) (3 . ("Kauko")) (4 . ("Ari" "Arsi" "Atro")) (5 . ("Laila" "Leila")) (6 . ("Tarmo")) (7 . ("Tarja" "Taru")) (8 . ("Vilppu")) (9 . ("Auvo")) (10 . ("Aurora" "Aura" "Auri")) (11 . ("Kalervo")) (12 . ("Reijo" "Reko")) (13 . ("Erno" "Tarvo" "Ernesti")) (14 . ("Matilda" "Tilda")) (15 . ("Risto")) (16 . ("Ilkka")) (17 . ("Kerttu" "Kerttuli")) (18 . ("Eetu" "Edvard")) (19 . ("Jooseppi" "Juuso" "Joosef" "Josefiina")) (20 . ("Aki" "Joakim" "Kim" "Jaakkima")) (21 . ("Pentti")) (22 . ("Vihtori")) (23 . ("Akseli")) (24 . ("Kaapo" "Gabriel" "Kaapro" "Kaappo")) (25 . ("Aija")) (26 . ("Manu" "Immanuel" "Manne" "Immo")) (27 . ("Sauli" "Saul")) (28 . ("Armas")) (29 . ("Joonas" "Jouni" "Joni" "Joonas" "Jonne" "Jonni")) (30 . ("Usko")) (31 . ("Irma" "Irmeli")) )) (4 . ( (1 . ("Raita" "Pulmu")) (2 . ("Pellervo")) (3 . ("Sampo")) (4 . ("Ukko")) (5 . ("Irene" "Irina" "Ira" "Iro")) (6 . ("Vilho" "Ville" "Viljami" "Vilhelm" "Vili" "Jami")) (7 . ("Allan" "Ahvo")) (8 . ("Suoma" "Suometar")) (9 . ("Elias" "Eelis" "Eljas")) (10 . ("Tero")) (11 . ("Verna")) (12 . ("Julius" "Julia" "Juliaana")) (13 . ("Tellervo")) (14 . ("Taito")) (15 . ("Lina" "Tuomi")) (16 . ("Jalo" "Patrik")) (17 . ("Otto")) (18 . ("Valto" "Valdemar")) (19 . ("Pälvi" "Pilvi")) (20 . ("Lauha")) (21 . ("Anssi" "Anselmi")) (22 . ("Alina")) (23 . ("Yrjö" "Jyrki" "Jyri" "Yrjänä" "Jori")) (24 . ("Pertti" "Albert" "Altti")) (25 . ("Markku" "Markus" "Marko")) (26 . ("Terttu" "Teresa")) (27 . ("Merja")) (28 . ("Ilpo" "Ilppo" "Tuure")) (29 . ("Teijo")) (30 . ("Mirja" "Mirva" "Mira" "Miia" "Mirjami" "Mirka" "Mirkka")) )) (5 . ( (1 . ("Vappu" "Valpuri")) (2 . ("Vuokko" "Viivi")) (3 . ("Outi")) (4 . ("Ruusu" "Roosa")) (5 . ("Maini")) (6 . ("Ylermi")) (7 . ("Helmi" "Kastehelmi")) (8 . ("Heino")) (9 . ("Timo")) (10 . ("Aino" "Aina" "Ainikki")) (11 . ("Osmo")) (12 . ("Liotta")) (13 . ("Kukka" "Floora")) (14 . ("Tuula")) (15 . ("Sofia" "Sinja" "Sohvi")) (16 . ("Esteri" "Essi" "Ester")) (17 . ("Maila" "Maili" "Mailis" "Rebekka")) (18 . ("Erkki" "Eero" "Eerikki" "Eerika")) (19 . ("Emilia" "Emma" "Emmi" "Milla" "Milja" "Milka" "Amalia")) (20 . ("Lilja" "Karoliina" "Lilli")) (21 . ("Kosti" "Konsta" "Konstantin")) (22 . ("Hemmikki" "Hemmo")) (23 . ("Lyydia" "Lyyli")) (24 . ("Tuukka" "Tuoko")) (25 . ("Urpo")) (26 . ("Vilhelmiina" "Minna" "Vilma" "Miina" "Mimmi")) (27 . ("Ritva")) (28 . ("Alma")) (29 . ("Oiva" "Oivi" "Olivia")) (30 . ("Pasi")) (31 . ("Helka" "Helga")) )) (6 . ( (1 . ("Teemu" "Nikodemus")) (2 . ("Venla")) (3 . ("Orvokki" "Viola")) (4 . ("Toivo")) (5 . ("Sulevi")) (6 . ("Kustaa" "Kyösti" "Kustavi")) (7 . ("Suvi" "Robert" "Roope")) (8 . ("Salomo" "Salomon")) (9 . ("Ensio")) (10 . ("Seppo")) (11 . ("Impi" "Immi")) (12 . ("Esko")) (13 . ("Raili" "Raila")) (14 . ("Kielo")) (15 . ("Vieno" "Viena")) (16 . ("Päivi" "Päivikki" "Päivä")) (17 . ("Urho")) (18 . ("Tapio")) (19 . ("Siiri")) (20 . ("Into")) (21 . ("Ahti" "Ahto")) (22 . ("PaulaLiina" "Pauliina")) (23 . ("Aatto" "Aatu" "Aadolf")) (24 . ("Johannes" "Juhani" "Juha" "Juho" "Jukka" "Jussi" "Janne" "Jani" "Juhana")) (25 . ("Uuno")) (26 . ("Jorm" "Jarmo" "Jarkko" "Jarno" "Jere" "Jeremias")) (27 . ("Elviira" "Elvi")) (28 . ("Leo")) (29 . ("Pietari" "Pekka" "Petri" "Petra" "Petteri" "Pekko")) (30 . ("Päiviö" "Päivö")) )) (7 . ( (1 . ("Aaro" "Aaron")) (2 . ("Maria" "Mari" "Maija" "Meeri" "Maaria" "Marika" "Maiju" "Maikki" "Kukka-Maaria")) (3 . ("Arvo")) (4 . ("Ulla" "Ulpu")) (5 . ("Unto" "Untamo")) (6 . ("Esa" "Esaias")) (7 . ("Klaus" "Launo")) (8 . ("Turo" "Turkka")) (9 . ("Ilta" "Jasmin")) (10 . ("Saima" "Saimi")) (11 . ("Elli" "Noora" "Nelli" "Eleonoora")) (12 . ("Hermanni" "Herkko" "Herman")) (13 . ("Ilari" "Lari" "Joel")) (14 . ("Aliisa")) (15 . ("Rauni" "Rauna")) (16 . ("Reino")) (17 . ("Ossi" "Ossian")) (18 . ("Riikka")) (19 . ("Saara" "Sari" "Salli" "Salla" "Sara")) (20 . ("Marketta" "Maarit" "Reeta" "Maaret" "Reetta" "Margareeta")) (21 . ("Johanna" "Hanna" "Hanne" "Jenni" "Jonna" "Jenna" "Hannele" "Joanna")) (22 . ("Leena" "Leeni" "Lenita" "Matleena")) (23 . ("Oili" "Olga")) (24 . ("Kristiina" "Kirsti" "Tiina" "Kirsi" "Kiia")) (25 . ("Jaakko" "Jaakoppi" "Jaakob")) (26 . ("Martta")) (27 . ("Heidi")) (28 . ("Atso")) (29 . ("Olavi" "Olli" "Uolevi" "Uoti")) (30 . ("Asta")) (31 . ("Helena" "Elena")) )) (8 . ( (1 . ("Maire")) (2 . ("Kimmo")) (3 . ("Linnea" "Nea" "Vanamo")) (4 . ("Veera")) (5 . ("Salme" "Sanelma")) (6 . ("Toimi" "Keimo")) (7 . ("Lahja")) (8 . ("Sylvi" "Sylvia" "Silva")) (9 . ("Erja" "Eira")) (10 . ("Lauri" "Lasse" "Lassi")) (11 . ("Sanna" "Sanni" "Susanna" "Susanne")) (12 . ("Klaara")) (13 . ("Jesse")) (14 . ("Onerva" "Kanerva")) (15 . ("Marjatta" "Marja" "Jaana" "Marjo" "Marjut" "Marjaana" "Marjukka" "Marita" "Maritta" "Marianne" "Marianna")) (16 . ("Aulis")) (17 . ("Verneri")) (18 . ("Leevi")) (19 . ("Mauno" "Maunu")) (20 . ("Samuli" "Sami" "Samuel" "Samu")) (21 . ("Soini" "Veini")) (22 . ("Iivari" "Iivo")) (23 . ("Varma" "Signe")) (24 . ("Perttu")) (25 . ("Loviisa")) (26 . ("Ilma" "Ilmi" "Ilmatar")) (27 . ("Rauli")) (28 . ("Tauno")) (29 . ("Iines" "Iina" "Iinari")) (30 . ("Eemil" "Eemeli")) (31 . ("Arvi")) )) (9 . ( (1 . ("Pirkka")) (2 . ("Sinikka" "Sini")) (3 . ("Soili" "Soile" "Soila")) (4 . ("Ansa")) (5 . ("Roni" "Mainio")) (6 . ("Asko")) (7 . ("Miro" "Arho" "Arhippa")) (8 . ("Taimi")) (9 . ("Eevert" "Isto")) (10 . ("Kalevi" "Kaleva")) (11 . ("Aleksanteri" "Ali" "Ale" "Aleksandra")) (12 . ("Valma" "Vilja")) (13 . ("Orvo")) (14 . ("Iida")) (15 . ("Sirpa")) (16 . ("Hellevi" "Hillevi" "Hille" "Hilla")) (17 . ("Aili" "Aila")) (18 . ("Tyyne" "Tytti" "Tyyni")) (19 . ("Reija")) (20 . ("Varpu" "Vaula")) (21 . ("Mervi")) (22 . ("Mauri")) (23 . ("Mielikki")) (24 . ("Alvar" "Auno")) (25 . ("Kullervo")) (26 . ("Kuisma")) (27 . ("Vesa")) (28 . ("Arja")) (29 . ("Mikael" "Mikko" "Miika" "Miikka" "Miska" "Mikaela")) (30 . ("Sorja" "Sirja")) )) (10 . ( (1 . ("Rauno" "Rainer" "Raine" "Raino")) (2 . ("Valio")) (3 . ("Raimo")) (4 . ("Saila" "Saija")) (5 . ("Inkeri" "Inka")) (6 . ("Minttu" "Pinja")) (7 . ("Pirkko" "Pirjo" "Piritta" "Pirita" "Birgitta")) (8 . ("Hilja")) (9 . ("Ilona")) (10 . ("Aleksi" "Aleksis")) (11 . ("Otso" "Ohto")) (12 . ("Aarre" "Aarto")) (13 . ("Taina" "Tanja" "Taija")) (14 . ("Elsa" "Else" "Elsi")) (15 . ("Helvi" "Heta")) (16 . ("Sirkka" "Sirkku")) (17 . ("Saini" "Saana")) (18 . ("Satu" "Säde")) (19 . ("Uljas")) (20 . ("Kauno" "Kasperi")) (21 . ("Ursula")) (22 . ("Anja" "Anita" "Anniina" "Anitta")) (23 . ("Severi")) (24 . ("Asmo" "Rasmus")) (25 . ("Sointu")) (26 . ("Amanda" "Niina" "Manta")) (27 . ("Helli" "Hellä" "Hellin" "Helle")) (28 . ("Simo")) (29 . ("Alfred" "Urmas")) (30 . ("Eila")) (31 . ("Artturi" "Arto" "Arttu")) )) (11 . ( (1 . ("Pyry" "Lyly")) (2 . ("Topi" "Topias")) (3 . ("Terho")) (4 . ("Hertta")) (5 . ("Reima")) (6 . ("Kustaa Aadolf")) (7 . ("Taisto")) (8 . ("Aatos")) (9 . ("Teuvo")) (10 . ("Martti")) (11 . ("Panu")) (12 . ("Virpi")) (13 . ("Ano" "Kristian")) (14 . ("Iiris")) (15 . ("Janika" "Janita" "Janina" "Janette")) (16 . ("Aarne" "Aarno" "Aarni")) (17 . ("Eino" "Einari")) (18 . ("Tenho" "Jousia")) (19 . ("Elisabet" "Liisa" "Eliisa" "Elisa" "Elise" "Liisi")) (20 . ("Jalmari" "Jari")) (21 . ("Hilma")) (22 . ("Silja" "Selja")) (23 . ("Ismo")) (24 . ("Lempi" "Lemmikki" "Sivi")) (25 . ("Katri" "Kaisa" "Kaija" "Katja" "Kaarina" "Katariina" "Katriina" "Kati" "Kaisu" "Riina")) (26 . ("Sisko")) (27 . ("Hilkka")) (28 . ("Heini")) (29 . ("Aimo")) (30 . ("Antti" "Antero" "Atte")) )) (12 . ( (1 . ("Oskari")) (2 . ("Anelma" "Unelma")) (3 . ("Vellamo" "Meri")) (4 . ("Airi" "Aira")) (5 . ("Selma")) (6 . ("Niilo" "Nikolai" "Niko" "Niklas")) (7 . ("Sampsa")) (8 . ("Kyllikki" "Kylli")) (9 . ("Anna" "Anne" "Anni" "Anu" "Annikki" "Anneli" "Annukka" "Annika")) (10 . ("Jutta")) (11 . ("Taneli" "Tatu" "Daniel")) (12 . ("Tuovi")) (13 . ("Seija")) (14 . ("Jouko")) (15 . ("Heimo")) (16 . ("Auli" "Aulikki" "Aada")) (17 . ("Raakel")) (18 . ("Aapo" "Aappo" "Rami")) (19 . ("Iikka" "Iiro" "Iisakki" "Isko")) (20 . ("Benjamin" "Kerkko")) (21 . ("Tuomas" "Tuomo" "Tommi" "Tomi")) (22 . ("Raafael")) (23 . ("Senni")) (24 . ("Aatami" "Eeva" "Eevi" "Eveliina")) (25 . ()) (26 . ("Tapani" "Teppo" "Tahvo")) (27 . ("Hannu" "Hannes")) (28 . ("Piia")) (29 . ("Rauha")) (30 . ("Daavid" "Taavetti" "Taavi")) (31 . ("Sylvester" "Silvo")) )))) (lyskom-define-namedays 'fi-sv "Finlandssvenska" "\ Namnsdagar enligt någon finlandssvensk namnlängd." '((1 . ((1 . ()) (2 . ("Gehard" "Gert")) (3 . ("Elmer" "Helmer")) (4 . ("Rut")) (5 . ("Lea")) (6 . ("Harry" "Harriet")) (7 . ("August" "Augusta")) (8 . ("Gunnar")) (9 . ("Bror")) (10 . ("Sigurd")) (11 . ("Osvald")) (12 . ("Eivor")) (13 . ("Knut")) (14 . ("Zacharias")) (15 . ("Doris")) (16 . ("Gudmund" "Germund")) (17 . ("Anton" "Tony" "Antonia")) (18 . ("Laura")) (19 . ("Henrik" "Henry" "Henrika" "Henrietta")) (20 . ("Sebastian" "Fabian")) (21 . ("Agnes" "Agneta")) (22 . ("Fridolf")) (23 . ("Ingegerd" "Ingela")) (24 . ("Jarl")) (25 . ("Paul")) (26 . ("Jonatan")) (27 . ("Folke")) (28 . ("Karl" "Carola")) (29 . ("Valter" "Volter")) (30 . ("Gunnel" "Gunilla")) (31 . ("Alfhild" "Alfa")) )) (2 . ( (1 . ("Berit")) (2 . ("Disa")) (3 . ("Hugo")) (4 . ("My" "Ronja")) (5 . ("Sture")) (6 . ("Dorotea" "Dora" "Tea" "Dorrit")) (7 . ("Rikard" "Dick")) (8 . ("Rigmor")) (9 . ("Bodil")) (10 . ("Elin" "Ellen" "Ella" "Elna")) (11 . ("Isabella" "Isa")) (12 . ("Elma")) (13 . ("Algot")) (14 . ("Valenton")) (15 . ("Sigfrid")) (16 . ("Kaj")) (17 . ("Carita" "Rita")) (18 . ("Tyra")) (19 . ("Fritjof")) (20 . ("Ragnborg")) (21 . ("Alf" "Alva")) (22 . ("Hildur" "Hilda")) (23 . ("Bjarne")) (24 . ("Mattias" "Mats")) (25 . ("Jessica")) (26 . ("Ingvar" "Ingvald")) (27 . ("Torsten")) (28 . ("Rune" "Runa")) )) (3 . ( (1 . ("Albin")) (2 . ("Fanny")) (3 . ("Torbjörn")) (4 . ("Adrian" "Atle")) (5 . ("Laila" "Leila")) (6 . ("Rudolf" "Rolf")) (7 . ("Gudrun")) (8 . ("Filip" "Filippa")) (9 . ("Edvin")) (10 . ("Aurora")) (11 . ("Torgny" "Torkel")) (12 . ("Gregorius" "Greger" "Grels")) (13 . ("Ernst")) (14 . ("Matilda")) (15 . ("Kristoffer")) (16 . ("Herbert")) (17 . ("Gertrud" "Trude")) (18 . ("Edvard")) (19 . ("Josef" "Josefina")) (20 . ("Joakim" "Kim")) (21 . ("Bengt" "Bengta" "Benita")) (22 . ("Viktor" "Viktoria")) (23 . ("Axel")) (24 . ("Gabriel" "Gabriella")) (25 . ("Gunvor" "Gunnevi")) (26 . ("Emanuel" "Immanuel" "Manne")) (27 . ("Torvald")) (28 . ("Sune")) (29 . ("Jonas")) (30 . ("Tage" "Guy")) (31 . ("Irma" "Irmelin")) )) (4 . ( (1 . ("Harald")) (2 . ("Vidar")) (3 . ("Ferdinand")) (4 . ("Odin")) (5 . ("Irene")) (6 . ("Vilhelm" "William")) (7 . ("Allan")) (8 . ("Rea")) (9 . ("Elias" "Elis" "Eliel")) (10 . ("Tryggve")) (11 . ("Verna")) (12 . ("Julius" "Julia" "Juliana")) (13 . ("Etel")) (14 . ("Ruben")) (15 . ("Linda" "Linn")) (16 . ("Patrik" "Patricia")) (17 . ("Otto")) (18 . ("Valdemar" "Volmar")) (19 . ("Bernhard" "Bernt")) (20 . ("Arla")) (21 . ("Camilla")) (22 . ("Alina")) (23 . ("Georg" "Gäran" "Örjan" "Jöran" "Jörgen" "Jörn")) (24 . ("Albert" "Albertina")) (25 . ("Markus")) (26 . ("Teresia" "Teresa" "Terese")) (27 . ("Engelbrekt" "Engelbert")) (28 . ("Ture")) (29 . ("Henning")) (30 . ("Mirjam" "Mia")) )) (5 . ( (1 . ("Valborg")) (2 . ("Vivan" "Vivi")) (3 . ("Linus")) (4 . ("Rosa")) (5 . ("Ulrik")) (6 . ("Frej" "Frejvid" "Freja")) (7 . ("Tua")) (8 . ("Åke")) (9 . ("Dennis")) (10 . ("Aina" "Aino")) (11 . ("Kennet" "Kent")) (12 . ("Charlotta" "Lotta" "Lotten")) (13 . ("Flora")) (14 . ("Edit")) (15 . ("Sofia" "Sonja")) (16 . ("Ester")) (17 . ("Rebecka" "Hagar")) (18 . ("Erik" "Jerker" "Erika")) (19 . ("Emilia" "Emma" "Amalia" "Mili")) (20 . ("Karolina" "Lilli" "Lilian")) (21 . ("Konstantin" "Conny")) (22 . ("Hemming")) (23 . ("Lydia")) (24 . ("Alarik")) (25 . ("Urban")) (26 . ("Vilhelmina" "Minna")) (27 . ("Ingeborg")) (28 . ("Alma")) (29 . ("Orvar" "Oliver" "Olivia")) (30 . ("Rurik")) (31 . ("Helge" "Helga")) )) (6 . ( (1 . ("Rabbe")) (2 . ("Vendla")) (3 . ("Viola")) (4 . ("Selim")) (5 . ("Stig")) (6 . ("Gustav" "Gösta" "Gustava")) (7 . ("Robert" "Robin")) (8 . ("Kjell" "Kettil")) (9 . ("Dag" "Daga")) (10 . ("Svante")) (11 . ("Hjördis")) (12 . ("Eskil")) (13 . ("Åsa" "Aslög")) (14 . ("Tord")) (15 . ("Mona" "Monika")) (16 . ("Eugen")) (17 . ("Birger" "Börje")) (18 . ("Ingolf")) (19 . ("Sigrid" "Siri")) (20 . ("Inga")) (21 . ("Ingemar" "Ingmar" "Inge")) (22 . ("Paula" "Paulina" "Lina")) (23 . ("Adolf")) (24 . ("Johannes" "Johan" "Jan" "Jon" "John" "Johnny" "Jens")) (25 . ("Uno")) (26 . ("Viveka")) (27 . ("Elvira" "Elvi")) (28 . ("Leo" "Leopold")) (29 . ("Peter" "Per" "Pette" "Petra" "Pernilla")) (30 . ("Leif")) )) (7 . ( (1 . ("Kasimir")) (2 . ("Maria" "Marika" "Maja" "Maj" "Mary")) (3 . ("Egil" "Ejvind" "Öjvind")) (4 . ("Ulrika" "Ulla")) (5 . ("Ulf")) (6 . ("Halvar")) (7 . ("Klas" "Klaus")) (8 . ("Tor" "Tore" "Tora")) (9 . ("Nanna" "Nanny")) (10 . ("Saima" "Saimi")) (11 . ("Eleonora" "Nora" "Leonora" "Elli" "Ellinor")) (12 . ("Herman")) (13 . ("Joel")) (14 . ("Alice")) (15 . ("Ragnhild" "Ragni" "Ragna")) (16 . ("Reinhold")) (17 . ("Ossian")) (18 . ("Fredrik" "Fred" "Fredrika")) (19 . ("Sara" "Sally")) (20 . ("Margareta" "Margit" "Marit" "Greta" "Gretel")) (21 . ("Johanna" "Joanna" "Jonna" "Jenny" "Hanna" "Hannele")) (22 . ("Magdalena" "Malin" "Lena")) (23 . ("Olga")) (24 . ("Kristina" "Kerstin" "Kristel" "Kia" "Stina" "Tina")) (25 . ("Jakob" "Jim")) (26 . ("Marta")) (27 . ("Heidi")) (28 . ("Håkan")) (29 . ("Olof" "Olav" "Ola" "Ole" "Olle")) (30 . ("Asta")) (31 . ("Helena")) )) (8 . ( (1 . ("Gerda" "Gerd")) (2 . ("Holger")) (3 . ("Linnea")) (4 . ("Vera")) (5 . ("Gurli")) (6 . ("Sixten")) (7 . ("Yrsa")) (8 . ("Sylvia")) (9 . ("Eira" "Natalie")) (10 . ("Lars")) (11 . ("Susanna" "Susanne" "Sanna")) (12 . ("Klara")) (13 . ("Alfons")) (14 . ("Svea")) (15 . ("Marita" "Marianne" "Marlene")) (16 . ("Brynolf")) (17 . ("Verner" "Veronika")) (18 . ("Bo")) (19 . ("Magnus" "Måns")) (20 . ("Samuel" "Sam")) (21 . ("Sven")) (22 . ("Ivar")) (23 . ("Signe" "Signhild")) (24 . ("Bertel" "Bertil" "Berta")) (25 . ("Lovisa" "Louise")) (26 . ("Märta" "Märit")) (27 . ("Ralf" "Rufus")) (28 . ("Hilding")) (29 . ("Ines" "Ina")) (30 . ("Emil")) (31 . ("Arvid")) )) (9 . ( (1 . ("Gottfrid")) (2 . ("Sunnöve")) (3 . ("Solveig")) (4 . ("Roland")) (5 . ("Ragnvald" "Ronald" "Ronny")) (6 . ("Felix")) (7 . ("Regina" "Roy")) (8 . ("Göte" "Göta")) (9 . ("Evert")) (10 . ("Östen")) (11 . ("Alexander" "Alex" "Alexandra" "Sandra")) (12 . ("Dagny")) (13 . ("Ylva")) (14 . ("Ida")) (15 . ("Runar")) (16 . ("Hellevi" "Hillevi" "Helvig")) (17 . ("Hildegard" "Hildegerd")) (18 . ("Pamela")) (19 . ("Torborg")) (20 . ("Erna")) (21 . ("Gunborg" "Gunlög")) (22 . ("Mauritz" "Moritz")) (23 . ("Tekla")) (24 . ("Alvar")) (25 . ("Sigvard")) (26 . ("Finn")) (27 . ("Torolf")) (28 . ("Leonard" "Lennart")) (29 . ("Mikael" "Mikaela")) (30 . ("Roger")) )) (10 . ( (1 . ("Ragnar" "Rainer")) (2 . ("Ludvig")) (3 . ("Evald")) (4 . ("Frans" "Frank")) (5 . ("Ingrid" "Inger")) (6 . ("Bruno")) (7 . ("Birgitta" "Brita" "Britta" "Britt" "Birgit")) (8 . ("Peik")) (9 . ("Marina")) (10 . ("Alexis")) (11 . ("Björn")) (12 . ("Valfrid")) (13 . ("Ebbe" "Ebba")) (14 . ("Elsa" "Else" "Ilse")) (15 . ("Hedvig" "Hedda")) (16 . ("Stella")) (17 . ("Vesta" "Diana")) (18 . ("Saga")) (19 . ("Viking")) (20 . ("Kasper" "Jesper")) (21 . ("Ursula")) (22 . ("Anita" "Anja")) (23 . ("Severin" "Sören")) (24 . ("Fjalar" "Rasmus")) (25 . ("Yvonne")) (26 . ("Amanda" "Nina" "Ninni")) (27 . ("Sabina")) (28 . ("Simon")) (29 . ("Alfred")) (30 . ("Jennifer")) (31 . ("Artur")) )) (11 . ( (1 . ("Gun" "Gunhild")) (2 . ("Tobias")) (3 . ("Erland")) (4 . ("Carina")) (5 . ("Torhild")) (6 . ("Gustav Adolf")) (7 . ("Glenn")) (8 . ("Styrbjörn")) (9 . ("Teodor" "Theo")) (10 . ("Martin" "Mårten" "Martina")) (11 . ("Boris")) (12 . ("Konrad" "Kurt")) (13 . ("Kristian" "Krister")) (14 . ("Iris")) (15 . ("Janina" "Jannika" "Jeanette")) (16 . ("Arne" "Arnold" "Arna")) (17 . ("Einar" "Enar")) (18 . ("Max")) (19 . ("Elisabet" "Lisa" "Lisen" "Lisbet" "Elise")) (20 . ("Hjalmar" "Pontus")) (21 . ("Hilma")) (22 . ("Cecilia")) (23 . ("Yngve" "Yngvar")) (24 . ("Siv")) (25 . ("Katarina" "Karin" "Kajsa" "Katja")) (26 . ("Dagmar")) (27 . ("Astrid" "Estrid")) (28 . ("Sten")) (29 . ("Edgar")) (30 . ("Anders" "Andreas" "André" "Andrea")) )) (12 . ( (1 . ("Oskar")) (2 . ("Beata" "Beatrice")) (3 . ("Urda")) (4 . ("Barbara" "Barbro")) (5 . ("Selma")) (6 . ("Nils" "Niklas")) (7 . ("Agata" "Agda" "Ågot")) (8 . ("Magnhild" "Magna")) (9 . ("Anna" "Anni" "Anne" "Annika" "Anneli" "Annette")) (10 . ("Judit" "Jutta")) (11 . ("Daniel" "Dan" "Daniela")) (12 . ("Tove")) (13 . ("Lucia")) (14 . ("Ove")) (15 . ("Sverker")) (16 . ("Ada" "Adele")) (17 . ("Rakel")) (18 . ("Abraham")) (19 . ("Isak")) (20 . ("Benjamin" "Ben" "Benny")) (21 . ("Tomas" "Tom" "Tommy")) (22 . ("Rafael")) (23 . ("Elof")) (24 . ("Adam" "Eva")) (25 . ()) (26 . ("Stefan" "Staffan")) (27 . ("Hans")) (28 . ("Pia")) (29 . ("Frida")) (30 . ("David")) (31 . ("Sylvester")) )))) (lyskom-define-namedays 'hu "Magyar" "\ Namnsdagar ur någon ungersk namnlängd. Eftersom utvecklarna inte kan ungerska så är beskrivningen på svenska, med förhoppningen att någon som kan ungerska kommer att reta sig på den och skriva om texten på rätt språk." '((1 . ( (1 . ("Fruzsina")) (2 . ("Ábel")) (3 . ("Genovéna" "Benjámin")) (4 . ("Titusz" "Leóna" "Angéla")) (5 . ("Simon" "Amata")) (6 . ("Boldizsár")) (7 . ("Attila" "Ramóna")) (8 . ("Gyöngyvér")) (9 . ("Marcell")) (10 . ("Melánia")) (11 . ("Ágota")) (12 . ("Ernõ")) (13 . ("Veronika")) (14 . ("Bódog")) (15 . ("Lóránt" "Lóránd")) (16 . ("Gusztáv")) (17 . ("Antal" "Antónia")) (18 . ("Piroska")) (19 . ("Sára" "Márió")) (20 . ("Fábián" "Sebestyén")) (21 . ("Ágnes")) (22 . ("Vince" "Artúr" "Anasztáz")) (23 . ("Zelma" "Rajmund")) (24 . ("Timót")) (25 . ("Pál")) (26 . ("Vanda" "Paula")) (27 . ("Angelika" "Angéla")) (28 . ("Károly" "Karola")) (29 . ("Adél")) (30 . ("Martina" "Gerda")) (31 . ("Marcella")) )) (2 . ( (1 . ("Ignác")) (2 . ("Karolina" "Aida")) (3 . ("Balázs")) (4 . ("Ráhel" "Csenge" "András")) (5 . ("Ágota" "Ingrid")) (6 . ("Dorottya" "Dóra" "Ajándék" "Amanda")) (7 . ("Tódor" "Rómeó")) (8 . ("Aranka")) (9 . ("Abigél" "Alex")) (10 . ("Elvira")) (11 . ("Bertold" "Marietta" "Adolf")) (12 . ("Lívia" "Lídia")) (13 . ("Ella" "Linda")) (14 . ("Bálint" "Valentin")) (15 . ("Kolos" "Georgina")) (16 . ("Julianna" "Lilla")) (17 . ("Donát")) (18 . ("Bernadett")) (19 . ("Zsuzsanna")) (20 . ("Aladár" "Álmos" "Amata")) (21 . ("Eleonóra")) (22 . ("Gerzson")) (23 . ("Alfréd")) (24 . ("Mátyás")) (25 . ("Géza")) (26 . ("Edina")) (27 . ("Ákos" "Bátor")) (28 . ("Elemér")) )) (3 . ( (1 . ("Albin" "Albina")) (2 . ("Lujza")) (3 . ("Kornélia")) (4 . ("Kázmér" "Adorján" "Adrián" "Adrienn")) (5 . ("Adorján" "Adrián" "Adrienn")) (6 . ("Leonora" "Inez")) (7 . ("Tamás")) (8 . ("Zoltán")) (9 . ("Franciska" "Fanni")) (10 . ("Ildikó")) (11 . ("Szilárd" "Aladár")) (12 . ("Gergely")) (13 . ("Krisztián" "Ajtóny")) (14 . ("Matild")) (15 . ("Kristóf")) (16 . ("Henrietta")) (17 . ("Gertrúd" "Patrik")) (18 . ("Sándor" "Ede" "Alexandra")) (19 . ("József" "Bánk")) (20 . ("Klaudia")) (21 . ("Benedek")) (22 . ("Beáta" "Izolda")) (23 . ("Emõke")) (24 . ("Gábor" "Karina")) (25 . ("Irén" "Írisz")) (26 . ("Emánuel")) (27 . ("Hajnalka")) (28 . ("Gedeon" "Johanna")) (29 . ("Aguszta")) (30 . ("Zalán" "Amade")) (31 . ("Árpád" "Ajtóny")) )) (4 . ( (1 . ("Hugó")) (2 . ("Áron")) (3 . ("Buda" "Richárd")) (4 . ("Izidor")) (5 . ("Vince")) (6 . ("Vilmos" "Bíborka")) (7 . ("Herman")) (8 . ("Dénes")) (9 . ("Erhard")) (10 . ("Zsolt")) (11 . ("Leó" "Szaniszló")) (12 . ("Gyula")) (13 . ("Ida")) (14 . ("Tibor")) (15 . ("Anasztázia" "Tas")) (16 . ("Csongor")) (17 . ("Rudolf")) (18 . ("Andrea" "Ilma" "András")) (19 . ("Emma")) (20 . ("Tivadar")) (21 . ("Konrád")) (22 . ("Csilla" "Noémi")) (23 . ("Béla")) (24 . ("György")) (25 . ("Márk")) (26 . ("Ervin")) (27 . ("Zita")) (28 . ("Valéria")) (29 . ("Péter" "Albert" "Albertína")) (30 . ("Katalin" "Kitti")) )) (5 . ( (1 . ("Fülöp" "Jakab" "Amarilla")) (2 . ("Zsigmond")) (3 . ("Tímea" "Irma")) (4 . ("Mónika" "Flórián")) (5 . ("Györgyi")) (6 . ("Ivett" "Frida")) (7 . ("Gizella")) (8 . ("Mihály")) (9 . ("Gergely")) (10 . ("Ármin" "Pálma")) (11 . ("Ferenc" "Adolf")) (12 . ("Pongrác")) (13 . ("Szervác" "Imola")) (14 . ("Bonifác")) (15 . ("Zsófia" "Szonja")) (16 . ("Mózes" "Botond")) (17 . ("Paszkál")) (18 . ("Erik" "Alexandra")) (19 . ("Ivó" "Milán")) (20 . ("Bernát" "Felícia")) (21 . ("Konstantin" "András")) (22 . ("Júlia" "Rita")) (23 . ("Dezsõ")) (24 . ("Eszter" "Eliza")) (25 . ("Orbán")) (26 . ("Fülöp" "Evelin" "Amanda")) (27 . ("Hella")) (28 . ("Emil" "Csanád" "Ágoston")) (29 . ("Magdolna")) (30 . ("Janka" "Zsanett")) (31 . ("Angéla" "Petronella")) )) (6 . ( (1 . ("Tünde")) (2 . ("Kármen" "Anita" "Anna" "Annamária")) (3 . ("Klotild")) (4 . ("Bulcsú")) (5 . ("Fatime")) (6 . ("Norbert" "Cintia")) (7 . ("Róbert")) (8 . ("Medárd")) (9 . ("Félix" "Annabella")) (10 . ("Margit" "Gréta")) (11 . ("Barnabás")) (12 . ("Villó")) (13 . ("Antal" "Anett" "Anna")) (14 . ("Vazul")) (15 . ("Jolán" "Vid")) (16 . ("Jusztin")) (17 . ("Laura" "Alida" "Adolf" "Alina" "Alinda")) (18 . ("Arnold" "Levente")) (19 . ("Gyárfás")) (20 . ("Rafael")) (21 . ("Alajos" "Leila" "Aladár" "Aloma")) (22 . ("Paulina")) (23 . ("Zoltán")) (24 . ("Iván")) (25 . ("Vilmos")) (26 . ("János" "Pál")) (27 . ("Lászlo")) (28 . ("Levente" "Irén")) (29 . ("Péter" "Pál")) (30 . ("Pál")) )) (7 . ( (1 . ("Tihamér" "Annamária")) (2 . ("Ottó")) (3 . ("Kornél" "Soma" "Anatol")) (4 . ("Ulrik")) (5 . ("Emese" "Sarolta" "Antal")) (6 . ("Csaba")) (7 . ("Apollonia")) (8 . ("Ellák")) (9 . ("Lukrécia")) (10 . ("Amália" "Alma")) (11 . ("Nóra" "Lili")) (12 . ("Izabella" "Dalma")) (13 . ("Jenõ")) (14 . ("Örs" "Stella")) (15 . ("Henrik" "Roland")) (16 . ("Valter")) (17 . ("Endre" "Elek" "Ajándék" "András")) (18 . ("Frigyes")) (19 . ("Emília")) (20 . ("Íllás")) (21 . ("Dániel" "Daniella")) (22 . ("Magdolna")) (23 . ("Lenke")) (24 . ("Kinga" "Kincsó")) (25 . ("Kristóf" "Jakab")) (26 . ("Anna" "Anikó" "Annamária")) (27 . ("Olga" "Liliana" "Ajtóny")) (28 . ("Szabolcs")) (29 . ("Márta" "Flóra")) (30 . ("Judit" "Xénia")) (31 . ("Oszkár")) )) (8 . ( (1 . ("Boglárka")) (2 . ("Lehel" "Alfonz")) (3 . ("Hermina")) (4 . ("Domonkos" "Dominika")) (5 . ("Krisztina" "Afrodité")) (6 . ("Berta" "Bettína")) (7 . ("Ibolya" "Afrodité")) (8 . ("László")) (9 . ("Emõd")) (10 . ("Lõrinc")) (11 . ("Zsuzsanna" "Tiborc")) (12 . ("Klára")) (13 . ("Ipoly")) (14 . ("Marcell")) (15 . ("Mária")) (16 . ("Ábrahám")) (17 . ("Jácint" "Anasztáz")) (18 . ("Ilona")) (19 . ("Huba")) (20 . ("István")) (21 . ("Sámuel" "Hajna")) (22 . ("Menyhért" "Mirjam")) (23 . ("Bence")) (24 . ("Bertalan")) (25 . ("Lajos" "Patrícia")) (26 . ("Izsó")) (27 . ("Gáspár")) (28 . ("Ágoston")) (29 . ("Beatrix" "Erna")) (30 . ("Rózsa")) (31 . ("Erika" "Bella")) )) (9 . ( (1 . ("Egyed" "Egon")) (2 . ("Rebeka" "Dorina")) (3 . ("Hilda")) (4 . ("Rozália")) (5 . ("Viktor" "Lõrinc" "Alpár")) (6 . ("Zakariás")) (7 . ("Regina")) (8 . ("Mária" "Adrienn" "Adorján" "Adrián")) (9 . ("Ádám" "András")) (10 . ("Nikolett" "Hunor")) (11 . ("Teodóra")) (12 . ("Mária")) (13 . ("Kornél" "Amata")) (14 . ("Szeréna" "Roxána")) (15 . ("Enikõ" "Melitta")) (16 . ("Edit")) (17 . ("Zsófia")) (18 . ("Diána")) (19 . ("Vilhelmina")) (20 . ("Friderika")) (21 . ("Máté" "Mirella")) (22 . ("Móric")) (23 . ("Tekla")) (24 . ("Gellért" "Mercédesz")) (25 . ("Eufrózina" "Kende")) (26 . ("Jusztina")) (27 . ("Adalbert" "Adolf" "Albertina")) (28 . ("Vencel")) (29 . ("Mihály")) (30 . ("Jeromos")) )) (10 . ( (1 . ("Malvin")) (2 . ("Petra")) (3 . ("Helga")) (4 . ("Ferenc")) (5 . ("Aurél")) (6 . ("Brúnó" "Renáta")) (7 . ("Amália")) (8 . ("Koppány")) (9 . ("Dénes")) (10 . ("Gedeon")) (11 . ("Brigitta")) (12 . ("Miksa")) (13 . ("Kálmán" "Ede")) (14 . ("Helén")) (15 . ("Teréz")) (16 . ("Gál")) (17 . ("Hedvig")) (18 . ("Lukács")) (19 . ("Nándor")) (20 . ("Vendel")) (21 . ("Orsolya")) (22 . ("Elõd")) (23 . ("Gyöngyi")) (24 . ("Salamon")) (25 . ("Blanka" "Bianka")) (26 . ("Dömötör")) (27 . ("Szabina")) (28 . ("Simon" "Szimonetta")) (29 . ("Nárcisz")) (30 . ("Alfonz")) (31 . ("Farkas")) )) (11 . ( (1 . ("Marianna")) (2 . ("Achilles")) (3 . ("Gyõzõ")) (4 . ("Károly")) (5 . ("Imre")) (6 . ("Lénárd")) (7 . ("Rezsõ")) (8 . ("Zsombor")) (9 . ("Tivadar")) (10 . ("Réka" "András")) (11 . ("Márton")) (12 . ("Jónás" "Renátó" "Aba")) (13 . ("Szilvia")) (14 . ("Alíz")) (15 . ("Albert" "Lipót")) (16 . ("Ödön")) (17 . ("Hortenzia" "Gergõ")) (18 . ("Jenõ")) (19 . ("Erzsébet")) (20 . ("Jolán")) (21 . ("Olivér")) (22 . ("Cecília")) (23 . ("Kelemen" "Klementína")) (24 . ("Emma")) (25 . ("Katalin" "Alan")) (26 . ("Virág")) (27 . ("Virgil")) (28 . ("Stefánia")) (29 . ("Taksony")) (30 . ("András" "Andor")) )) (12 . ( (1 . ("Elza")) (2 . ("Melinda" "Vivien")) (3 . ("Ferenc")) (4 . ("Borbála" "Barbara")) (5 . ("Vilma")) (6 . ("Miklós")) (7 . ("Ambrus")) (8 . ("Mária")) (9 . ("Natália")) (10 . ("Judit")) (11 . ("Árpád")) (12 . ("Gabriella")) (13 . ("Luca" "Otília")) (14 . ("Szilárda")) (15 . ("Valér")) (16 . ("Etelka" "Aletta" "Albina")) (17 . ("Lázár" "Olimpia")) (18 . ("Auguszta")) (19 . ("Viola")) (20 . ("Teofil")) (21 . ("Tamás")) (22 . ("Zénó")) (23 . ("Viktória")) (24 . ("Ádám" "Éva" "Ada" "Adél")) (25 . ("Eugénia")) (26 . ("István")) (27 . ("János")) (28 . ("Kamilla")) (29 . ("Tamás" "Tamara")) (30 . ("Dávid")) (31 . ("Szilveszter")) )) )) (lyskom-define-namedays 'cz "Czechia" "\ Namnsdagar ur någon tjeckisk namnlängd. Eftersom utvecklarna inte kan tjeckiska så är beskrivningen på svenska, med förhoppningen att någon som kan tjeckiska kommer att reta sig på den och skriva om texten på rätt språk." '((1 . ( (1 . ("Nov-Bý-A rok")) (2 . ("Karina")) (3 . ("Radmila")) (4 . ("Diana")) (5 . ("Dalimil")) (6 . ("T-Bøi-A kr-Bálové"))-A (7 . ("Vilma")) (8 . ("-BÈestmír"))-A (9 . ("Vladan")) (10 . ("B-Bøetislav"))-A (11 . ("Bohdana")) (12 . ("Pravoslav")) (13 . ("Edita")) (14 . ("Radovan")) (15 . ("Alice")) (16 . ("Ctirad")) (17 . ("Drahoslav")) (18 . ("Vladislav")) (19 . ("Doubravka")) (20 . ("Ilona")) (21 . ("B-Bìla"))-A (22 . ("Slavom-Bír"))-A (23 . ("Zden-Bìk"))-A (24 . ("Milena")) (25 . ("Milo-B¹"))-A (26 . ("Zora")) (27 . ("Ingrid")) (28 . ("Ot-Býlie"))-A (29 . ("Zdislava")) (30 . ("Robin")) (31 . ("Marika")) )) (2 . ( (1 . ("Hynek")) (2 . ("Nela")) (3 . ("Bla-B¾ej"))-A (4 . ("Jarmila")) (5 . ("Dobromila")) (6 . ("Vanda")) (7 . ("Veronika")) (8 . ("Milada")) (9 . ("Apolena")) (10 . ("Mojm-Bír"))-A (11 . ("Bo-B¾ena"))-A (12 . ("Slav-Bìna"))-A (13 . ("V-Bìnceslav"))-A (14 . ("Valent-Býn"))-A (15 . ("Ji-Bøina"))-A (16 . ("Ljuba")) (17 . ("Miloslava")) (18 . ("Gizela")) (19 . ("Patrik")) (20 . ("Old-Bøich"))-A (21 . ("Lenka")) (22 . ("Petr")) (23 . ("Svatopluk")) (24 . ("Mat-Bìj"))-A (25 . ("Liliana")) (26 . ("Dora")) (27 . ("Alexandr")) (28 . ("Lum-Bír"))-A )) (3 . ( (1 . ("Alb-Bín"))-A (2 . ("Ane-B¾ka"))-A (3 . ("Kamil")) (4 . ("Stela")) (5 . ("Kazim-Bír"))-A (6 . ("Miroslav")) (7 . ("Tom-Bá¹"))-A (8 . ("Gabriela")) (9 . ("Franti-B¹ka"))-A (10 . ("Viktorie")) (11 . ("And-Bìla"))-A (12 . ("-BØehoø"))-A (13 . ("R-Bù¾ena"))-A (14 . ("Matylda" "R-Bút"))-A (15 . ("Ida")) (16 . ("Amos")) (17 . ("Vlastimil")) (18 . ("Eduard")) (19 . ("Josef")) (20 . ("Sv-Bìtlana"))-A (21 . ("Radek")) (22 . ("Leona")) (23 . ("Ivona")) (24 . ("Gabriel")) (25 . ("Mari-Bán"))-A (26 . ("Emanuel")) (27 . ("Dita")) (28 . ("So-Bòa"))-A (29 . ("Ta-B»ána"))-A (30 . ("Arno-B¹t"))-A (31 . ("Kvido")) )) (4 . ( (1 . ("Hugo")) (2 . ("Erika")) (3 . ("Richard")) (4 . ("Ivana")) (5 . ("Miroslava")) (6 . ("Vendula")) (7 . ("He-Bøman"-A "Herm-Bína"))-A (8 . ("Ema")) (9 . ("Du-B¹an"))-A (10 . ("Darja")) (11 . ("Izabela")) (12 . ("Julius")) (13 . ("Ale-B¹"))-A (14 . ("Vincenc")) (15 . ("Anast-Bázie"))-A (16 . ("Irena")) (17 . ("Rudolf")) (18 . ("Val-Bérie"))-A (19 . ("Rostislav")) (20 . ("Marcela")) (21 . ("Alexandra")) (22 . ("Ev-B¾enie"))-A (23 . ("Vojt-Bìch"))-A (24 . ("Ji-Bøí"))-A (25 . ("Marek")) (26 . ("Oto")) (27 . ("Jaroslav")) (28 . ("Vlastislav")) (29 . ("Robert")) (30 . ("Blahoslav")) )) (5 . ( (1 . ("Sv-Bátek-A pr-Báce"))-A (2 . ("Zikmund")) (3 . ("Alexej")) (4 . ("Kv-Bìtoslav"))-A (5 . ("Klaudie")) (6 . ("Radoslav")) (7 . ("Stanislav")) (8 . ()) (9 . ("Ctibor")) (10 . ("Bla-B¾ena"))-A (11 . ("Svatava")) (12 . ("Pankr-Bác"))-A (13 . ("Serv-Bác"))-A (14 . ("Bonif-Bác"))-A (15 . ("-B®ofie"))-A (16 . ("P-Bøemysl"))-A (17 . ("Aneta")) (18 . ("Nata-B¹a"))-A (19 . ("Ivo")) (20 . ("Zby-B¹ek"))-A (21 . ("Monika")) (22 . ("Emil")) (23 . ("Vladim-Bír"))-A (24 . ("Jana")) (25 . ("Viola")) (26 . ("Filip")) (27 . ("Valdemar")) (28 . ("Vil-Bém"))-A (29 . ("Maximili-Bán"-A "Maxim")) (30 . ("Ferdinand")) (31 . ("Kamila")) )) (6 . ( (1 . ("Laura")) (2 . ("Jarmil")) (3 . ("Tamara")) (4 . ("Dalibor")) (5 . ("Dobroslav")) (6 . ("Norbert")) (7 . ("Iveta")) (8 . ("Medard")) (9 . ("Stanislava")) (10 . ("Gita")) (11 . ("Fl-Bóra"))-A (12 . ("Antonie")) (13 . ("Anton-Bín"))-A (14 . ("Vasil")) (15 . ("V-Bít"))-A (16 . ("Zbyn-Bìk"))-A (17 . ("Adolf")) (18 . ("Milan")) (19 . ("Leo-B¹"))-A (20 . ("Kv-Bìta"))-A (21 . ("Alois")) (22 . ("Pavla")) (23 . ("Zde-Bòka"))-A (24 . ("Jan")) (25 . ("Ivan")) (26 . ("Adriana")) (27 . ("Ladislav")) (28 . ("Lubom-Bír"))-A (29 . ("Petr a Pav")) (30 . ("-B©árka"))-A )) (7 . ( (1 . ("Jaroslava")) (2 . ("Patricie")) (3 . ("Radom-Bír"))-A (4 . ("Prokop")) (5 . ("Cyril")) (6 . ("Jan Hus")) (7 . ("Bohuslava")) (8 . ("Nora")) (9 . ("Drahoslava")) (10 . ("Libu-B¹e"))-A (11 . ("Olga")) (12 . ("Bo-Bøek"))-A (13 . ("Mark-Béta"))-A (14 . ("Karol-Bína"))-A (15 . ("Jind-Bøich"))-A (16 . ("Lubo-B¹"))-A (17 . ("Martina")) (18 . ("Drahom-Bíra"))-A (19 . ("-BÈenìk"))-A (20 . ("Ilja")) (21 . ("V-Bítìzslav"))-A (22 . ("Magdal-Béna"))-A (23 . ("Libor")) (24 . ("Krist-Býna"))-A (25 . ("Jakub")) (26 . ("Anna")) (27 . ("V-Bìroslav"))-A (28 . ("Viktor")) (29 . ("Marta")) (30 . ("Bo-Bøivoj"))-A (31 . ("Ign-Bác"))-A )) (8 . ( (1 . ("Oskar")) (2 . ("Gustav")) (3 . ("Milu-B¹e"))-A (4 . ("Dominik")) (5 . ("Milivoj")) (6 . ("Old-Bøi¹ka"))-A (7 . ("Lada")) (8 . ("Sob-Bìslav"))-A (9 . ("Roman")) (10 . ("Vav-Bøinec"))-A (11 . ("Zuzana")) (12 . ("Kl-Bára"))-A (13 . ("Alena")) (14 . ("Alan")) (15 . ("Hana")) (16 . ("J-Báchym"))-A (17 . ("Petra")) (18 . ("Helena")) (19 . ("Ludv-Bík"))-A (20 . ("Bernard")) (21 . ("Johana")) (22 . ("Bohuslav")) (23 . ("Sandra")) (24 . ("Bartolom-Bìj"))-A (25 . ("Radim")) (26 . ("Lud-Bìk"))-A (27 . ("Otakar")) (28 . ("August-Býn"))-A (29 . ()) (30 . ("-B©tìpán"))-A (31 . ("Pavl-Bína"))-A )) (9 . ( (1 . ("Linda" "Samuel")) (2 . ("Ad-Béla"))-A (3 . ("Bronislav")) (4 . ("Jind-Bøi¹ka"))-A (5 . ("Boris")) (6 . ("Boleslav")) (7 . ("Regina")) (8 . ("Mariana")) (9 . ("Daniela")) (10 . ("Irma")) (11 . ("Denisa")) (12 . ("Marie")) (13 . ("Lubor")) (14 . ("Radka")) (15 . ("Jolana")) (16 . ("Ludmil")) (17 . ("Nad-Bì¾da"))-A (18 . ("Kry-B¹tof"))-A (19 . ("Zita")) (20 . ("Oleg")) (21 . ("Matou-B¹"))-A (22 . ("Darina")) (23 . ("Berta")) (24 . ("Jarom-Bír"))-A (25 . ("Zlata")) (26 . ("Andrea")) (27 . ("Jon-Bá¹"))-A (28 . ("V-Báclav"))-A (29 . ("Michal")) (30 . ("Jeron-Bým"))-A )) (10 . ( (1 . ("Igor")) (2 . ("Ol-Bívie"-A "Galina" "Oliver")) (3 . ("Bohumil")) (4 . ("Franti-B¹ek"))-A (5 . ("Eli-B¹ka"))-A (6 . ("Hanu-B¹"))-A (7 . ("Sergej")) (8 . ("V-Bìra"))-A (9 . ("-B©tefan"-A "S-Bára"))-A (10 . ("Marina")) (11 . ("Andrej")) (12 . ("Marcel")) (13 . ("Ren-Báta"))-A (14 . ("Ag-Báta"))-A (15 . ("Tereza")) (16 . ("Havel")) (17 . ("Hedvika")) (18 . ("Luk-Bá¹"))-A (19 . ("Michaela")) (20 . ("Vendel-Bín"))-A (21 . ("Brigita")) (22 . ("Sabina")) (23 . ("Teodor")) (24 . ("Nina")) (25 . ("Be-Báta"))-A (26 . ("Erik")) (27 . ("-B©arlota"-A "Zoja" "Zoe")) (28 . ()) (29 . ("Silvie")) (30 . ("Tade-Bá¹"))-A (31 . ("-B©tìpánka"))-A )) (11 . ( (1 . ("Felix")) (2 . ("Du-B¹ièky"))-A (3 . ("Hubert")) (4 . ("Karel")) (5 . ("Miriam")) (6 . ("Lib-Bìna"))-A (7 . ("Saskie")) (8 . ("Bohum-Bír"))-A (9 . ("Bohdan")) (10 . ("Ev-B¾en"))-A (11 . ("MArtin")) (12 . ("Benedikt")) (13 . ("Tibor")) (14 . ("S-Báva"))-A (15 . ("Leopold")) (16 . ("Otmar")) (17 . ("Mahulena")) (18 . ("Romana")) (19 . ("Al-B¾bìta"))-A (20 . ("Nikola")) (21 . ("Albert")) (22 . ("Cec-Bílie"))-A (23 . ("Klement")) (24 . ("Em-Bílie"))-A (25 . ("Kate-Bøina"))-A (26 . ("Artur")) (27 . ("Xenie")) (28 . ("Ren-Bé"))-A (29 . ("Zina")) (30 . ("Ond-Bøej"))-A )) (12 . ( (1 . ("Iva")) (2 . ("Blanka")) (3 . ("Svatoslav")) (4 . ("Barbora")) (5 . ("Jitka")) (6 . ("Mikul-Bá¹"))-A (7 . ("Ambro-B¾"-A "Benjam-Bín"))-A (8 . ("Kv-Bìtoslava"))-A (9 . ("Vratislav")) (10 . ("Julie")) (11 . ("Dana")) (12 . ("Simona")) (13 . ("Lucie")) (14 . ("L-Býdie"))-A (15 . ("Radan" "Radana")) (16 . ("Alb-Bína"))-A (17 . ("Daniel")) (18 . ("Miloslav")) (19 . ("Ester")) (20 . ("Dagmar")) (21 . ("Nat-Bálie"))-A (22 . ("-B©imon"))-A (23 . ("Vlasta")) (24 . ("Adam a Eva")) (25 . ("Bo-B¾í-A hod")) (26 . ("-B©tìpán"))-A (27 . ("-B®aneta"))-A (28 . ("Bohumila")) (29 . ("Judita")) (30 . ("David")) (31 . ("Silvestr")) )) )) (lyskom-define-namedays 'fi-orthodox "Finska (ortodoxa)" "\ Namnsdagar ur någon finsk ortodox namnlängd. Eftersom utvecklarna inte kan finska är beskrivningen på svenska, med förhoppningen att någon som kan finska kommer att reta sig på den och skriva om texten på rätt språk." '((1 . ((1 . ("Vasili" "Vilho" "Pasi")) (2 . ("Sylvester" "Tapio" "Serafim")) (3 . ("Malakia" "Harto")) (4 . ("Isto")) (5 . ("Pentti" "Tauno" "Sylvi")) (6 . ()) (7 . ("Johannes" "Juhani" "Juha")) (8 . ("Jyrki" "Yrjö" "Tuomi" "Keijo")) (9 . ("Jehto" "Ilpo" "Filip" "Vilppu" "Heimo")) (10 . ("Riiko" "Marko" "Tommo" "Paavali")) (11 . ("Teo" "Mikael" "Miihkali" "Mikko")) (12 . ("Tatjana" "Tanja" "Taina" "Sauvo")) (13 . ("Jermi" "Tarvo" "Ele")) (14 . ("Aatto" "Aatos" "Benjamin" "Niina")) (15 . ("Paavali" "Paavo" "Johannes" "Juhani")) (16 . ("Leonilla" "Leila")) (17 . ("Anttoni" "Toni")) (18 . ("Ahvo" "Ohvo" "Kirilä" "Kiril")) (19 . ("Makari" "Kari")) (20 . ("Jehki")) (21 . ("Maksima" "Visa" "Jouko" "Valeri" "Auni")) (22 . ("Timo" "Anastisi" "Nasto")) (23 . ("Klemens" "Klementti" "Liimo" "Oiva" "Aatos")) (24 . ("Senja" "Senni" "Seni")) (25 . ("Riiko" "Riku" "Reijo")) (26 . ("Maria" "Marja" "Mari" "Arjo")) (27 . ("Johannes" "Juhani" "Juha")) (28 . ("Raimo" "Reima" "Jehri")) (29 . ("Ignati" "Iknata" "Iikka")) (30 . ("Vasili" "Vilho" "Riiko" "Johannes" "Ilpo")) (31 . ("Kyrö" "Johannes" "Juhani" "Juha" "Nikita" "Niikko" "Ritva")) )) (2 . ( (1 . ("Triifon" "Tuija" "Tua" "Aino")) (2 . ()) (3 . ("Simeoni" "Simana" "Hanna")) (4 . ("Isko" "Jyrki" "Yrjö" "Kirilä" "Kiril")) (5 . ("Helli" "Helvi" "Hellevi" "Tuula" "Tuulikki")) (6 . ("Nyyrikki" "Nyri" "Terhi")) (7 . ("Pertti" "Luukas")) (8 . ("Feodor" "Heikki" "Sakari")) (9 . ("Voitto" "Pellervo")) (10 . ("Kaarle" "Valentina" "Enni" "Anna")) (11 . ("Valassi" "Lassi" "Dimitri" "Miska" "Mitja" "Valto")) (12 . ("Mitjo" "Aleksi" "Aleksis")) (13 . ("Martti")) (14 . ("Soini" "Kiril")) (15 . ("Anssi" "Anto")) (16 . ("Vilkko")) (17 . ("Feodor" "Heikki" "Marianne" "Marjaana")) (18 . ("Leonilla" "Leila")) (19 . ("Arhippa" "Arhi")) (20 . ("Leo" "Agaton" "Oiva")) (21 . ("Timo" "Jesto")) (22 . ("Mauri")) (23 . ("Viljo")) (24 . ("Asmo" "Osmo")) (25 . ("Tarasi")) (26 . ("Pirkka")) (27 . ("Prokko" "Okko")) (28 . ("Vasili" "Vilho" "Kassian" "Kiira")) )) (3 . ( (1 . ("Outi" "Tyyne")) (2 . ("Esko" "Teuvo" "Arseni" "Arsi" "Taila")) (3 . ("Otto" "Kleo" "Pasi")) (4 . ("Arvo")) (5 . ("Kuuno")) (6 . ("Heikko" "Teuvo" "Kosti" "Kyösti" "Viljo")) (7 . ("Ilmari" "Ilmo" "Toivo")) (8 . ("Lasari" "Lasse" "Ahvo" "Ohvo")) (9 . ("Rauli" "Valeri")) (10 . ("Konni" "Galina" "Iina" "Inna")) (11 . ("Roni" "Jehki")) (12 . ("Teo" "Riiko" "Riku" "Reijo")) (13 . ("Nikifor" "Voitto")) (14 . ("Pentti")) (15 . ("Armas")) (16 . ("Savina" "Risto")) (17 . ("Aleksi" "Patrik" "Makari" "Kari")) (18 . ("Kirilä" "Kiril")) (19 . ("Darja" "Tarja" "Larja")) (20 . ("Tinja" "Svetlana")) (21 . ("Jaakko")) (22 . ("Vasili" "Vilho" "Helmi" "Rosita")) (23 . ("Niko" "Lyydia" "Lyyli")) (24 . ("Arto")) (25 . ("Maria" "Mari" "Maija" "Marjatta" "Meeri")) (26 . ("Gabriel" "Kauri" "Alli" "Larissa" "Maisa")) (27 . ("Matja")) (28 . ("Ilari" "Ilkka" "Teppo" "Teppana" "Tapani")) (29 . ("Markus" "Markku" "Kirilä" "Kiril" "Joona" "Joonas")) (30 . ("Johannes" "Juhani" "Juha")) (31 . ("Ylermi")) )) (4 . ( (1 . ("Maria" "Marja" "Mari" "Jehki")) (2 . ("Tiitus" "Tito")) (3 . ("Nikita" "Niikko")) (4 . ("Jyrki" "Yrjö" "Ossi" "Virve" "Virpi")) (5 . ("Turo" "Siro" "Tuulo")) (6 . ("Tyko")) (7 . ("Lippo" "Jyrki" "Yrjö")) (8 . ("Iiro" "Ermo")) (9 . ("Aulis" "Uoti" "Risto" "Anastasia")) (10 . ("Tero")) (11 . ("Antippa")) (12 . ("Vasili" "Vilho")) (13 . ("Arto")) (14 . ("Martti" "Tuomi")) (15 . ("Ari" "Rohkima" "Runo")) (16 . ("Irina" "Irinja" "Irja" "Rauha" "Lempi" "Leonid" "Heini" "Aliisa")) (17 . ("Simeoni" "Simana" "Aake" "Sosima")) (18 . ("Johannes" "Juhani" "Hannele" "Hanni")) (19 . ("Johannes" "Juhani" "Juha" "Nuutti")) (20 . ("Feodor" "Heikki" "Aleksanteri" "Ale")) (21 . ("Jani" "Janne" "Feodor" "Heikki" "Hilppa")) (22 . ("Feodor" "Heikki")) (23 . ("Jyrki" "Yrjö" "Aleksandra" "Sanni" "Sanja")) (24 . ("Elisabet" "Liisa" "Elisa" "Elsa" "Sauvo")) (25 . ("Markus" "Markku")) (26 . ("Vasili" "Vilho" "Teppo" "Teppana" "Tapani")) (27 . ("Simeoni" "Simana")) (28 . ("Jason" "Maksima")) (29 . ("Mauno")) (30 . ("Jaakko" "Ignati")) )) (5 . ( (1 . ("Jere" "Jari" "Jarkko" "Nuutti" "Tamara")) (2 . ("Tamara")) (3 . ("Ahvo" "Ohvo" "Saija" "Soja")) (4 . ("Timo" "Maura" "Teo")) (5 . ("Pelagia" "Alvi" "Alpo")) (6 . ("Irene" "Irina" "Irinja" "Irja" "Rauha")) (7 . ("Jopi" "Job")) (8 . ("Aake")) (9 . ("Johannes" "Juhani" "Arseni ,Arsi")) (10 . ("Esa" "Risto" "Nikolai" "Niko" "Niilo")) (11 . ("Simo" "Taisia" "Taija")) (12 . ("Ilkka" "Kiril" "Kirilä" "Mefodi" "Torsti")) (13 . ("Ilmo" "Herman" "Hemmo")) (14 . ("Lauha" "Isko")) (15 . ("Heimo" "Esa")) (16 . ("Heikki" "Raimo" "Reima" "Muusa")) (17 . ("Jussi" "Antero")) (18 . ("Petri" "Teino" "Klaudia" "Faina" "Julia")) (19 . ("Patrik" "Niila" "Dimitri" "Miska" "Mitja")) (20 . ("Vesa" "Aleksi" "Asko")) (21 . ("Konsta" "Helena" "Mikael" "Feodor")) (22 . ("Pasi")) (23 . ("Mikael" "Mikko" "Leino" "Onni")) (24 . ("Simeoni" "Simana" "Niikko" "Voitto" "Kristian")) (25 . ("Johannes" "Juham Juhani")) (26 . ("Viljo" "Alf" "Jyrki" "Yrjö")) (27 . ("Päivö" "Terho")) (28 . ("Tyko" "Niikko" "Voitto" "Ignati" "Kaino")) (29 . ("Heidi" "Johannes" "Juhani" "Juha")) (30 . ("Iisakki")) (31 . ("Erjo")) )) (6 . ( (1 . ("Usti" "Teino")) (2 . ("Voitto" "Johannes" "Juhani" "Juha")) (3 . ("Valo" "Paula" "Pauliina")) (4 . ("Mitro")) (5 . ("Terho" "Joona" "Joonas" "Igor" "Iikka")) (6 . ("Ilkka" "Ilari" "Vesa" "Visa" "Joonas")) (7 . ("Teuvo" "Eira" "Erja" "Valeria" "Vaula")) (8 . ("Feodor" "Heikki")) (9 . ("Kirilä" "Kiril")) (10 . ("Timo" "Aleksanteri" "Ale" "Antoniina")) (11 . ("Perttu")) (12 . ("Unto" "Pietari" "Petri" "Pekka" "Arseni")) (13 . ("Akuliina" "Alina" "Liina" "Ville")) (14 . ("Eeli" "Torsti")) (15 . ("Aamos" "Joonas" "Aukusti" "Kriska")) (16 . ("Tiihon")) (17 . ("Sauri" "Manuel" "Manu" "Sauli" "Ismo")) (18 . ("Leino" "Onni")) (19 . ("Juuda")) (20 . ("Torsti")) (21 . ("Uljas" "Jesse" "Harras")) (22 . ("Ahri" "Harras")) (23 . ("Ahri" "Aura")) (24 . ("Johannes" "Juhani" "Juha" "Eero")) (25 . ("Rauni" "Pietari" "Petro" "Pekka")) (26 . ("Taavi" "Taavetti")) (27 . ("Johanna" "Jonna" "Sampo" "Sampsa")) (28 . ("Sergei" "Herman" "Kyrö" "Johannes")) (29 . ("Pietari" "Petri" "Pekka" "Paavali" "Paavo" "Pauli")) (30 . ("Andreas" "Simo" "Petri" "Jaakko" "Juha" "Tani" "Matti" "Tuomas")) )) (7 . ( (1 . ("Kosma" "Kuisma" "Tami")) (2 . ("Maria" "Mari" "Maija" "Marja" "Marjatta" "Meeri")) (3 . ("Anto" "Anatoli")) (4 . ("Antti" "Antero" "Martta")) (5 . ("Ahvo" "Ohvo" "Leimu" "Sergei")) (6 . ("Sisso")) (7 . ("Kiia" "Tuomas" "Tuomo")) (8 . ("Prokko" "Okko")) (9 . ("Valto")) (10 . ("Anton" "Anttoni" "Toni")) (11 . ("Jefimia" "Olga" "Oilo" "Helga")) (12 . ("Kauko" "Ilari" "Mikael" "Veronika")) (13 . ("Kauri" "Teppo" "Teppana" "Tapani")) (14 . ("Aki" "Eeli")) (15 . ("Kerkko" "Jutta" "Vladimir")) (16 . ("Teino" "Aila" "Aili")) (17 . ("Marina" "Marketta" "Maarit" "Erho")) (18 . ("Eemeli" "Eemil" "Into")) (19 . ("Riina" "Teijo" "Serafim")) (20 . ("Elias" "Eelis" "Ilja")) (21 . ("Maria" "Johanne" "Juhani" "Juha" "Simeoni" "Simana")) (22 . ("Maria" "Magdaleena")) (23 . ("Rohkima" "Runo" "Viljo" "Tuukka")) (24 . ("Kristiina" "Kirsti" "Kirsi" "Tiina" "Boris")) (25 . ("Anna" "Anni" "Piia" "Ruusa")) (26 . ("Jorma" "Jarmo" "Paraske" "Eeva")) (27 . ("Leimo" "Pauno")) (28 . ("Timo")) (29 . ("Tea" "Teija" "Serafiima" "Fiina")) (30 . ("Silvo" "Herman" "Hemmo" "Valentin")) (31 . ("Kim" "Kimmo")) )) (8 . ( (1 . ("Soile" "Soili" "Ele")) (2 . ("Stefna" "Teemu" "Vasili" "Vilho" "Ville")) (3 . ("Iisakki" "Anton" "Salome" "Salme")) (4 . ("Maksim" "Kustaa" "Martti" "Teino")) (5 . ("Joutsi" "Nonna" "Nanna")) (6 . ()) (7 . ("Tarmo")) (8 . ("Eemeli" "Eemil")) (9 . ("Matias" "Matti" "Herman" "Hemmo")) (10 . ("Lauri")) (11 . ("Susanna" "Sanna")) (12 . ("Huoti")) (13 . ("Maksima" "Tiihon" "Noora" "Tiia")) (14 . ("Miika")) (15 . ("Maria" "Mari" "Maija" "Marja" "Marjatta" "Meeri")) (16 . ("Toimi")) (17 . ("Miro" "Heikki" "Teuvo")) (18 . ("Lauri")) (19 . ("Antti" "Antero")) (20 . ("Samuel" "Samuli")) (21 . ("Tatu" "Assi" "Usko" "Avrami" "Aapo")) (22 . ("Ake" "Laila")) (23 . ("Reino")) (24 . ("Tyko" "Siiri" "Sirkka")) (25 . ("Perttu" "Tiitus" "Tito")) (26 . ("Atro" "Natalia")) (27 . ("Pimen" "Piminä")) (28 . ("Mooses")) (29 . ("Hannes" "Hannu" "Iivo" "Juha" "Juhana")) (30 . ("Ale" "Aleksander" "Paavo" "Pauli")) (31 . ("Kiprian")) )) (9 . ( (1 . ("Simeoni" "Simana" "Joosua")) (2 . ("Johannes" "Juhani" "Veli" "Veikko")) (3 . ("Anto" "Isto" "Ari" "Viici")) (4 . ("Mooses" "Irma" "Irmeli")) (5 . ("Sakari" "Elisabet" "Liisa" "Elisa" "Elsa")) (6 . ("Raisa" "Raija")) (7 . ("Johannes" "Juhani" "Juha")) (8 . ("Maria" "Mari" "Maija" "Marjatta" "Meeri")) (9 . ("Joakim" "Aki" "Anna" "Severi" "Ossi")) (10 . ("Minna" "Miina" "Tuire")) (11 . ("Lahja" "Sergei" "Herman" "Hemmo" "Iia")) (12 . ("Ahti")) (13 . ("Niila" "Vieno")) (14 . ()) (15 . ("Nikita" "Voitto")) (16 . ("Jefimia" "Milla" "Milja")) (17 . ("Veera" "Elpi" "Elvi" "Lempi" "Sofia" "Sonja")) (18 . ("Arja" "Aira" "Airi")) (19 . ("Tuure" "Feodor" "Heikki" "Taavetti" "Taavi" "Konsta" "Kosti")) (20 . ("Jesto" "Mikael" "Mikko" "Olli" "Helge")) (21 . ("Dimitri" "Miska" "Mitja")) (22 . ("Tuukka" "Joona" "Joonas")) (23 . ("Iira" "Raita")) (24 . ("Tekla" "Silvo")) (25 . ("Opri" "Sergei")) (26 . ("Johannes" "Juhani" "Juha")) (27 . ("Kaari")) (28 . ("Hariton" "Harri")) (29 . ("Kyrö")) (30 . ("Riiki" "Riku" "Reijo" "Kaija")) )) (10 . ( (1 . ("Romana" "Sauvo")) (2 . ("Kiprian" "Stiina" "Antti" "Antero")) (3 . ("Teino")) (4 . ("Guri")) (5 . ("Karita" "Pietari" "Petri" "Pekka" "Aleksi" "Joona" "Joonas" "Ilpo")) (6 . ("Tuomas" "Tuomo")) (7 . ("Sergei" "Vaka")) (8 . ("Pelagia" "Laina")) (9 . ("Jaakko" "Antero" "Hannele" "Hanni")) (10 . ("Oula" "Eila")) (11 . ("Ilpo" "Teo" "Siina")) (12 . ("Antero" "Kosma" "Kuisma")) (13 . ("Viljo" "Armi")) (14 . ("Nasari" "Paraske" "Eeva")) (15 . ("Jehki")) (16 . ("Heino")) (17 . ("Antti" "Antero")) (18 . ("Luukas")) (19 . ("Joel")) (20 . ("Artemi" "Arttu" "Arvo")) (21 . ("Iiari" "Ilkka")) (22 . ("Erkki")) (23 . ("Jaakko")) (24 . ("Aarre")) (25 . ("Marko")) (26 . ("Dimitri" "Miska" "Mitja")) (27 . ("Nestori")) (28 . ("Tero" "Neonilla" "Teppo" "Teppana" "Tapani" "Arseni" "Paraske" "Eeva")) (29 . ("Anastasia" "Asta" "Aapo" "Rostislav")) (30 . ("Veijo" "Vilja")) (31 . ("Urpo" "Panu" "Taisto")) )) (11 . ( (1 . ("Kosma" "Kuisma" "Taimi")) (2 . ("Ahto" "Ohto")) (3 . ("Ossi")) (4 . ("Joni" "Jonne" "Kauno")) (5 . ("Joona" "Joonas" "Kai")) (6 . ("Paavali" "Paavo" "Pauli")) (7 . ("Lasari" "Lasse" "Kaisa")) (8 . ("Mikael" "Mika" "Miihkali" "Mikko" "Raafael")) (9 . ("Pirkka" "Matja" "Eija" "Eini")) (10 . ("Iiro" "Ere" "Martti")) (11 . ("Viktor" "Iida" "Feodor" "Heikki")) (12 . ("Johannes" "Juhani" "Juha" "Niilo")) (13 . ("Johannes" "Juhani" "Juha")) (14 . ("Ilpo")) (15 . ("Guri")) (16 . ("Matti")) (17 . ("Riiki" "Riku" "Reijo")) (18 . ("Rauno" "Romana")) (19 . ("Päiviö")) (20 . ("Riiko" "Riku" "Reijo" "Kauko")) (21 . ("Maria" "Maija" "Marjatta")) (22 . ("Silja" "Mikael" "Miihkali" "Mikko")) (23 . ("Riiko" "Riku" "Aleksanteri" "Mitro")) (24 . ("Katariina" "Katja")) (25 . ("Liimo" "Pekka" "Petri" "Katariina" "Katja")) (26 . ("Jyrki" "Yrjö")) (27 . ("Jaakko")) (28 . ("Teppo" "Teppana" "Tapani" "Arho")) (29 . ("Aake")) (30 . ("Antti" "Antero")) )) (12 . ( (1 . ("Uuno")) (2 . ("Auvo" "Mira" "Mirka" "Salomo")) (3 . ("Sauvo")) (4 . ("Varvara" "Johannes" "Aleksanteri")) (5 . ("Sauvo")) (6 . ("Nikolai" "Niko" "Niilo")) (7 . ("Ambrosius" "Anton" "Anttoni" "Toni")) (8 . ("Tapio" "Kirilä" "Kiril")) (9 . ("Anna" "Anni" "Anja" "Anneli" "Anita")) (10 . ("Minkka" "Kirmo")) (11 . ("Taneli")) (12 . ("Piri" "Pirkka")) (13 . ("Lusia" "Seija")) (14 . ("Aari")) (15 . ("Paavo" "Pauli" "Teppo" "Tapani" "Triifon")) (16 . ("Fanni")) (17 . ("Taneli")) (18 . ("Seppo")) (19 . ("Vaito")) (20 . ("Ignatios" "Juha")) (21 . ("Jaana" "Pietari" "Petri" "Pekka")) (22 . ("Anastasia" "Nasti" "Asta")) (23 . ("Tuulo")) (24 . ("Jenni")) (25 . ("Immanuel")) (26 . ("Jehki")) (27 . ("Joosef" "Daavid" "Jaakko" "Teppo")) (28 . ("Domna" "Vilja")) (29 . ("Markko")) (30 . ("Ani")) (31 . ("Maila")) )))) (defun kom-list-nameday-lists () (interactive) (with-output-to-temp-buffer "*Help*" (princ (mapconcat (lambda (x) (format "%s -- %s\n%s\n\n" (nameday-data->code (cdr x)) (nameday-data->name (cdr x)) (nameday-data->description (cdr x)))) lyskom-namedays "")))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: commands1.el,v 44.223 2005/01/12 11:42:13 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: commands1.el ;;;; ;;;; This file contains the code for some of the high level commands. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: commands1.el,v 44.223 2005/01/12 11:42:13 _cvs_pont_lyskomelisp Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) ;;; ================================================================ ;;; F} uppmuntran - Get appreciation ;;; Author: Inge Wallin (def-kom-command kom-get-appreciation () "Provides a little light in the dark." (interactive) (lyskom-insert-string 'appreciation)) ;;; ================================================================ ;;; F} Sk{ll - Get abuse ;;; Author: Inge Wallin (def-kom-command kom-get-abuse () "Provides a bit of verbal abuse." (interactive) (lyskom-insert-string 'abuse)) ;;; ================================================================ ;;; Utpl}na - Delete a person or a conference ;;; Author: Inge Wallin (def-kom-command kom-delete-conf () "Deletes a person or a conference. In order to delete a conference you must be the supervisor of the conference. Once a conference is deleted, it can never be restored, and texts with no recipients other than the deleted conference will become inaccessible, and will eventually be permanently deleted." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'what-conf-to-delete '(all) nil nil t))) (if conf-stat (if (lyskom-ja-or-nej-p (lyskom-format 'confirm-delete-pers-or-conf (if (conf-type->letterbox (conf-stat->conf-type conf-stat)) (lyskom-get-string 'the-pers) (lyskom-get-string 'the-conf)) (conf-stat->name conf-stat))) (if (blocking-do 'delete-conf (conf-stat->conf-no conf-stat)) (progn (lyskom-format-insert 'conf-is-deleted (conf-stat->name conf-stat)) (when (= (conf-stat->conf-no conf-stat) lyskom-pers-no) (lyskom-insert (lyskom-get-string 'you-have-deleted-yourself)) (lyskom-init-membership) (setq lyskom-pers-no nil lyskom-to-do-list (lyskom-create-read-list) lyskom-reading-list (lyskom-create-read-list) lyskom-pending-commands (cons 'kom-start-anew lyskom-pending-commands)))) (lyskom-format-insert 'you-could-not-delete conf-stat)) (lyskom-insert-string 'deletion-not-confirmed)) (lyskom-insert-string 'somebody-else-deleted-that-conf)))) ;;; ================================================================ ;;; Radera (text) - Delete a text ;;; Author: Inge Wallin (def-kom-command kom-delete-text (text-no) "Permanently deletes a text. In order to delete a text you must be the author of the text, or the supervisor of the author. It is a very bad idea to delete texts that have comments. By deleting a text with comments, the comments lost their context. This can lead to fragmented discussion trees, where it is impossible to understand what a comment means, or indeed what the whole discussion is about. Instead of deleting a text, consider moving it to a conference created specifically for storing texts that are no longer interesting. Several LysKOM systems have such conferences, so ask around. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-text-to-delete))) (if text-no (let* ((text-stat (blocking-do 'get-text-stat text-no)) (num-marks (and text-stat (text-stat->no-of-marks text-stat))) (num-comments (and text-stat (length (lyskom-text-comments text-stat)))) (is-marked-by-me (cache-text-is-marked text-no))) (if (null text-stat) (lyskom-report-command-answer nil) (when (and (or (eq 0 num-marks) (lyskom-j-or-n-p (lyskom-format 'delete-marked-text (if (> num-marks 0) (if is-marked-by-me (if (= num-marks 1) (lyskom-get-string 'delete-marked-by-you) (lyskom-format 'delete-marked-by-you-and-others (1- num-marks))) (lyskom-format 'delete-marked-by-several num-marks)))))) (or (eq 0 num-comments) (progn (lyskom-format-insert "%#1@%#2t\n" `(face ,kom-warning-face) (lyskom-get-string 'delete-commented-text-help)) (lyskom-beep t) (and (lyskom-j-or-n-p (lyskom-get-string 'delete-commented-text)) (lyskom-j-or-n-p (lyskom-get-string 'really-delete-commented-text)))))) (lyskom-format-insert 'deleting-text text-no) (when (lyskom-report-command-answer (blocking-do 'delete-text text-no)) (when is-marked-by-me (lyskom-unmark-text text-no)))))) (lyskom-insert 'confusion-what-to-delete))) ;;; ================================================================ ;;; ]terse presentation - Review the presentation ;;; for a person or a conference ;;; Author: Inge Wallin (def-kom-command kom-review-presentation (&optional text-or-conf-no) "Reviews the presentation for a person or a conference. If you give a prefix argument it is treated as a text number prefix argument (see `lyskom-read-text-no-prefix-arg'), and this command shows the presentation of the author of that text. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (and current-prefix-arg ; only peek at textno:s when prefixed! (list (lyskom-read-text-no-prefix-arg 'text-to-see-author-of)))) (let ((conf-stat (if text-or-conf-no (blocking-do 'get-conf-stat (if (interactive-p) (text-stat->author (blocking-do 'get-text-stat text-or-conf-no)) text-or-conf-no)) (lyskom-read-conf-stat 'presentation-for-whom '(all) nil nil t)))) (lyskom-review-presentation conf-stat))) (def-kom-command kom-unread-presentation (&optional text-or-conf-no) "Marks the presentation for a person or a conference as unread. If you give a prefix argument it is treated as a text number prefix argument (see `lyskom-read-text-no-prefix-arg'), and this command unreads the presentation of the author of that text. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (and current-prefix-arg ; only peek at textno:s when prefixed! (list (lyskom-read-text-no-prefix-arg 'text-to-unread-author-of)))) (let ((conf-stat (if text-or-conf-no (blocking-do 'get-conf-stat (if (interactive-p) (text-stat->author (blocking-do 'get-text-stat text-or-conf-no)) text-or-conf-no)) (lyskom-read-conf-stat 'unread-presentation-for-whom '(all) nil nil t)))) (if (zerop (conf-stat->presentation conf-stat)) (lyskom-format-insert 'has-no-presentation conf-stat) (lyskom-format-insert 'marking-text-unread (conf-stat->presentation conf-stat)) (lyskom-report-command-answer (lyskom-mark-unread (conf-stat->presentation conf-stat)))))) (defun lyskom-review-presentation (conf-stat) "Review the presentation of conference CONF-STAT." (if (null conf-stat) (lyskom-insert-string 'somebody-deleted-that-conf) (lyskom-format-insert 'review-presentation-of conf-stat) (if (/= (conf-stat->presentation conf-stat) 0) (lyskom-view-text (conf-stat->presentation conf-stat)) (lyskom-format-insert 'has-no-presentation conf-stat)) (lyskom-traverse faq (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 14) (lyskom-print-comment-like-aux faq conf-stat)))) (defun lyskom-print-comment-like-aux (item object) (when (lyskom-aux-item-validate (aux-item->data item) 'lyskom-string-to-int) (let* ((text-no (string-to-int (aux-item->data item))) (text-stat nil) (text nil)) (unless kom-deferred-printing (blocking-do-multiple ((x-text (get-text text-no)) (x-text-stat (get-text-stat text-no))) (setq text-stat x-text-stat text x-text))) (cond ((or text-stat (not kom-deferred-printing)) (lyskom-insert-comment-like-aux item text-no text-stat text object)) (t (let ((defer-info (lyskom-create-defer-info 'get-text-stat text-no 'lyskom-insert-deferred-comment-like-aux (point-max-marker) (length lyskom-defer-indicator) nil ; Filled in later (list item object text-no)))) (lyskom-format-insert "%#1s\n" lyskom-defer-indicator) (lyskom-defer-insertion defer-info))))))) (defun lyskom-insert-comment-like-aux (item text-no text-stat text object) (let* ((author (if text-stat (text-stat->author text-stat) nil)) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (formats (lyskom-aux-item-definition-field item 'text-header-line)) (subject (lyskom-print-faq-format-subject text text-stat text-no)) content-type ) (if (and mx-from (setq content-type (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data content-type)) (setq content-type (format "(%s) " (aux-item->data content-type)))) (setq content-type "")) (setq author (or (lyskom-format-mx-author mx-from mx-author) author)) (lyskom-format-insert (cond ((not (listp formats)) formats) ((<= (length formats) 1) (car formats)) (author (elt formats 1)) (t (elt formats 0))) text-no author content-type (lyskom-aux-item-terminating-button item object) subject) (lyskom-insert "\n"))) ;;; FIXME: This contains code that duplicates the code in ;;; lyskom-insert-deferred-header-comm. That's a BAD THING. (defun lyskom-insert-deferred-comment-like-aux (text-stat defer-info) (initiate-get-text 'deferred 'lyskom-insert-deferred-comment-like-aux-2 (elt (defer-info->data defer-info) 2) text-stat defer-info)) (defun lyskom-insert-deferred-comment-like-aux-2 (text text-stat defer-info) (let* ((author (if text-stat (text-stat->author text-stat) nil)) (item (elt (defer-info->data defer-info) 0)) (object (elt (defer-info->data defer-info) 1)) (text-no (elt (defer-info->data defer-info) 2)) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (formats (lyskom-aux-item-definition-field item 'text-header-line)) (subject (lyskom-print-faq-format-subject text text-stat text-no)) content-type ) (if (and mx-from (setq content-type (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data content-type)) (setq content-type (format "(%s) " (aux-item->data content-type)))) (setq content-type "")) (setq author (or (lyskom-format-mx-author mx-from mx-author) author)) (set-defer-info->format defer-info (cond ((not (listp formats)) formats) ((<= (length formats) 1) (car formats)) (author (elt formats 1)) (t (elt formats 0)))) (lyskom-replace-deferred defer-info text-no author content-type (lyskom-aux-item-terminating-button item object) subject))) ;;; ================================================================ ;;; Återse det kommenterade - View commented text ;;; Author: Inge Wallin ;;; Modified by: David Kågedal, Johan Sundström (def-kom-command kom-view-commented-text (text-no) "Views the text that the selected text is a comment to. If the current text is comment or footnote to several texts then the first text is shown and the remaining texts are reviewed. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache'." (interactive (list (lyskom-read-text-no-prefix-arg 'review-commented-q))) (if (not text-no) (lyskom-insert-string 'confusion-what-to-view) (lyskom-tell-internat 'kom-tell-read) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (let ((kom-show-footnotes-immediately nil)) (lyskom-view-commented-text (blocking-do 'get-text-stat text-no))))) (def-kom-command kom-unread-commented-text (text-no) "MArkes the texts that the selected text is a comment to as unread. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-commented-q))) (if text-no (lyskom-unread-commented-text (blocking-do 'get-text-stat text-no)) (lyskom-insert-string 'confusion-what-to-mark-unread))) (def-kom-command kom-view-previous-commented-text (text-no) "Views the text that the selected text is a comment to. If the current text is comment or footnote to several texts then the first text is shown and the remaining texts are reviewed. Without a prefix argument this will display the text that the next-to-last text in the buffer is a comment to. With a prefix argument this command is identical to `kom-view-commented-text'. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg') See `kom-review-uses-cache'." (interactive (list (lyskom-read-text-no-prefix-arg 'review-commented-q))) (cond (text-no (lyskom-tell-internat 'kom-tell-read) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-view-commented-text (blocking-do 'get-text-stat text-no))) (t (lyskom-insert-string 'confusion-what-to-view)))) (def-kom-command kom-unread-previous-commented-text (text-no) "Marks the texts that the selected text is a comment to as unread. Without a prefix argument this will display the text that the next-to-last text in the buffer is a comment to. With a prefix argument this command is identical to `kom-unread-commented-text'. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')" (interactive (list (lyskom-read-text-no-prefix-arg 'review-commented-q))) (if text-no (lyskom-unread-commented-text (blocking-do 'get-text-stat text-no)) (lyskom-insert-string 'confusion-what-to-mark-unread))) (defun lyskom-text-stat-commented-texts (text-stat) "Return a list of the text-nos that TEXT-STAT is a comment or footnote to." (let* ((misc-info-list (and text-stat (text-stat->misc-info-list text-stat))) (misc-infos (and misc-info-list (append (lyskom-misc-infos-from-list 'COMM-TO misc-info-list) (lyskom-misc-infos-from-list 'FOOTN-TO misc-info-list))))) (and misc-infos (mapcar (function (lambda (misc-info) (if (equal (misc-info->type misc-info) 'COMM-TO) (misc-info->comm-to misc-info) (misc-info->footn-to misc-info)))) misc-infos)))) (defun lyskom-view-commented-text (text-stat) "Handles the return from the initiate-get-text-stat, displays and builds list." (let ((text-nos (lyskom-text-stat-commented-texts text-stat))) (if text-nos (progn (lyskom-format-insert 'review-text-no (car text-nos)) (if (cdr text-nos) (read-list-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list (cdr text-nos)) lyskom-current-text) lyskom-reading-list t)) (unless kom-review-uses-cache (cache-del-text-stat (car text-nos))) (lyskom-view-text (car text-nos) nil nil nil nil nil nil t)) (lyskom-insert-string 'no-comment-to)))) (defun lyskom-unread-commented-text (text-stat) "Marks the texts that TEXT-STAT is a comment to as unread." (let ((text-nos (lyskom-text-stat-commented-texts text-stat))) (if text-nos (lyskom-traverse text-no text-nos (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no))) (lyskom-insert-string 'no-comment-to-to-unread)))) (defun lyskom-misc-infos-from-list (type list) "Get all the misc-infos from the misc-info-list LIST with the same type as TYPE. If no such misc-info, return NIL" (let ((result nil)) (while list (when (equal type (misc-info->type (car list))) (setq result (cons (car list) result))) (setq list (cdr list))) (nreverse result))) ;;; ================================================================ ;;; Brev - Send letter ;;; Author: Inge Wallin (def-kom-command kom-send-letter (&optional pers-no) "Send a personal letter to a person. This command is similar to `kom-write-text', but intended specifically for sending personal messages. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled." (interactive) (lyskom-tell-internat 'kom-tell-write-letter) (lyskom-write-text pers-no 'who-letter-to)) ;;; ================================================================ ;;; Bli medlem i m|te - Become a member of a conference ;;; Addera medlem - Add somebody else as a member ;;; Author: David Byers, David Kågedal (def-kom-command kom-add-member () "Invite a person as a member of a conference. Depending on the server configuration this command may either create an invitation or simply make the person a member of the conference without asking them for confirmation." (interactive) (lyskom-add-member)) (def-kom-command kom-add-self (&optional conf) "Become a member of a conference. The default priority of the membership is determined by `kom-membership-default-priority' and its placement by `kom-membership-default-placement' You can also use this command to change the priority of an existing membership and to re-join a conference of which you are a passive member. See `kom-membership-default-priority' and `kom-membership-default-placement'" (interactive) (lyskom-add-member (blocking-do 'get-conf-stat lyskom-pers-no) conf)) (def-kom-command kom-change-priority (&optional conf) "Changes the priority of a single membership. If you want to change the priority of several memberships, use `kom-prioritize' instead." (interactive) (let* ((conf-stat (if conf (blocking-do 'get-conf-stat conf) (lyskom-read-conf-stat 'change-priority-for-q '(all) nil nil t))) (mship (and conf-stat (lyskom-get-membership (conf-stat->conf-no conf-stat) t)))) (cond ((null conf-stat) (lyskom-format-insert 'no-such-conf)) ((null mship) (lyskom-format-insert 'not-member-of-conf conf-stat)) ((membership-type->passive (membership->type mship)) (lyskom-format-insert 'cant-change-priority-of-passive)) (t (lyskom-add-member (blocking-do 'get-conf-stat lyskom-pers-no) conf-stat t t (list (membership->priority mship)) nil t 'change-priority-for))))) (defun lyskom-add-member-by-no (conf-no pers-no &optional no-of-unread mship-type thendo &rest data) "Fetch info to be able to add a person to a conf. Get the conf-stat CONF-NO for the conference and the conf-stat and pers-stat for person PERS-NO and send them into lyskom-add-member." (blocking-do-multiple ((whereto (get-conf-stat conf-no)) (who (get-conf-stat pers-no))) (prog1 (lyskom-add-member who whereto mship-type no-of-unread) (and thendo (apply thendo data))))) (defun lyskom-add-member (&optional pers-conf-stat conf-conf-stat mship-type no-of-unread priority position force message-string) "Add PERS-CONF-STAT to CONF-CONF-STAT. Returns non-nil if person if person is a member of the conference after this call has comleted. Optional MSHIP-TYPE is the membership type to use. If it is t, keep the old membership type (if one exists). Optional NO-OF-UNREAD specifies how many unread texts to leave in the conference. If set to t, don't change the number of unread. Optional PRIORITY is the priority of the membership. If it is a list, this function will prompt with the car of the list as the default priority. Optional POSITION is the position of the new membership. If optional FORCE is non-nil, add even if the user is already a member of the conference. If optional MESSAGE-STRING is non-nil, use it as the prompt when adding the membership. This function will prompt interactively for any information not specified when calling it. This function blocks, so it may not be called from a callback." (let* ((who (or pers-conf-stat (lyskom-read-conf-stat 'who-to-add '(pers) nil nil t))) (pers-stat (blocking-do 'get-pers-stat (conf-stat->conf-no who))) (self (eq (conf-stat->conf-no who) lyskom-pers-no)) (whereto (or conf-conf-stat (lyskom-read-conf-stat (if self 'where-to-add-self 'where-to-add) '(all) nil nil t))) (mship (lyskom-is-member (conf-stat->conf-no whereto) (conf-stat->conf-no who))) (mship-type (if (and (eq mship-type t) mship) (membership->type mship) mship-type)) (became-member nil)) (cond ;; Already a member ((and mship (not (and self (or force (membership-type->passive (membership->type mship)) (membership-type->invitation (membership->type mship)))))) (lyskom-format-insert (if self 'you-already-member 'add-already-member) whereto who) (setq became-member t)) ;; We're already passive members, so depassivate ((and mship self (membership-type->passive (membership->type mship))) (set-membership-type->passive (membership->type mship) nil) (set-membership-type->message-flag (membership->type mship) t) (lyskom-format-insert 'activate-mship whereto) (let ((res (blocking-do 'set-membership-type lyskom-pers-no (conf-stat->conf-no whereto) (membership->type mship)))) (lyskom-report-command-answer res) (when res (setq became-member t) (lyskom-format-insert 'activate-mship-done whereto) (lp--update-buffer (membership->conf-no mship)) (lyskom-fetch-start-of-map whereto mship)))) ;; We be adding someone for real (t (let* ((no-of-unread (cond ((eq no-of-unread t) nil) (no-of-unread) (t (when (and self (not (membership-type->passive (membership->type mship)))) (lyskom-read-num-range-or-date 0 (conf-stat->no-of-texts whereto) (lyskom-format 'initial-unread) nil t nil))))) (priority (cond ((numberp priority) priority) ((not self) (lyskom-read-num-range 0 255 (lyskom-get-string 'other-priority-q) nil 100)) ((and (null priority) (numberp kom-membership-default-priority) (< kom-membership-default-priority 256) (>= kom-membership-default-priority 0)) kom-membership-default-priority) (t (lyskom-read-num-range 0 255 (lyskom-get-string 'priority-q) nil (cond (mship (membership->priority mship)) ((listp priority) (car priority))))))) (position (or position (cond ((not self) 1) ((and (numberp kom-membership-default-placement) (>= kom-membership-default-placement 0)) kom-membership-default-placement) ((eq kom-membership-default-placement 'first) 0) ((eq kom-membership-default-placement 'last) (lyskom-membership-length)) (t (lyskom-read-num-range 0 (pers-stat->no-of-confs pers-stat) (lyskom-format 'where-on-list-q (lyskom-membership-length))))))) (message-flag (or (when mship-type (membership-type->message-flag mship-type)) (when (eq 'ask kom-membership-default-message-flag) (lyskom-j-or-n-p (lyskom-format 'set-message-flag-q whereto))) kom-membership-default-message-flag)) (mship-type (or mship-type (lyskom-create-membership-type (not self) nil nil message-flag nil nil nil nil))) (no-of-unread-string (cond ((null no-of-unread) nil) ((numberp no-of-unread) (lyskom-format 'member-in-conf-with-unread no-of-unread)) ((listp no-of-unread) (lyskom-format 'member-in-conf-with-unread-date (elt no-of-unread 0) (car (rassq (elt no-of-unread 1) lyskom-month-names)) (elt no-of-unread 2))))) ) ;; Now add the member; we've got all the information we need ;; Adding ourselves. Adjust where so the membership ;; list remains sorted. Find the closest position to ;; where at which we can put the membership and keep ;; the membership lsit sorted. (when (eq lyskom-pers-no (conf-stat->conf-no who)) (setq position (lyskom-query-membership-position priority position))) ;; Print the prompt (lyskom-format-insert (cond (message-string) ((and self mship (membership-type->invitation (membership->type mship))) 'accepting-invitation) (self 'member-in-conf) (t 'add-member-in)) who whereto no-of-unread-string) ;; Do the add thing (lyskom-ignoring-async (18 lyskom-pers-no (conf-stat->conf-no whereto)) (let ((res (blocking-do 'add-member (conf-stat->conf-no whereto) (conf-stat->conf-no who) priority position mship-type))) (cond ;; Failure ((null res) (lyskom-insert-string 'nope) (let* ((errno lyskom-errno) (err-stat lyskom-err-stat) (is-supervisor (lyskom-is-supervisor (conf-stat->conf-no whereto) lyskom-pers-no)) (is-member (lyskom-is-member (conf-stat->conf-no whereto) (conf-stat->conf-no who))) (rd-prot (conf-type->rd_prot (conf-stat->conf-type whereto)))) (cond (is-member (lyskom-format-insert 'add-already-member who whereto)) ((and rd-prot is-supervisor) (lyskom-insert-error errno err-stat)) (rd-prot (let ((supervisorconf (blocking-do 'get-conf-stat (conf-stat->supervisor whereto)))) (if supervisorconf (lyskom-format-insert 'is-read-protected-contact-supervisor whereto supervisorconf) (lyskom-format-insert 'cant-find-supervisor whereto)))) (t (lyskom-insert-error errno err-stat))))) (t (setq became-member t) ;; If we're re-adding a membership, then we need to set the ;; membership type explicity since add-member won't (when (and self mship) (blocking-do 'set-membership-type (conf-stat->conf-no who) (conf-stat->conf-no whereto) mship-type)) (cache-del-pers-stat (conf-stat->conf-no who)) (cache-del-conf-stat (conf-stat->conf-no whereto)) (when self (when no-of-unread (cond ((listp no-of-unread) (let* ((target-date (lyskom-create-time 0 0 0 (elt no-of-unread 2) (elt no-of-unread 1) (elt no-of-unread 0) 0 0 nil)) (text (lyskom-find-text-by-date whereto target-date))) (when text (blocking-do 'set-last-read (conf-stat->conf-no whereto) (car text))))) ((numberp no-of-unread) (blocking-do 'set-unread (conf-stat->conf-no whereto) no-of-unread)))) (let ((mship (blocking-do 'query-read-texts lyskom-pers-no (conf-stat->conf-no whereto) t 0))) (read-list-delete-read-info (conf-stat->conf-no whereto) lyskom-to-do-list) (if (lyskom-try-get-membership (conf-stat->conf-no whereto) t) (lyskom-replace-membership mship) (lyskom-add-membership mship whereto t)) (unless (membership->position mship) (set-membership->position mship position)) (if (< (membership->priority mship) lyskom-session-priority) (progn (lyskom-format-insert-before-prompt 'member-in-conf-with-low-priority whereto) (when (= (conf-stat->conf-no whereto) lyskom-current-conf) (lyskom-leave-current-conf))) (lyskom-fetch-start-of-map whereto mship)))) (lyskom-insert-string 'done)))))))) became-member)) (defun lyskom-add-membership (membership conf-no-or-stat &optional blocking) "Adds MEMBERSHIP to the sorted list of memberships. If BLOCKING is non-nil, block while reading the conference map until at least one text has been seen. CONF-NO-OR-STAT is the conf-no to add unless BLOCKING is t, in which cast it is the conf-stat." (if membership (progn (lyskom-insert-membership membership) (if blocking (lyskom-fetch-start-of-map conf-no-or-stat membership) (lyskom-prefetch-map conf-no-or-stat membership)) (lyskom-run-hook-with-args 'lyskom-add-membership-hook membership)) (lyskom-insert-string 'conf-does-not-exist))) ;;; ================================================================ ;;; Uttr{d - Subtract yourself as a member from a conference ;;; Uteslut medlem - Subtract somebody else as a member ;;; Author: David Byers ;;; Based on code by Inge Wallin ;; Subtract another person (def-kom-command kom-sub-member () "Remove a member from a conference. To do this you need to be the supervisor of the conference or of the member being removed." (interactive) (lyskom-sub-member (lyskom-read-conf-stat 'who-to-exclude '(pers) nil nil t) (lyskom-read-conf-stat 'where-from-exclude '(all) nil nil t))) (def-kom-command kom-sub-self (&optional conf-no) "Resign your membership of a conference. If `kom-unsubscribe-makes-passive' is set, them resigning once converts your membership to a passive membership and resigning twice removes the membership completely (if the server supports passive memberships). See `kom-unsubscribe-makes-passive'." (interactive) (let* ((me (blocking-do 'get-conf-stat lyskom-pers-no)) (conf (if conf-no (blocking-do 'get-conf-stat conf-no) (lyskom-read-conf-stat 'leave-what-conf '(membership) nil nil t)))) (lyskom-sub-member me conf))) (defun lyskom-sub-member (pers conf &optional have-message) "Remove the person indicated by PERS as a member of CONF." (let* ((reply nil) (self (= (conf-stat->conf-no pers) lyskom-pers-no)) (mship (and self kom-unsubscribe-makes-passive (lyskom-get-membership (conf-stat->conf-no conf)))) (passivate (and mship (lyskom-have-call 102) ; set-membership-type (not (membership-type->passive (membership->type mship)))))) (cond ((null pers) (lyskom-insert-string 'error-fetching-person)) ((null conf) (lyskom-insert-string 'error-fetching-conf)) (passivate (lyskom-prefetch-cancel-prefetch-map (conf-stat->conf-no conf)) (unless have-message (lyskom-format-insert 'unsubscribe-to conf)) (set-membership-type->passive (membership->type mship) t) (set-membership-type->message-flag (membership->type mship) nil) (setq reply (blocking-do 'set-membership-type (conf-stat->conf-no pers) (conf-stat->conf-no conf) (membership->type mship))) (if (not reply) (lyskom-format-insert 'unsubscribe-failed (lyskom-get-string 'You) conf) (lyskom-insert-string 'done) (lyskom-format-insert 'passivate-done conf) (when (= (conf-stat->conf-no conf) lyskom-current-conf) (lyskom-leave-current-conf)) (read-list-delete-read-info (conf-stat->conf-no conf) lyskom-to-do-list) (lp--update-buffer (conf-stat->conf-no conf)))) (t (when self (lyskom-prefetch-cancel-prefetch-map (conf-stat->conf-no conf))) (if self (lyskom-format-insert 'unsubscribe-to conf) (lyskom-format-insert 'exclude-from pers conf)) (lyskom-ignoring-async (8 (conf-stat->conf-no conf)) (setq reply (blocking-do 'sub-member (conf-stat->conf-no conf) (conf-stat->conf-no pers)))) (if self (lyskom-remove-membership (conf-stat->conf-no conf))) (if (not reply) (lyskom-format-insert 'unsubscribe-failed (if self (lyskom-get-string 'You) (conf-stat->name pers)) conf) (lyskom-insert-string 'done) (when (and self (= (conf-stat->conf-no conf) lyskom-current-conf)) (lyskom-leave-current-conf)) (read-list-delete-read-info (conf-stat->conf-no conf) lyskom-to-do-list)))))) ;;; ================================================================ ;;; Skapa m|te - Create a conference ;;; Author: ??? (def-kom-command kom-create-conf (&optional name) "Create a new conference. Use this command when you want to create a new conference. It will ask for all required information. Before creating a conference, check that there isn't already one covering the intended topics. There may be a conference for discussing converence creation where you can ask. If there isn't, there is probably a general Q&A conference where you can ask." (interactive) (let* ((conf-name (or name (lyskom-read-string (lyskom-get-string 'name-of-conf)))) (open (j-or-n-p (lyskom-get-string 'anyone-member))) (secret (if (not open) (j-or-n-p (lyskom-get-string 'secret-conf)))) (orig (j-or-n-p (lyskom-get-string 'comments-allowed))) (anarchy (j-or-n-p (lyskom-get-string 'anonymous-allowed))) (secmem (and (lyskom-have-feature long-conf-types) (not (lyskom-j-or-n-p (lyskom-get-string 'secret-members-allowed))))) (life-expectancy (lyskom-read-number 'new-garb-nice-q)) (keep-commented (lyskom-read-number 'new-keep-commented-q)) (conf-no (blocking-do 'create-conf conf-name (lyskom-create-conf-type (not open) (not orig) secret nil anarchy secmem nil nil) nil))) (if (null conf-no) (progn (lyskom-format-insert 'could-not-create-conf conf-name) (lyskom-insert-error)) (progn (let ((conf-stat (blocking-do 'get-conf-stat conf-no))) (lyskom-format-insert 'created-conf-no-name (or conf-stat conf-no) (or conf-stat conf-name) (if conf-stat (lyskom-default-button 'conf conf-stat) nil))) (lyskom-scroll) (lyskom-add-member-by-no conf-no lyskom-pers-no nil nil (if secret nil ; Don't write a presentation 'lyskom-create-conf-handler-2) conf-no conf-name) (blocking-do 'set-garb-nice conf-no life-expectancy) (blocking-do 'set-keep-commented conf-no keep-commented))))) (defun lyskom-create-conf-handler-2 (conf-no conf-name) "Starts editing a presentation for the newly created conference. This does lyskom-end-of-command" (lyskom-tell-internat 'kom-tell-conf-pres) (let ((conf (blocking-do 'get-conf-stat conf-no))) (if conf (lyskom-dispatch-edit-text lyskom-proc (lyskom-create-misc-list 'RECPT (server-info->conf-pres-conf lyskom-server-info)) conf-name "" 'lyskom-set-presentation conf-no)))) (defun lyskom-set-presentation (text-no conf-no) "Set presentation of a conference. Args: text-no conf-no." (initiate-set-presentation 'background nil conf-no text-no) (cache-del-conf-stat conf-no)) ;+++Borde {ndra i cachen i st{llet. ;+++ Kan tas bort n{r det existerar ;asynkrona meddelanden som talar om att ;n}got {r {ndrat. (defun lyskom-set-conf-motd (text-no conf-no) "Set motd of a conference. Args: text-no conf-no." (initiate-set-conf-motd 'background nil conf-no text-no) (cache-del-conf-stat conf-no)) ;+++Borde {ndra i cachen i st{llet. ;+++ Kan tas bort n{r det existerar ;asynkrona meddelanden som talar om att ;n}got {r {ndrat. ;;; ================================================================ ;;; Kommentera - write comment ;;; Author: ??? ;;; FIXME: Does not use def-kom-command (def-kom-command kom-write-comment (text-no) "Write a comment to the selected text. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." :prompt-format (concat "%#1C " (if text-no (lyskom-format " (%#1n)" text-no) "")) (interactive (list (let ((lyskom-current-command 'kom-write-comment)) (lyskom-read-text-no-prefix-arg 'what-comment-no)))) (if text-no (progn (lyskom-nag-about-presentation) (blocking-do-multiple ((text (get-text text-no)) (text-stat (get-text-stat text-no))) (when (or (null (text-stat-find-aux text-stat 4)) (lyskom-j-or-n-p (lyskom-get-string 'no-comments-q))) (if (and (text-stat-find-aux text-stat 5) (lyskom-j-or-n-p (lyskom-get-string 'private-answer-q))) (lyskom-private-answer-soon text-stat text text-no) (lyskom-write-comment-soon text-stat text text-no 'comment))))) (lyskom-insert-string 'confusion-who-to-reply-to))) (def-kom-command kom-write-footnote (text-no) "Write a footnote to the selected text. In order to write a footnote you must be the author, or superviser of the author, of the selected text. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg'). Without a prefix argument this command will write a footnote to the most recently read or written applicable text." :prompt-format (concat "%#1C " (if text-no (lyskom-format " (%#1n)" text-no) "")) (interactive (list (lyskom-read-text-no-prefix-arg 'what-footnote-no))) (if text-no (lyskom-write-comment-soon (blocking-do 'get-text-stat text-no) (blocking-do 'get-text text-no) text-no 'footnote) (lyskom-insert-string 'confusion-what-to-footnote))) (def-kom-command kom-comment-previous (text-no) "Write a comment to the selected text. Without a prefix argument the selected text is the next-to-last text in the buffer. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." :prompt-format (concat "%#1C " (if text-no (lyskom-format " (%#1n)" text-no) "")) (interactive (list (lyskom-read-text-no-prefix-arg 'what-comment-no))) (if text-no (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (when (or (null text-stat) (null text) (null (text-stat-find-aux text-stat 4)) (lyskom-j-or-n-p (lyskom-get-string 'no-comments-q))) (if (and (text-stat-find-aux text-stat 5) (lyskom-j-or-n-p (lyskom-get-string 'private-answer-q))) (lyskom-private-answer-soon text-stat text text-no) (lyskom-write-comment-soon text-stat text text-no 'comment)))) (lyskom-insert-string 'confusion-what-to-comment))) (defun lyskom-write-comment-soon (text-stat text text-no type) "Write a comment to the text with TEXT-STAT, TEXT and, TEXT-NO. TYPE is either 'comment or 'footnote." (let ((str (and text-stat text (text->decoded-text-mass text text-stat)))) (cond ;; Text not found? ((or (null text-stat) (null text)) (lyskom-format-insert 'cant-read-textno text-no)) ;; Give header. ((string-match "\n" str) (lyskom-write-comment text-stat (substring str 0 (match-beginning 0)) type)) ;; The commented text had no header. (t (lyskom-write-comment text-stat "" type))))) (defun lyskom-write-comment (text-stat subject type) "Write a comment to the text associated with TEXT-STAT. The default subject is SUBJECT. TYPE is either 'comment or 'footnote." (if (null text-stat) (progn (lyskom-insert-string 'confusion-what-to-comment)) (let ((ccrep nil) (bccrep nil)) (lyskom-tell-internat (if (eq type 'comment) 'kom-tell-write-comment 'kom-tell-write-footnote)) (let (data) (mapcar (function (lambda (misc-info) (cond ((eq 'RECPT (misc-info->type misc-info)) (setq data (cons (blocking-do 'get-conf-stat (misc-info->recipient-no misc-info)) data))) ((and (eq type 'footnote) (eq 'CC-RECPT (misc-info->type misc-info))) (setq ccrep (cons (misc-info->recipient-no misc-info) ccrep)) (setq data (cons (blocking-do 'get-conf-stat (misc-info->recipient-no misc-info)) data))) ((and (eq type 'footnote) (eq 'BCC-RECPT (misc-info->type misc-info))) (setq bccrep (cons (misc-info->recipient-no misc-info) bccrep)) (setq data (cons (blocking-do 'get-conf-stat (misc-info->recipient-no misc-info)) data)))))) (text-stat->misc-info-list text-stat)) (lyskom-comment-recipients (nreverse data) lyskom-proc text-stat subject type (nreverse ccrep) (nreverse bccrep)))))) (defun lyskom-comment-recipients (data lyskom-proc text-stat subject type ccrep bccrep) "Compute recipients to a comment to a text. Args: DATA, LYSKOM-PROC TEXT-STAT SUBJECT TYPE CCREP BCCREP. DATA is a list of all the recipients that should receive this text. If DATA contains more than one conference the user is asked (using y-or-n-p) if all conferences really should receive the text. The call is continued to the lyskom-edit-text. TYPE is info whether this is going to be a comment of footnote. CCREP is a list of all recipients that are going to be cc-recipients. BCCREP is a list of all recipient that are going to be bcc-recipients." (condition-case nil ;; Catch any quits (progn ;; Filter multiple recipients through y-or-n-p. (if (and (eq kom-confirm-multiple-recipients 'before) (> (length data) 1) (not (and (= (length data) 2) (or (= lyskom-pers-no (conf-stat->conf-no (car data))) (= lyskom-pers-no (conf-stat->conf-no (car (cdr data)))))))) (let ((new-data nil)) (while data (if (lyskom-j-or-n-p (lyskom-format 'comment-keep-recpt-p (conf-stat->name (car data)))) (setq new-data (cons (car data) new-data))) (setq data (cdr data))) (setq data (nreverse new-data)))) (let* ((member nil) (recver (lyskom-create-misc-list (cond ((eq type 'comment) 'COMM-TO) ((eq type 'footnote) 'FOOTN-TO) (t (signal 'lyskom-internal-error (list "Unknown comment type" type)))) (text-stat->text-no text-stat))) (recpts nil)) (while data (let* ((conf-stat (car data)) (confno (conf-stat->conf-no conf-stat)) (commno (if (eq type 'footnote) confno (conf-stat->comm-conf conf-stat)))) (if (memq commno recpts) nil (setq recver (append recver (list (cons (cond ((memq confno ccrep) 'CC-RECPT) ((memq confno bccrep) 'BCC-RECPT) (t 'RECPT)) commno)))) (if (lyskom-get-membership commno) (setq member t)) (setq recpts (cons commno recpts)))) (setq data (cdr data))) ;; Add the user to the list of recipients if he isn't a member in ;; any of the recipients. (when (not member) (setq recver (append recver (list (cons 'RECPT (or (lyskom-get-send-comments-to lyskom-pers-no) lyskom-pers-no)))))) (lyskom-edit-text lyskom-proc recver subject ""))) (quit (signal 'quit nil)))) ;;; ================================================================ ;;; Personligt svar - personal answer ;;; ;;; Author: ??? ;;; Rewritten using blocking-do by: Linus Tolke (def-kom-command kom-private-answer (text-no) "Write a private answer to the selected text. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." :prompt-format (concat "%#1C " (if text-no (lyskom-format " (%#1n)" text-no) "")) (interactive (list (lyskom-read-text-no-prefix-arg 'what-private-no))) (if text-no (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (when (or (null (text-stat-find-aux text-stat 4)) (lyskom-j-or-n-p (lyskom-get-string 'no-comments-q))) (lyskom-private-answer-soon text-stat text text-no))) (lyskom-insert-string 'confusion-who-to-reply-to))) (defun lyskom-private-answer-soon (text-stat text text-no) "Write a private answer to TEXT-STAT, TEXT." (if (and text-stat text) (let ((str (text->decoded-text-mass text text-stat))) (if (string-match "\n" str) (lyskom-private-answer text-stat (substring str 0 (match-beginning 0))) (lyskom-private-answer text-stat ""))) (lyskom-format-insert 'no-such-text-no text-no))) (defun lyskom-private-answer (text-stat subject) "Write a private answer. Args: TEXT-STAT SUBJECT." (cond ((null text-stat) (lyskom-insert-string 'confusion-what-to-answer-to)) ((= (text-stat->author text-stat) 0) (lyskom-insert-string 'personal-comment-to-anonymous)) (t (lyskom-tell-internat 'kom-tell-write-reply) (cache-del-conf-stat (text-stat->author text-stat)) (let* ((conf-stat (blocking-do 'get-conf-stat (text-stat->author text-stat)))) (if (if (zerop (conf-stat->msg-of-day conf-stat)) t (progn (recenter 1) (lyskom-format-insert 'has-motd conf-stat) (lyskom-view-text (conf-stat->msg-of-day conf-stat)) (if (lyskom-j-or-n-p (lyskom-get-string 'motd-persist-q)) t nil))) (lyskom-edit-text lyskom-proc (if (= (text-stat->author text-stat) lyskom-pers-no) (lyskom-create-misc-list 'COMM-TO (text-stat->text-no text-stat) 'RECPT (text-stat->author text-stat)) (lyskom-create-misc-list 'COMM-TO (text-stat->text-no text-stat) 'RECPT (text-stat->author text-stat) 'RECPT lyskom-pers-no)) subject "")))))) ;;; ================================================================ ;;; Personligt svar p} f|reg}ende - kom-private-answer-previous ;;; ;;; Author: ceder ;;; Rewritten using blocking-do by: Linus Tolke (def-kom-command kom-private-answer-previous (text-no) "Write a private answer to the selected text. Without a prefix argument the next-to-last text in the buffer will be selected. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." :prompt-format (concat "%#1C " (if text-no (lyskom-format " (%#1n)" text-no) "")) (interactive (list (lyskom-read-text-no-prefix-arg 'what-private-no))) (if text-no (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (when (or (null (text-stat-find-aux text-stat 4)) (lyskom-j-or-n-p (lyskom-get-string 'no-comments-q))) (lyskom-private-answer-soon text-stat text text-no))) (lyskom-insert-string 'confusion-who-to-reply-to))) ;;; ================================================================ ;;; Sluta - quit ;;; Author: ??? (defun kom-quit (&optional arg) "Exit LysKOM. With prefix argument, don't ask for confirmation." (interactive "P") (lyskom-start-of-command 'kom-quit t) (let ((do-end-of-command t)) (unwind-protect (setq do-end-of-command (cond ((and (lyskom-buffers-of-category 'write-texts) (display-buffer (car (lyskom-buffers-of-category 'write-texts))) (not (lyskom-ja-or-nej-p (lyskom-get-string 'quit-in-spite-of-unsent)))) t) ((or arg (lyskom-ja-or-nej-p (lyskom-get-string 'really-quit))) (lyskom-quit) nil) (t t))) (if do-end-of-command (lyskom-end-of-command))))) (defun lyskom-quit () "Quit a session. Kill process and buffer-local variables. Don't ask for confirmation." (initiate-logout 'main nil) (lyskom-remove-unread-buffer lyskom-buffer) (set-process-sentinel lyskom-proc nil) (delete-process lyskom-proc) (lyskom-insert-string (lyskom-get-string-sol 'session-ended)) (lyskom-scroll) (setq mode-line-process (lyskom-get-string 'mode-line-down)) (run-hooks 'kom-quit-hook) (when (and (boundp 'lyskom-ssh-proxy) lyskom-ssh-proxy) (let* ((numleft (1- (get lyskom-ssh-proxy 'num-connected))) (procname (symbol-name lyskom-ssh-proxy)) (bufname (concat " *" procname "*")) (proc (get-process procname))) (put lyskom-ssh-proxy 'num-connected numleft) (when (and (<= numleft 0) proc) (string-match "^ssh<\\([^:]*\\)" procname) (lyskom-message "%s" (lyskom-format 'ssh-closing (or (match-string 1 procname) (lyskom-get-string 'ssh-unknown-host)))) (delete-process proc) (when (get-buffer bufname) (save-excursion (set-buffer bufname) (goto-char (point-max)) (insert "\n--- closed connection ---\n"))))))) ;;; ================================================================ ;;; [ndra presentation - Change presentation ;;; S{tta lapp p} d|rren - Change conf-motd ;;; Author: Inge Wallin ;;; Changed by Linus Tolke (def-kom-command kom-change-presentation () "Change presentation for a person or a conference. If the person or conference doesn't have a presentation, a new presentation will be created." (interactive) (lyskom-change-pres-or-motd-2 (let ((no (lyskom-read-conf-no 'what-to-change-pres-you '(all) nil nil t))) (blocking-do 'get-conf-stat no)) 'pres)) (def-kom-command kom-change-conf-motd () "Change the notice for a person or a conference. If the person or conference doesn't have a notice, a new notice till be created." (interactive) (lyskom-change-pres-or-motd-2 (let ((no (lyskom-read-conf-no 'who-to-put-motd-for '(all) nil nil t))) (blocking-do 'get-conf-stat no)) 'motd)) (defun lyskom-get-recipients-from-misc-list (misc-list) "Return a misc-info-list containing only the recipients." (let* ((info (car misc-list)) (type (misc-info->type info))) (cond ((null misc-list) '()) ((memq type lyskom-recpt-types-list) (append (list (intern (symbol-name type)) (misc-info->recipient-no info)) (lyskom-get-recipients-from-misc-list (cdr misc-list)))) (t (lyskom-get-recipients-from-misc-list (cdr misc-list)))))) (defun lyskom-change-pres-or-motd-2 (conf-stat type) "Change the presentation or motd of CONF-STAT. TYPE is either 'pres or 'motd, depending on what should be changed." (cond ((null conf-stat) ;+++ annan felhantering (lyskom-insert-string 'cant-get-conf-stat)) ((or lyskom-is-administrator (lyskom-get-membership (conf-stat->supervisor conf-stat) t) (= lyskom-pers-no (conf-stat->conf-no conf-stat))) (blocking-do-multiple ((text-stat (get-text-stat (conf-stat->presentation conf-stat))) (text-mass (get-text (cond ((eq type 'pres) (conf-stat->presentation conf-stat)) ((eq type 'motd) (conf-stat->msg-of-day conf-stat)))))) (let ((str (and text-mass (text->decoded-text-mass text-mass text-stat)))) (lyskom-dispatch-edit-text lyskom-proc (apply 'lyskom-create-misc-list (if (and (eq type 'pres) (not (or (zerop (conf-stat->presentation conf-stat)) (null text-stat)))) (append (lyskom-get-recipients-from-misc-list (text-stat->misc-info-list text-stat)) (list 'COMM-TO (conf-stat->presentation conf-stat))) (list 'RECPT (cond ((eq type 'motd) (server-info->motd-conf lyskom-server-info)) ((eq type 'pres) (if (conf-type->letterbox (conf-stat->conf-type conf-stat)) (server-info->pers-pres-conf lyskom-server-info) (server-info->conf-pres-conf lyskom-server-info))))))) (conf-stat->name conf-stat) (if (and text-mass (string-match "\n" str)) (substring str (match-end 0)) (if (and (eq type 'pres) (conf-type->letterbox (conf-stat->conf-type conf-stat))) (lyskom-get-string 'presentation-form) "")) (cond ((eq type 'pres) 'lyskom-set-presentation) ((eq type 'motd) 'lyskom-set-conf-motd)) (conf-stat->conf-no conf-stat))))) (t (lyskom-format-insert 'not-supervisor-for conf-stat)))) (def-kom-command kom-set-presentation (arg) "Set the presentation of a conference or person to the selected text. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive "P") (let ((conf-no (lyskom-read-conf-no 'what-to-set-pres-you '(all) nil nil t)) (text-no (lyskom-read-text-no-prefix-arg 'what-text-to-set-as-pres-no))) (lyskom-set-pres-or-motd-2 conf-no text-no 'pres))) (def-kom-command kom-set-motd-text (arg) "Set the notice for a person or conference to the selected text. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive "P") (let ((conf-no (lyskom-read-conf-no 'what-to-set-motd-you '(all) nil nil t)) (text-no (lyskom-read-text-no-prefix-arg 'what-text-to-set-as-motd-no))) (lyskom-set-pres-or-motd-2 conf-no text-no 'motd))) (defun lyskom-set-pres-or-motd-2 (conf-no text-no what) (let ((set-pres (eq what 'pres))) (blocking-do-multiple ((conf-stat (get-conf-stat conf-no)) (text-stat (get-text-stat text-no))) (cond ((null conf-stat) (lyskom-format-insert 'no-such-conf-or-pers)) ((null text-stat) (lyskom-format-insert 'no-such-text-no text-no)) (t (let ((existing (if set-pres (conf-stat->presentation conf-stat) (conf-stat->msg-of-day conf-stat)))) (when (or (zerop existing) (progn (lyskom-view-text existing) (lyskom-j-or-n-p (lyskom-get-string (if set-pres 'conf-already-has-pres 'conf-already-has-motd))))) (cache-del-conf-stat conf-no) (cache-del-text-stat text-no) (lyskom-format-insert (if set-pres 'setting-conf-pres 'setting-conf-motd) conf-stat text-no) (lyskom-report-command-answer (cond ((eq what 'pres) (blocking-do 'set-presentation conf-no text-no)) ((eq what 'motd) (blocking-do 'set-conf-motd conf-no text-no))))))))))) (def-kom-command kom-remove-presentation () "Removes the presentation for a person or a conference. Please don't remove a presentation without adding a new one. This can be accomplished with the `kom-change-presentation' command." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'who-to-remove-pres-for '(all) nil nil t))) (cond ((null conf-stat) (lyskom-insert-string 'cant-get-conf-stat)) ((zerop (conf-stat->presentation conf-stat)) (lyskom-format-insert 'has-no-presentation conf-stat)) (t (lyskom-format-insert 'removing-pres-for-conf conf-stat (conf-stat->presentation conf-stat)) (lyskom-report-command-answer (blocking-do 'set-presentation (conf-stat->conf-no conf-stat) 0)))))) ;;; ================================================================ ;;; Ta bort lapp p} d|rren - delete conf-motd ;;; Author: Linus Tolke (& Inge Wallin) (def-kom-command kom-unset-conf-motd () "Removes the notice for a person or conference." (interactive) (let ((conf-stat (or (lyskom-read-conf-stat 'who-to-remove-motd-for '(all) nil nil t) (blocking-do 'get-conf-stat lyskom-pers-no)))) (cond ((null conf-stat) (lyskom-insert-string 'cant-get-conf-stat)) ((or lyskom-is-administrator (lyskom-get-membership (conf-stat->supervisor conf-stat) t)) ;; This works like a dispatch. No error handling. (lyskom-set-conf-motd 0 (conf-stat->conf-no conf-stat))) (t (lyskom-format-insert 'not-supervisor-for conf-stat))))) ;;; ================================================================ ;;; G} till M|te - Go to a conference. ;;; Author: ??? (def-kom-command kom-go-to-conf (&optional conf-no) "Go to a conference and start reading texts there. Changing conferences runs `kom-change-conf-hook' and `kom-after-change-conf-hook'." (interactive) (let ((conf (if conf-no (blocking-do 'get-conf-stat conf-no) (lyskom-read-conf-stat 'go-to-conf-p '(all) nil nil t)))) (when (lyskom-check-go-to-conf conf) (lyskom-go-to-conf conf)))) (defun lyskom-go-to-conf (conf &optional no-prompt) "Go to the conference in CONF. CONF can be conf-no of conf-stat. Allowed conferences are conferences and the mailboxes you are member of. If NO-PROMPT is non-nil, don't print message that we have gone to conf." (if (numberp conf) (setq conf (blocking-do 'get-conf-stat conf))) (let ((membership (lyskom-get-membership (conf-stat->conf-no conf) t))) (unless no-prompt (lyskom-format-insert 'go-to-conf conf)) ;; FIXME: DEBUG+++ (let ((lyskom-inhibit-prefetch t)) (cond (membership (lyskom-do-go-to-conf conf membership)) ((conf-type->letterbox (conf-stat->conf-type conf)) (lyskom-format-insert 'cant-go-to-his-mailbox conf)) (t (progn (lyskom-format-insert 'not-member-of-conf conf) (lyskom-scroll) (if (lyskom-j-or-n-p (lyskom-get-string 'want-become-member)) (if (lyskom-add-member-by-no (conf-stat->conf-no conf) lyskom-pers-no) (lyskom-do-go-to-conf conf (lyskom-get-membership (conf-stat->conf-no conf) t)) (lyskom-report-command-answer nil)) (lyskom-insert-string 'no-ok)))))) ;; DEBUG+++ (lyskom-continue-prefetch) )) (defun lyskom-do-go-to-conf (conf-stat membership) "Go to a conference. Args: CONF-STAT MEMBERSHIP. Put a read-info of type CONF first on lyskom-reading-list. Args: CONF-STAT MEMBERSHIP" (let ((priority (lyskom-get-current-priority))) (lyskom-maybe-move-unread nil) (if conf-stat (lyskom-set-mode-line conf-stat)) (let ((r 0) (len (read-list-length lyskom-to-do-list)) (found nil)) (while (and (not found) (< r len)) (if (and (read-info->conf-stat (read-list->nth lyskom-to-do-list r)) (= (conf-stat->conf-no conf-stat) (conf-stat->conf-no (read-info->conf-stat (read-list->nth lyskom-to-do-list r))))) (setq found t) (++ r))) (cond (found (let ((read-info (read-list->nth lyskom-to-do-list r))) (read-list-enter-first read-info lyskom-reading-list) (read-list-delete-read-info (conf-stat->conf-no conf-stat) lyskom-to-do-list) (read-list-enter-first read-info lyskom-to-do-list) (set-read-info->priority read-info priority) (lyskom-enter-conf conf-stat read-info))) (t (lyskom-go-to-empty-conf conf-stat)))))) (defun lyskom-go-to-empty-conf (conf-stat) "Go to a conference with no unseen messages. Args: CONF-STAT." (let ((old-current-conf lyskom-current-conf)) (unless lyskom-is-anonymous (blocking-do 'pepsi (conf-stat->conf-no conf-stat))) (lyskom-run-hook-with-args 'lyskom-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat)) (lyskom-run-hook-with-args 'kom-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat)) (setq lyskom-current-conf (conf-stat->conf-no conf-stat)) (lyskom-enter-conf-print-unread conf-stat 0) (lp--update-buffer old-current-conf) (lp--update-buffer lyskom-current-conf) (lyskom-run-hook-with-args 'lyskom-after-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat)) (lyskom-run-hook-with-args 'kom-after-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat)))) (defun lyskom-get-current-priority () "Return the current priority level." (or (and (read-list->first lyskom-reading-list) (read-info->priority (read-list->first lyskom-reading-list))) (and (read-list->first lyskom-to-do-list) (read-info->priority (read-list->first lyskom-to-do-list))) -1)) ;;; ================================================================ ;;; Skriva inl{gg - write text ;;; Author: ??? (def-kom-command kom-write-text (&optional arg) "Start writing a new text that isn't a comment to any existing text. With a prefix argument don't ask for a recipient. Several settings affect writing texts in general. `kom-write-texts-in-window' controls which window is used to write the comment; `kom-confirm-multiple-recipients' affects how multiple recipients are handled." (interactive "P") (lyskom-tell-internat 'kom-tell-write-text) (lyskom-write-text arg 'who-send-text-to)) (defun lyskom-write-text (arg prompt) "Start writing a new text." (lyskom-nag-about-presentation) (let* ((tono (cond ((and arg (listp arg) lyskom-current-conf (not (eq 0 lyskom-current-conf))) lyskom-current-conf) ((numberp arg) arg) (t (lyskom-read-conf-no prompt '(pers conf) nil nil t)))) (conf-stat (blocking-do 'get-conf-stat tono))) (cache-del-conf-stat tono) (if (if (zerop (conf-stat->msg-of-day conf-stat)) t (progn (recenter 1) (lyskom-format-insert 'has-motd conf-stat) (lyskom-view-text (conf-stat->msg-of-day conf-stat)) (if (lyskom-j-or-n-p (lyskom-get-string 'motd-persist-q)) t nil))) (if (= tono lyskom-pers-no) (lyskom-edit-text lyskom-proc (lyskom-create-misc-list 'RECPT tono) "" "") (lyskom-edit-text lyskom-proc (if (lyskom-get-membership tono) (lyskom-create-misc-list 'RECPT tono) (lyskom-create-misc-list 'RECPT tono 'RECPT lyskom-pers-no)) "" ""))))) ;;; ================================================================ ;;; Lista Personer - List persons ;;; ;;; Author: ceder ;;; Rewritten: linus (def-kom-command kom-list-persons (match) "List all persons whose names start with a particular string. For more flexible listing, use kom-list-re instead." (interactive (list (lyskom-read-string (lyskom-get-string 'search-for-pers)))) (let ((result (blocking-do 'lookup-z-name match 1 0))) (if result (if (conf-z-info-list->conf-z-infos result) (lyskom-traverse info (conf-z-info-list->conf-z-infos result) (lyskom-list-pers-print info)) (lyskom-format-insert 'no-matching-perss match)) (lyskom-insert (lyskom-current-error))))) (defun lyskom-list-pers-print (conf-z) "Print name of the person CONF-NO for kom-list-persons." (lyskom-format-insert "%[%#1@%5#2:p %#2P%]\n" (lyskom-default-button 'pers (conf-z-info->conf-no conf-z)) conf-z)) ;;; ================================================================ ;;; Lista M|ten - List conferences ;;; Author: ceder ;;; Rewritten: linus (def-kom-command kom-list-conferences (&optional match) "List all conferences whose names start with a particular string. Those that you are not a member in will be marked with an asterisk. For more flexible searching, use `kom-list-re'." (interactive) (unless kom-allow-incompleteness (sit-for 0) (lyskom-prefetch-all-confs)) (setq match (or match (lyskom-read-string (lyskom-get-string 'search-for-conf)))) (let ((result (blocking-do 'lookup-z-name match 0 1))) (if result (if (conf-z-info-list->conf-z-infos result) (progn (lyskom-traverse info (conf-z-info-list->conf-z-infos result) (lyskom-list-conf-print info)) (lyskom-insert 'conf-list-legend)) (lyskom-format-insert 'no-matching-confs match)) (lyskom-insert (lyskom-current-error))))) (def-kom-command kom-list-created-conferences (arg) "List all conferences created by a particular person. With a prefix argument, also list persons created by that person. See `kom-allow-incompleteness'." (interactive "P") (unless kom-allow-incompleteness (sit-for 0) (lyskom-prefetch-all-confs)) (blocking-do 'get-uconf-stat lyskom-pers-no) (let ((pers (lyskom-read-conf-stat (if arg 'list-pers-confs-created-by 'list-confs-created-by) '(all) nil nil t))) (lyskom-format-insert 'listing-confs-created-by (conf-stat->conf-no pers)) (lyskom-message (lyskom-get-string (if arg 'getting-all-pers-confs 'getting-all-confs))) (let ((result (blocking-do 'lookup-z-name "" (if arg 1 0) 1))) (lyskom-message (lyskom-get-string (if arg 'getting-all-pers-confs-done 'getting-all-confs-done))) (if result (if (conf-z-info-list->conf-z-infos result) (let ((counter (vector nil 1 (length (conf-z-info-list->conf-z-infos result)) 0)) (calls nil) (was-at-max (= (save-excursion (end-of-line) (point)) (point-max)))) (condition-case arg (progn (lyskom-traverse conf-z (conf-z-info-list->conf-z-infos result) (setq calls (cons (initiate-get-conf-stat 'main 'lyskom-list-created-conferences-2 (conf-z-info->conf-no conf-z) counter (conf-stat->conf-no pers) arg ) calls))) (lyskom-wait-queue 'main) (if (eq 0 (elt counter 3)) (lyskom-format-insert 'no-created-confs pers) (let ((window (get-buffer-window (current-buffer)))) (if (and window was-at-max) (if (pos-visible-in-window-p (point-max) window) (goto-char (point-max)) (and kom-continuous-scrolling (lyskom-scroll))))))) (quit (aset counter 0 t) (lyskom-cancel-call 'main calls) (signal 'quit nil)))) (lyskom-insert (lyskom-get-string (if arg 'no-pers-confs-exist 'no-confs-exist)))) (lyskom-format-insert (lyskom-current-error)))))) (defun lyskom-list-conf-membership-char (conf-no) (if lyskom-membership-is-read (cond ((lyskom-get-membership conf-no) ?\ ) ((lyskom-get-membership conf-no t) ?-) (t ?*)) (cond ((lyskom-try-get-membership conf-no) ?\ ) ((lyskom-try-get-membership conf-no t) ?-) (t ?\?)))) (defun lyskom-list-created-conferences-2 (cs counter pers-no arg) (unless (elt counter 0) (aset counter 1 (1+ (elt counter 1))) (lyskom-message (lyskom-format (if arg 'finding-created-pers-confs 'finding-created-confs) (elt counter 1) (elt counter 2))) (when (and cs (memq pers-no (list (conf-stat->creator cs) (conf-stat->supervisor cs) (conf-stat->super-conf cs)))) (aset counter 3 (1+ (elt counter 3))) (lyskom-format-insert "%5#2m %5#6d %#3c %4#4s %#5s %#2M\n" (lyskom-default-button 'conf (conf-stat->conf-no cs)) cs (lyskom-list-conf-membership-char (conf-stat->conf-no cs)) (concat (if (eq pers-no (conf-stat->creator cs)) (lyskom-get-string 'created-conf-letter) " ") (if (eq pers-no (conf-stat->supervisor cs)) (lyskom-get-string 'supervisor-conf-letter) " ") (if (and (conf-type->original (conf-stat->conf-type cs)) (eq pers-no (conf-stat->super-conf cs))) (lyskom-get-string 'superconf-conf-letter) " ")) (cond ((conf-type->secret (conf-stat->conf-type cs)) (lyskom-get-string 'secret-conf-letter)) ((conf-type->rd_prot (conf-stat->conf-type cs)) (lyskom-get-string 'protected-conf-letter)) (t " ")) (conf-stat->garb-nice cs)) (sit-for 0)))) (defun lyskom-list-conf-print (conf-z) "Print a line of info about CONF-NO. If you are not member in the conference it will be flagged with an asterisk." (lyskom-format-insert "%5#1m %#2c %#1M\n" conf-z (lyskom-list-conf-membership-char (conf-z-info->conf-no conf-z)))) ;;; ================================================================ ;;; Lista med regexpar - List regexp (defun lyskom-make-re-case-insensitive (re) "Convert the regexp RE to a case insensitive regexp." (unless lyskom-char-classes (setq lyskom-char-classes (lyskom-compute-char-classes lyskom-collate-table))) (let ((res nil) (input (listify-vector re)) val) (while input (cond ;; Copy "[]" character sets literally. ((eq (car input) ?\[) (setq res (cons "[" res)) (setq input (cdr input)) (when input ;Handle "[]asdf]" properly. (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input))) (while (and input (not (eq (car input) ?\]))) (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input))) (when input ;Don't forget the terminating "]". (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input)))) ;; Copy backslashed sequences literally. ((eq (car input) ?\\) (setq res (cons "\\" res)) (setq input (cdr input)) (when input (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input)))) ;; Copy special characters literally. ((memq (car input) '(?\( ?\) ?\| ?+ ?\* ?\?)) (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input))) ;; Create "[]" character sets for equivalent characters. ((setq val (cdr-safe (assoc (car input) lyskom-char-classes))) (setq res (cons "[" res)) (if (member "]" val) ;"]" must come first. (setq res (cons "]" res))) (while val (cond ((string= "]" (car val))) ;already handled ((string= "-" (car val)) (setq res (cons "---" res))) (t (setq res (cons (car val) res)))) (setq val (cdr val))) (setq res (cons "]" res)) (setq input (cdr input))) ;; Copy other characters literally. (t (setq res (cons (make-string 1 (car input)) res)) (setq input (cdr input))))) (apply 'concat (nreverse res)))) (def-kom-command kom-list-re (regexp &optional case-sensitive what) "List all persons and conferences whose names match a particular regular expression. Regular expressions are case insensitive. You will be asked whether to look for persons, conferences, or both. Lisp documentation: By default, the regexp will be converted so that the match is performed in a case insensitive way. If the optional argument CASE-SENSITIVE is true, that conversion will not be performed. If the optional argument WHAT is 'person, only persons will be listed. If it is 'conf, only conferences will be listed." (interactive (let ((xwhat (let ((sel (lyskom-a-or-b-or-c-p 'search-re-for-what '(search-re-confs search-re-persons search-re-all) 'search-re-all))) (cond ((eq sel 'search-re-all) nil) ((eq sel 'search-re-persons) 'pers) ((eq sel 'search-re-confs) 'conf) (t nil))))) (list (lyskom-read-string (lyskom-get-string 'search-re)) current-prefix-arg xwhat))) (unless case-sensitive (setq regexp (lyskom-make-re-case-insensitive regexp))) (lyskom-format-insert (cond ((eq what 'pers) 'matching-regexp-perss) ((eq what 'conf) 'matching-regexp-confs) (t 'matching-regexp)) regexp) (let ((conf-list (blocking-do 're-z-lookup regexp (if (eq what 'conf) 0 1) (if (eq what 'pers) 0 1)))) (if conf-list (if (conf-z-info-list->conf-z-infos conf-list) (lyskom-traverse czi (conf-z-info-list->conf-z-infos conf-list) (lyskom-format-insert "%[%#1@%5#2:m %#3c %#2:M%]\n" (lyskom-default-button 'conf (conf-z-info->conf-no czi)) czi (if (conf-type->letterbox (conf-z-info->conf-type czi)) ?P ?M) )) (lyskom-format-insert (cond ((eq what 'pers) 'no-matching-perss) ((eq what 'conf) 'no-matching-confs) (t 'no-matching-anys)) regexp)) (lyskom-format-insert (lyskom-current-error))))) ;;; ================================================================ ;;; [ndra namn - Change name ;;; Author: Inge Wallin ;;; Changed by: Peter Eriksson(?) ;;; Changed again: Inge Wallin ;;; Rewritten: linus (def-kom-command kom-change-name () "Change the name of a person or conference. In order to change the name of a conference or person, you need to be the supervisor of that conference or person." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'name-to-be-changed '(all) nil nil t))) (if (null conf-stat) (lyskom-insert-string 'no-such-conf-or-pers) (let (name) (lyskom-format-insert 'about-to-change-name-from conf-stat) (lyskom-scroll) (lyskom-tell-internat 'kom-tell-change-name) (setq name (lyskom-read-string (lyskom-get-string 'new-name) (conf-stat->name conf-stat))) (if (blocking-do 'change-name (conf-stat->conf-no conf-stat) name) (progn (lyskom-format-insert 'change-name-done name (lyskom-default-button 'conf conf-stat)) (cache-del-conf-stat (conf-stat->conf-no conf-stat))) (lyskom-format-insert 'change-name-nope name (lyskom-get-error-text lyskom-errno) lyskom-errno)))))) ;;; ================================================================ ;;; [ndra parentes - Change parenthesis ;;; Author: Per Cederqvist (template stolen from kom-change-name) (def-kom-command kom-change-parenthesis () "Change parenthsized contents in the name of a person or conference. In some LysKOM communities it is popular to put a witticism enclosed in parenthesis at the end of one's name. This command is intended to make it easy to change this information." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'name-to-be-changed '(all) nil nil t))) (if (null conf-stat) (lyskom-insert-string 'no-such-conf-or-pers) (cond ((string-match ".*(.*).*(.*)" (conf-stat->name conf-stat)) (lyskom-insert-string 'too-many-parens-in-name)) ((string-match "^\\(.*\\)(\\(.*\\))\\(.*\\)$" (conf-stat->name conf-stat)) (let* ((pre-paren (match-string 1 (conf-stat->name conf-stat))) (post-paren (match-string 3 (conf-stat->name conf-stat))) (old-paren (match-string 2 (conf-stat->name conf-stat))) (paren (lyskom-read-string (lyskom-get-string 'new-paren) old-paren)) (name (concat pre-paren "(" paren ")" post-paren))) (if (blocking-do 'change-name (conf-stat->conf-no conf-stat) name) (progn (lyskom-format-insert 'change-name-done name (lyskom-default-button 'conf conf-stat)) (cache-del-conf-stat (conf-stat->conf-no conf-stat))) (lyskom-format-insert 'change-name-nope name (lyskom-get-error-text lyskom-errno) lyskom-errno)))) (t (lyskom-insert-string 'no-paren-in-name)))))) ;;; ================================================================ ;;; [ndra organisat|r - Change supervisor ;;; Author: Inge Wallin ;;; Rewritten: linus (def-kom-command kom-change-supervisor () "Change the supervisor of a person or conference. You need to be the supervisor of the person or conference to perform this operation." (interactive) (let ((supervisee (lyskom-read-conf-stat 'who-to-change-supervisor-for '(all) nil nil t))) (if (null supervisee) (lyskom-insert-string 'no-such-conf-or-pers) (lyskom-tell-internat 'kom-tell-change-supervisor) (let ((supervisor (lyskom-read-conf-stat 'new-supervisor '(all) nil nil t))) (lyskom-format-insert 'change-supervisor-from-to supervisee supervisor) (if (blocking-do 'set-supervisor (conf-stat->conf-no supervisee) (conf-stat->conf-no supervisor)) (progn (lyskom-insert-string 'done) (cache-del-conf-stat (conf-stat->conf-no supervisee))) (lyskom-format-insert 'change-supervisor-nope supervisee)))))) ;;; ================================================================ ;;; Markera och Avmarkera - Mark and Unmark a text ;;; Author: Inge Wallin ;;; Modified by: Linus Tolke, Johan Sundström, Joel Rosdahl (def-kom-command kom-mark-text (&optional text-no) "Mark a text. The settings `kom-symbolic-marks-alist' and `kom-default-mark' control what mark to set." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-mark))) (if text-no (lyskom-mark-text text-no) (lyskom-insert 'confusion-what-to-mark))) (def-kom-command kom-unmark-text (&optional text-no) "Unmark a text that was previously marked." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-unmark))) (if text-no (lyskom-unmark-text text-no) (lyskom-insert 'confusion-what-to-unmark))) (defun lyskom-unmark-text (text-no) "Do the actual unmarking of the text TEXT-NO." (lyskom-format-insert 'unmarking-textno text-no) (if (blocking-do 'unmark-text text-no) (progn (lyskom-insert-string 'done) (cache-del-marked-text text-no)) (lyskom-insert-string 'nope)) ;+++ lyskom-errno? (cache-del-text-stat text-no)) (defun lyskom-mark-text (text-no &optional mark) "Mark TEXT-NO using kom-default-mark (if non-nil) or prompt the user for what mark to use." (let ((mark (or mark kom-default-mark (lyskom-read-mark-type (lyskom-get-string 'what-mark) nil t)))) (lyskom-format-insert 'marking-textno text-no (lyskom-symbolic-mark-type-string mark t) mark) (if (blocking-do 'mark-text text-no mark) (progn (lyskom-insert-string 'done) (cache-add-marked-text text-no mark)) (lyskom-insert-string 'nope)) ;+++ lyskom-errno? (cache-del-text-stat text-no))) (defun lyskom-read-mark-type (prompt &optional nildefault create-nonexistent) "Ask user about symbolic mark type and return the (integer) mark-type. Prompt with PROMPT. If NILDEFAULT is non-nil, nil is returned if the user enters the empty string, otherwise the user is prompted again. If CREATE-NONEXISTENT is t, the user is asked whether the symbolic mark association should be created if it doesn't already exist." (let ((mark-type nil) ; nil: not yet set, 'default: default chosen (completion-ignore-case t) (completions kom-symbolic-marks-alist)) (while (and (not (eq mark-type 'default)) (or (not (integerp mark-type)) (< mark-type 0) (> mark-type 255))) (let* ((mark (lyskom-completing-read prompt (lyskom-maybe-frob-completion-table completions))) (mark-assoc (lyskom-string-assoc mark completions))) (when (null mark) (setq mark "")) (cond ;; Default completion. ((and nildefault (string-equal "" mark)) (setq mark-type 'default)) ((null mark)) ;; Correct completion. (mark-assoc (setq mark-type (cdr mark-assoc))) ;; Incorrect completion, integer entered. ((string-match "\\`\\s-*[0-9]+\\s-*\\'" mark) (setq mark-type (string-to-int mark))) ;; Incorrect completion; create new symbolic mark type. ((and create-nonexistent (not (string= mark "")) (lyskom-j-or-n-p (lyskom-format (lyskom-get-string 'want-to-create-symbolic-mark) mark))) (let ((new-mark-type (lyskom-allocate-mark-type))) (if (not new-mark-type) (lyskom-insert 'no-mark-types-left) (lyskom-format-insert 'creating-symbolic-mark-type mark new-mark-type) (setq kom-symbolic-marks-alist (cons (cons mark new-mark-type) kom-symbolic-marks-alist)) (lyskom-save-options (current-buffer) (lyskom-get-string 'saving-settings) (lyskom-get-string 'saving-settings-done) (lyskom-get-string 'could-not-save-options)) (setq mark-type new-mark-type)))) ;; Incorrect completion. (t (lyskom-insert 'erroneous-mark))))) (if (eq mark-type 'default) nil mark-type))) (defun lyskom-allocate-mark-type () "Returns the first mark type available that is neither named nor used. If no such type existed, the least used non-named mark type is returned. If no such existed either, nil is returned." (setq kom-symbolic-marks-alist (sort kom-symbolic-marks-alist (function (lambda (x y) (< (cdr x) (cdr y)))))) (let ((i 0) (list kom-symbolic-marks-alist) (used (lyskom-get-least-used-mark-types-alist)) (found nil)) (while (and (not found) (< i 256)) (when (not (assq i used)) ; mark type i not presently used? (when list (if (= i (cdr (car list))) ; already named? (setq list (cdr list)) (setq found t)))) ; neither used nor named! (when (not found) (++ i))) (if (and found (< i 256)) i ; no unused and unnamed mark type available; fall back ; to the least used not-yet-named type, if available: (when (and used (< (length used) 256) (< (length list) 256)) (cdr (car used)))))) (defun lyskom-get-least-used-mark-types-alist () "Returns an alist from mark type to number of such marks, ordered by increasing number of marks per mark type (and, when equal, by mark type)." (let ((mark-list (cache-get-marked-texts)) (cnt-alist nil)) ; the number of texts marked by each mark type ;; Count the number of texts marked per mark type: (while (not (null mark-list)) (let ((mark (car mark-list))) (when mark (let* ((type (mark->mark-type mark)) (tcnt (assq type cnt-alist))) (when tcnt (setq tcnt (cdr tcnt))) (setq cnt-alist (lyskom-set-alist cnt-alist type (if (null tcnt) 1 (1+ tcnt))))))) (setq mark-list (cdr mark-list))) ;; Sort the list, least-used, lowest number of mark type first: (sort cnt-alist (function (lambda (x y) (cond ((< (cdr x) (cdr y)) t) ((= (cdr x) (cdr y)) (< (car x) (car y))) (t nil))))))) ;;; ================================================================ ;;; ]terse alla markerade - Review marked texts ;;; Author: Inge Wallin ;;; Modified by: Joel Rosdahl (def-kom-command kom-review-marked-texts () "Review all texts you have marked with a particular mark." (interactive) (lyskom-review-marked-texts (lyskom-read-mark-type (lyskom-get-string 'what-mark-to-view) t))) (def-kom-command kom-review-all-marked-texts () "Review all texts you have marked, regardless of mark." (interactive) (lyskom-review-marked-texts nil)) (def-kom-command kom-unread-marked-texts () "Mark all texts you have marked with a particular mark as unread." (interactive) (lyskom-unread-marked-texts (lyskom-read-mark-type (lyskom-get-string 'what-mark-to-unread) t))) (def-kom-command kom-unread-all-marked-texts () "Mark all texts you have marked, regardless of mark, as unread." (interactive) (lyskom-unread-marked-texts nil)) (defun lyskom-unread-marked-texts (mark-no) "Mark all marked texts with the mark equal to MARK-NO unread. If MARK-NO is nil, review all marked texts." (let ((text-list (lyskom-get-marked-texts mark-no))) (if (null text-list) (lyskom-insert (if (null mark-no) (lyskom-get-string 'no-marked-texts) (lyskom-format 'no-marked-texts-mark (lyskom-symbolic-mark-type-string mark-no)))) (lyskom-traverse text-no text-list (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no)))))) (defun lyskom-review-marked-texts (mark-no) "Review all marked texts with the mark equal to MARK-NO. If MARK-NO is nil, review all marked texts." (let ((text-list (lyskom-get-marked-texts mark-no))) (if (null text-list) (lyskom-insert (if (null mark-no) (lyskom-get-string 'no-marked-texts) (lyskom-format 'no-marked-texts-mark (lyskom-symbolic-mark-type-string mark-no)))) (let ((read-info (lyskom-create-read-info 'REVIEW-MARK nil (lyskom-review-get-priority) (lyskom-create-text-list text-list) nil t))) (read-list-enter-read-info read-info lyskom-reading-list t) (read-list-enter-read-info read-info lyskom-to-do-list t))))) (defun lyskom-get-marked-texts (mark-no) "Return a list of all texts marked with MARK-NO." (let ((text-list nil)) (lyskom-traverse mark (cache-get-marked-texts) (if (and mark (or (null mark-no) (eq mark-no (mark->mark-type mark)))) (setq text-list (cons (mark->text-no mark) text-list)))) text-list)) ;;; ================================================================ ;;; [ndra L|senord - Change password ;;; Author: Inge Wallin (def-kom-command kom-change-password () "Change the password for a person. To change the password for a person you need either the old password for the person, or have administrative privileges enabled." (interactive) (let ((pers-no (lyskom-read-conf-no 'whos-passwd '(pers) nil nil t)) (old-pw (silent-read (lyskom-get-string 'old-passwd))) (new-pw1 (silent-read (lyskom-get-string 'new-passwd))) (new-pw2 (silent-read (lyskom-get-string 'new-passwd-again)))) (if (lyskom-string= new-pw1 new-pw2) (progn (lyskom-insert-string 'changing-passwd) (lyskom-report-command-answer (blocking-do 'set-passwd (if (zerop pers-no) lyskom-pers-no pers-no) old-pw new-pw1))) (lyskom-insert-string 'retype-dont-match)))) ;;; ================================================================ ;;; (Se) Tiden - display time and date. (defconst lyskom-times '(((nil 1 1 nil nil nil) . newyearday) ((nil 1 6 nil nil nil) . 13dayxmas) ((nil 1 13 nil nil nil) . 20dayxmas) ((nil 2 2 nil nil nil) . kyndeldag) ((nil 2 29 nil nil nil) . skottdag) ((nil 3 8 nil nil nil) . intwomday) ((nil 3 25 nil nil nil) . mariebdag) ((nil 3 29 nil nil nil) . lysbday) ((nil 4 30 nil nil nil) . cgdag) ((nil 6 6 nil nil nil) . sixjune) ((nil 6 24 nil nil nil) . johannesdday) ((nil 8 15 nil nil nil) . holdnose) ((nil 10 24 nil nil nil) . fnday) ((nil 11 1 nil nil nil) . allhelgonadag) ((nil 12 13 nil nil nil) . luciaday) ((nil 12 24 nil nil nil) . xmaseve) ((nil 12 25 nil nil nil) . xmasday) ((nil 12 28 nil nil nil) . varnlosdag) ((nil 12 31 nil nil nil) . newyeareve) ((nil 12 31 23 nil nil) . newyearevelate) )) (lyskom-with-external-functions (calendar-iso-from-absolute calendar-absolute-from-gregorian) (def-kom-command kom-display-time () "Display the current date and time, according to the server. If `kom-show-week-number', include the ISO week number. Display of today's name is controlled by `kom-show-namedays'." (interactive) (let ((time (lyskom-current-server-time)) (lyskom-last-text-format-flags nil) (weekno nil)) (lyskom-format-insert (if kom-show-week-number (condition-case nil (progn (require 'calendar) (require 'cal-iso) (setq weekno (car (calendar-iso-from-absolute (calendar-absolute-from-gregorian (list (time->mon time) (time->mday time) (time->year time)))))) 'time-is-week) (error 'time-is)) 'time-is) (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss time) ;; Kult: (if (and (= (time->hour time) (+ (/ (time->sec time) 10) (* (% (time->sec time) 10) 10))) (= (/ (time->min time) 10) (% (time->min time) 10))) (lyskom-get-string 'palindrome) "") weekno) ;; Mera kult (mapcar (function (lambda (el) (let ((when (car el)) (event (cdr el))) (if (and (or (null (elt when 0)) (= (time->year time) (elt when 0))) (or (null (elt when 1)) (= (time->mon time) (elt when 1))) (or (null (elt when 2)) (= (time->mday time) (elt when 2))) (or (null (elt when 3)) (= (time->hour time) (elt when 3))) (or (null (elt when 4)) (= (time->min time) (elt when 4))) (or (null (elt when 5)) (= (time->sec time) (elt when 5)))) (condition-case nil (progn (lyskom-insert " ") (lyskom-format-insert "%#1t" (lyskom-format event (time->year time) (time->mon time) (time->mday time) (time->hour time) (time->min time) (time->sec time)))) (error nil)))))) lyskom-times) (when kom-show-namedays (let ((tmp (lyskom-nameday time))) (when tmp (lyskom-insert "\n") (lyskom-insert tmp))))) (lyskom-insert "\n")) ) ;;; ================================================================ ;;; Vilka ({r inloggade) - Who is on? ;;; ;;; Author: ??? ;;; Rewritten by: David K}gedal (put 'lyskom-no-users 'error-conditions '(error lyskom-error lyskom-no-users)) (def-kom-command kom-who-is-on (&optional arg) "Display a list of active connected users. With a positive prefix argument ARG, list sessions who have been active in the last ARG minutes. With a positive zero prefix argument \(i.e. \"0\", not \"-0\"), list all visible sessions. With a negative nonzero prefix argument ARG, list both visible and invisible sessions who have been active in the last -ARG minutes. With a negative zero prefix argument (C-u -), list all sessions. Several variables affect display. See `kom-show-where-and-what', `kom-show-since-and-when' and `kom-idle-hide' for more information." (interactive "P") (condition-case nil (if (lyskom-have-feature dynamic-session-info) (lyskom-who-is-on-9 arg) (lyskom-who-is-on-8)) (lyskom-no-users (lyskom-insert (lyskom-get-string 'null-who-info))))) ;;; ================================================================ ;;; Vilka ({r inloggade i) möte - Who is on in a conference? ;;; Author: petli (def-kom-command kom-who-is-on-in-conference (&optional arg) "Display a list of all connected users who are members of a particular cnoference. With a positive prefix argument ARG, list sessions who have been active in the last ARG minutes. With a positive zero prefix argument \(i.e. \"0\", not \"-0\"), list all visible sessions. With a negative nonzero prefix argument ARG, list both visible and invisible sessions who have been active in the last -ARG minutes. With a negative zero prefix argument \(C-u -), list all sessions. Several variables affect display. See `kom-show-where-and-what', `kom-show-since-and-when' and `kom-idle-hide' for more information." (interactive "P") (let ((conf-stat (lyskom-read-conf-stat 'who-is-on-in-what-conference '(all) nil nil t))) (condition-case nil (if (lyskom-have-feature dynamic-session-info) (lyskom-who-is-on-9 arg conf-stat) (lyskom-who-is-on-8 conf-stat)) (lyskom-no-users (lyskom-insert (lyskom-get-string 'null-who-info)))))) ;;; ================================================================ ;;; Vilka ({r n{rvarande i) möte - Who is present in a conference? ;;; Author: Christer Ekholm ;;; Copied from kom-who-is-on-in-conference by petli (def-kom-command kom-who-is-present-in-conference (&optional arg) "Display a list of all connected users currently present in a particular conference. With a positive prefix argument ARG, list sessions who have been active in the last ARG minutes. With a positive zero prefix argument \(i.e. \"0\", not \"-0\"), list all visible sessions. With a negative nonzero prefix argument ARG, list both visible and invisible sessions who have been active in the last -ARG minutes. With a negative zero prefix argument \(C-u -), list all sessions. Several variables affect display. See `kom-show-where-and-what', `kom-show-since-and-when' and `kom-idle-hide' for more information." (interactive "P") (let ((conf-stat (lyskom-read-conf-stat 'who-is-present-in-what-conference '(all) nil nil t))) (condition-case nil (if (lyskom-have-feature dynamic-session-info) (lyskom-who-is-on-9 arg conf-stat t) (lyskom-who-is-on-8 conf-stat t)) (lyskom-no-users (lyskom-insert (lyskom-get-string 'null-who-info)))))) ;;; ================================================================ ;;; Vilka vänner (är inloggade) - What friends are on ;;; Author: Ulrik Haugen (def-kom-command kom-who-is-on-and-friend (&optional arg) "Display a list of all connected users in `kom-friends'. With a positive prefix argument ARG, list sessions who have been active in the last ARG minutes. With a positive zero prefix argument \(i.e. \"0\", not \"-0\"), list all visible sessions. With a negative nonzero prefix argument ARG, list both visible and invisible sessions who have been active in the last -ARG minutes. With a negative zero prefix argument \(C-u -), list all sessions. Several variables affect display. See `kom-show-where-and-what', `kom-show-since-and-when' and `kom-idle-hide' for more information." (interactive "P") (condition-case nil (if (lyskom-have-feature dynamic-session-info) (lyskom-who-is-on-9 arg nil nil t) (lyskom-who-is-on-8 nil nil t)) (lyskom-no-users (lyskom-insert (lyskom-get-string 'null-who-info))))) (defun lyskom-who-is-on-8 (&optional conf-stat show-present-only show-friends-only) "Display a list of all connected users. Uses Protocol A version 8 calls" (let* ((who-info-list (blocking-do 'who-is-on)) (who-list (sort (funcall (if show-friends-only #'lyskom-select-friends-from-who-list #'identity) (cond (show-present-only (lyskom-who-is-present-check-membership-8 who-info-list conf-stat)) (conf-stat (lyskom-who-is-on-check-membership-8 who-info-list conf-stat)) (t (listify-vector who-info-list)))) (function (lambda (who1 who2) (< (who-info->connection who1) (who-info->connection who2)))))) (total-users (length who-list)) (session-width (1+ (length (int-to-string (who-info->connection (nth (1- total-users) who-list)))))) (format-string-1 (lyskom-info-line-format-string session-width "P" "M")) (format-string-2 (lyskom-info-line-format-string session-width "s" "s")) (lyskom-default-conf-string 'not-present-anywhere) (lyskom-default-pers-string 'unknown-person)) (cond (show-friends-only (lyskom-format-insert 'who-is-friend)) (show-present-only (lyskom-format-insert 'who-is-active-and-present conf-stat)) (conf-stat (lyskom-format-insert 'who-is-active-and-member conf-stat))) (lyskom-format-insert format-string-2 "" (lyskom-get-string 'lyskom-name) (lyskom-get-string 'is-in-conf)) (if kom-show-where-and-what (lyskom-format-insert format-string-2 "" (lyskom-get-string 'from-machine) (lyskom-get-string 'is-doing))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 1) ?-) "\n")) (while who-list (let* ((who-info (car who-list)) (session-no (int-to-string (who-info->connection who-info))) (my-session (if (= lyskom-session-no (who-info->connection who-info)) "*" " "))) (lyskom-format-insert format-string-1 (concat session-no my-session) (who-info->pers-no who-info) (or (who-info->working-conf who-info) (lyskom-get-string 'not-present-anywhere))) (if kom-show-where-and-what (lyskom-format-insert format-string-2 "" (lyskom-return-username who-info) (concat "(" (or (string-replace-match "\n" (who-info->doing-what who-info) " " t t) (who-info->doing-what who-info)")"))))) (setq who-list (cdr who-list))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 1) ?-) "\n")) (lyskom-insert (lyskom-format 'total-visible-users total-users (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss))))) (defun lyskom-who-is-on-9 (arg &optional conf-stat show-present-only show-friends-only) "Display a list of all connected users. Uses Protocol A version 9 calls" (let* ((wants-invisibles (or (and (numberp arg) (< arg 0)) (and (symbolp arg) (eq '- arg)))) (idle-hide (if (numberp arg) (abs arg) (cond ((eq '- arg) 0) ((numberp kom-idle-hide) kom-idle-hide) (kom-idle-hide 30) (t 0)))) (who-info-list (blocking-do 'who-is-on-dynamic 't wants-invisibles (* idle-hide 60))) (who-list (sort (funcall (if show-friends-only #'lyskom-select-friends-from-who-list #'identity) (cond (show-present-only (lyskom-who-is-present-check-membership-9 who-info-list conf-stat)) (conf-stat (lyskom-who-is-on-check-membership-9 who-info-list conf-stat)) (t (listify-vector who-info-list)))) (function (lambda (who1 who2) (< (dynamic-session-info->session who1) (dynamic-session-info->session who2)))))) (total-users (length who-list)) (session-width (if (null who-list) (signal 'lyskom-no-users nil) (1+ (length (int-to-string (dynamic-session-info->session (nth (1- total-users) who-list))))))) (format-string-1 (lyskom-info-line-format-string session-width "P" "M")) (format-string-2 (lyskom-info-line-format-string session-width "D" "s")) (format-string-3 (lyskom-info-line-format-string session-width "D" "s")) (lyskom-default-conf-string 'not-present-anywhere) (lyskom-default-pers-string 'unknown-person)) (if (zerop idle-hide) (lyskom-insert (lyskom-get-string 'who-is-active-all)) (lyskom-format-insert 'who-is-active-last-minutes idle-hide)) (if wants-invisibles (lyskom-insert (lyskom-get-string 'showing-invisibles))) (cond (show-friends-only (lyskom-format-insert 'who-is-friend)) (show-present-only (lyskom-format-insert 'who-is-active-and-present conf-stat)) (conf-stat (lyskom-format-insert 'who-is-active-and-member conf-stat))) (lyskom-format-insert format-string-2 "" (lyskom-get-string 'lyskom-name) (lyskom-get-string 'is-in-conf)) (if kom-show-where-and-what (lyskom-format-insert format-string-2 "" (lyskom-get-string 'from-machine) (lyskom-get-string 'is-doing))) (if kom-show-since-and-when (lyskom-format-insert format-string-3 "" (lyskom-get-string 'connection-time) (lyskom-get-string 'active-last))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 1) ?-) "\n")) (while who-list (let* ((who-info (car who-list)) (session-no (dynamic-session-info->session who-info)) (session-no-s (int-to-string session-no)) (my-session (if (= lyskom-session-no session-no) "*" " "))) (lyskom-format-insert format-string-1 (concat session-no-s my-session) (dynamic-session-info->person who-info) (or (dynamic-session-info->working-conference who-info) (lyskom-get-string 'not-present-anywhere))) (if kom-show-where-and-what (let* (static defer-info username) (cond (kom-deferred-printing (setq static (cache-get-static-session-info session-no)) (if static (setq username (lyskom-combine-username (static-session-info->username static) (static-session-info->ident-user static) (static-session-info->hostname static))) (setq defer-info (lyskom-create-defer-info 'get-static-session-info session-no 'lyskom-insert-deferred-session-info (make-marker) (length lyskom-defer-indicator) "%#1s")) (setq username defer-info))) (t (setq static (blocking-do 'get-static-session-info session-no)) (setq username (lyskom-combine-username (static-session-info->username static) (static-session-info->ident-user static) (static-session-info->hostname static))))) (lyskom-format-insert format-string-2 "" username (concat "(" (or (string-replace-match "\n" (dynamic-session-info->what-am-i-doing who-info) " " t t) (dynamic-session-info->what-am-i-doing who-info)) ")")))) (if kom-show-since-and-when (let ((active (if (session-flags->user_active_used (dynamic-session-info->flags who-info)) (if (< (dynamic-session-info->idle-time who-info) 60) (lyskom-get-string 'active) (lyskom-format-secs (dynamic-session-info->idle-time who-info))) (lyskom-get-string 'Unknown2)) ) defer-info static since) (cond (kom-deferred-printing (setq static (cache-get-static-session-info session-no)) (if static (setq since (upcase-initials (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss (static-session-info->connection-time static)))) (setq defer-info (lyskom-create-defer-info 'get-static-session-info session-no 'lyskom-insert-deferred-session-info-since (make-marker) (length lyskom-defer-indicator) "%#1s")) (setq since defer-info))) (t (setq static (blocking-do 'get-static-session-info session-no)) (setq since (upcase-initials (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss (static-session-info->connection-time static)))))) (lyskom-format-insert format-string-3 "" since active))) (setq who-list (cdr who-list)))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 1) ?-) "\n")) (lyskom-insert (lyskom-format (cond ((and wants-invisibles (zerop idle-hide)) 'total-users) (wants-invisibles 'total-active-users) ((zerop idle-hide) 'total-visible-users) (t 'total-visible-active-users)) total-users (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss))))) (defun lyskom-who-is-on-check-membership-8 (who-info-list conf-stat) "Returns a list of those in WHO-INFO-LIST which is member in CONF-STAT." (let ((members (blocking-do 'get-members (conf-stat->conf-no conf-stat) 0 (conf-stat->no-of-members conf-stat))) (len (length who-info-list)) (i 0) (res nil) (mship nil)) (while (< i len) (setq mship (lyskom-member-list-find-member (who-info->pers-no (aref who-info-list i)) members)) (when (and mship (not (membership-type->passive (member->membership-type mship)))) (setq res (cons (aref who-info-list i) res))) (setq i (1+ i))) res)) (defun lyskom-who-is-on-check-membership-9 (who-info-list conf-stat) "Returns a list of those in WHO-INFO-LIST which is member in CONF-STAT." (let ((members (blocking-do 'get-members (conf-stat->conf-no conf-stat) 0 (conf-stat->no-of-members conf-stat))) (len (length who-info-list)) (i 0) (res nil) (mship nil)) (while (< i len) (setq mship (lyskom-member-list-find-member (dynamic-session-info->person (aref who-info-list i)) members)) (when (and mship (not (membership-type->passive (member->membership-type mship)))) (setq res (cons (aref who-info-list i) res))) (setq i (1+ i))) res)) (defun lyskom-who-is-present-check-membership-8 (who-info-list conf-stat) "Returns a list of those in WHO-INFO-LIST which is present in CONF-STAT." (let ((len (length who-info-list)) (i 0) (res nil)) (while (< i len) (if (eq (who-info->working-conf (aref who-info-list i)) (conf-stat->conf-no conf-stat)) (setq res (cons (aref who-info-list i) res))) (setq i (1+ i))) res)) (defun lyskom-who-is-present-check-membership-9 (who-info-list conf-stat) "Returns a list of those in WHO-INFO-LIST which is present in CONF-STAT." (let ((len (length who-info-list)) (i 0) (res nil)) (while (< i len) (if (eq (dynamic-session-info->working-conference (aref who-info-list i)) (conf-stat->conf-no conf-stat)) (setq res (cons (aref who-info-list i) res))) (setq i (1+ i))) res)) (defun lyskom-select-friends-from-who-list (who-list) "Returns a list of friends in WHO-LIST" (let ((result nil) (extended-friends (cons lyskom-pers-no kom-friends))) (while (not (null who-list)) (when (memq (dynamic-session-info->person (car who-list)) extended-friends) (setq result (cons (car who-list) result))) (setq who-list (cdr who-list))) result)) (defun lyskom-insert-deferred-session-info (session-info defer-info) (if session-info (lyskom-replace-deferred defer-info (lyskom-combine-username (static-session-info->username session-info) (static-session-info->ident-user session-info) (static-session-info->hostname session-info))) (lyskom-replace-deferred defer-info ""))) (defun lyskom-insert-deferred-session-info-since (session-info defer-info) (if session-info (lyskom-replace-deferred defer-info (upcase-initials (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss (static-session-info->connection-time session-info)))) (lyskom-replace-deferred defer-info ""))) ;;; ===================================================================== ;;; Lista klienter - List clients ;;; Author: David Kågedal ;;; Modified: Daivd Byers (def-kom-command kom-list-clients (prefix) "Display a list of all connected sessions, including current logon and client software. With a positive prefix argument ARG, list sessions who have been active in the last ARG minutes. With a positive zero prefix argument \(i.e. \"0\", not \"-0\"), list all visible sessions. With a negative nonzero prefix argument ARG, list both visible and invisible sessions who have been active in the last -ARG minutes. With a negative zero prefix argument \(C-u -), list all sessions." (interactive "P") (let* ((want-invisible (if prefix t nil)) (who-info-list (blocking-do 'who-is-on-dynamic t want-invisible nil)) (who-list (sort (listify-vector who-info-list) (function (lambda (who1 who2) (< (dynamic-session-info->session who1) (dynamic-session-info->session who2)))))) (total-users (length who-list)) (s-width (1+ (length (int-to-string (dynamic-session-info->session (nth (1- total-users) who-list)))))) (format-string (lyskom-info-line-format-string s-width "P" (if kom-deferred-printing "D" "s"))) (collect (make-collector))) (lyskom-format-insert format-string "" (lyskom-get-string 'lyskom-name) (lyskom-get-string 'lyskom-client)) (lyskom-insert (concat (make-string (- (lyskom-window-width) 2) ?-) "\n")) (while who-list (let* ((who-info (car who-list)) (session-no (int-to-string (dynamic-session-info->session who-info))) (my-session (if (= lyskom-session-no (dynamic-session-info->session who-info)) "*" " ")) (client (if kom-deferred-printing (lyskom-create-defer-info 'get-client-name (dynamic-session-info->session who-info) 'lyskom-deferred-client-1 nil nil nil ; Filled in later (list (dynamic-session-info->session who-info) collect)) (blocking-do-multiple ((name (get-client-name (dynamic-session-info->session who-info))) (version (get-client-version (dynamic-session-info->session who-info)))) (lyskom-list-clients-collect name version collect) (concat name " " version))))) (lyskom-format-insert format-string (concat session-no my-session) (dynamic-session-info->person who-info) client)) (setq who-list (cdr who-list))) (lyskom-insert (concat (make-string (- (lyskom-window-width) 2) ?-) "\n")) (lyskom-insert (lyskom-format (if want-invisible 'total-users 'total-visible-users) total-users (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss))) (lyskom-format-insert "%#1D\n" (lyskom-create-defer-info 'get-time nil 'lyskom-list-clients-statistics-1 nil nil nil collect)) )) (defun lyskom-list-clients-collect (client version collect) "Collect client statistics" (let* ((uversion (cond ((null version) version) ((null client) version) ((string-match "(.*; CVS)" version) (replace-in-string version "(.*; CVS)" "(from CVS)")) ((string-match "\\s-*(build [^)]*)" version) (replace-in-string version "\\s-*(build [^)]*)" "")) (t version))) (name (concat (or client "") (if uversion " " "") (or uversion ""))) (el (assoc name (collector->value collect)))) (if el (progn (aset (cdr el) 0 (1+ (aref (cdr el) 0))) (unless (lyskom-string-member (or version "") (aref (cdr el) 1)) (aset (cdr el) 1 (cons version (aref (cdr el) 1))))) (set-collector->value collect (cons (cons name (vector 1 (list version))) (collector->value collect)))))) (defun lyskom-list-clients-statistics-1 (time arg defer-info) (initiate-get-time 'deferred 'lyskom-list-clients-statistics-2 defer-info)) (defun lyskom-list-clients-statistics-2 (time defer-info) (lyskom-replace-deferred defer-info (concat "\n" (lyskom-get-string 'client-statistics) (mapconcat (lambda (el) (lyskom-format 'client-statistics-line (if (equal (car el) " ") (lyskom-get-string 'Unknown) (car el)) (aref (cdr el) 0) (length (aref (cdr el) 1)))) (nreverse (sort (collector->value (defer-info->data defer-info)) (lambda (a b) (string-lessp (car a) (car b))))) "\n") "\n"))) (defun lyskom-deferred-client-1 (name defer-info) (let* ((data (defer-info->data defer-info)) (session (if (consp data) (elt data 0) data)) (collector (if (consp data) (elt data 1) nil))) (initiate-get-client-version 'deferred 'lyskom-deferred-client-2 session defer-info name collector ))) (defun lyskom-deferred-client-2 (version defer-info name collect) (when collect (lyskom-list-clients-collect name version collect)) (lyskom-replace-deferred defer-info (if (zerop (length name)) "-" (concat name " " version)))) (defun lyskom-info-line-format-string (prefixlen type1 type2) "Return a format string suitable for inserting who-info lines etc." (let* ((plen (or prefixlen 7)) (width (- (lyskom-window-width) plen 2))) (concat "%" (int-to-string plen) "#1s" "%=-" (int-to-string (/ width 2)) "#2" type1 " %=-" (int-to-string (+ (/ width 2) (% width 2))) "#3" type2 "\n"))) (defun lyskom-window-width () "Returns the width of the lyskom-window or the screen-width if not displayed." (let ((win (get-buffer-window (current-buffer)))) (cond (win (window-width win)) (t (lyskom-frame-width))))) (defun lyskom-return-username (who-info) "Takes the username from the WHO-INFO and returns it on a better format." (let* ((username (cond ((lyskom-static-session-info-p who-info) (static-session-info->username who-info)) ((lyskom-session-info-p who-info) (session-info->username who-info)) (t (who-info->username who-info)))) (type (or (string-match "\\([^%@.]+\\)%\\(.+\\)@\\([^%@.]+\\)" username) (string-match "\\([^%@.]+\\)@\\([^%@.]+\\)" username)))) (if type (let ((name (substring username 0 (match-end 1))) (sent (if (match-beginning 3) (substring username (match-beginning 2) (match-end 2)))) (gott (if (match-beginning 3) (substring username (match-beginning 3) (match-end 3)) (substring username (match-beginning 2) (match-end 2)))) (rest (substring username (match-end 0)))) (if (or (not sent) (lyskom-string= (downcase sent) (downcase gott)) (lyskom-string= (downcase sent) (downcase (concat gott rest)))) (concat name "@" gott rest) (concat name "@" sent " (" gott rest ")"))) username))) (defun lyskom-combine-username (username identname hostname) "Return a description of from where a user is logged in." ;; Ignore ident info for now (if (string-match "\\(.*\\)%\\(.*\\)" username) (let ((user (substring username (match-beginning 1) (match-end 1))) (uhost (substring username (match-beginning 2) (match-end 2)))) (if (lyskom-string= uhost hostname) (concat user "@" hostname) (concat username "@" hostname))) (concat username "@" hostname))) ;;; ================================================================ ;;; Status (för) Session - Status (for a) session ;;; ;;; Author: David Byers (def-kom-command kom-status-session (&optional text-or-session-no) "Show status for all sessions a person has. Lisp documentation: Optional argument should be a list of sessions to get information about or a single session number. When used interactively, the prefix argument is used to find a text whose author's status is shown." (interactive (and current-prefix-arg ; only peek at textno:s when prefixed! (list (lyskom-read-text-no-prefix-arg 'text-to-see-author-status-of)))) (let ((sessions (or (when (and text-or-session-no (interactive-p)) (lyskom-session-from-conf (text-stat->author (blocking-do 'get-text-stat text-or-session-no)))) (cond ((listp text-or-session-no) text-or-session-no) ((numberp text-or-session-no) (list text-or-session-no))) (lyskom-read-session-no 'status-for-session))) who-info) (cond ((null sessions) (lyskom-insert-string 'no-such-session-r)) ((and (numberp (car sessions)) (<= (car sessions) 0)) (let ((pers-no (- (car sessions)))) (lyskom-format-insert (lyskom-get-string 'person-not-logged-in-r) pers-no (lyskom-format-time 'date-and-time (pers-stat->last-login (blocking-do 'get-pers-stat pers-no)))))) (t (if (lyskom-have-feature dynamic-session-info) (progn (setq who-info (listify-vector (blocking-do 'who-is-on-dynamic t t 0))) (mapcar (function (lambda (x) (lyskom-status-session-9 x who-info))) sessions)) (setq who-info (listify-vector (blocking-do 'who-is-on))) (mapcar (function (lambda (x) (lyskom-status-session-8 x who-info))) sessions)))))) (defun lyskom-status-session-8 (sid who-info-list) "Show session status for session SID. WHO-INFO is a list of WHO-INFOS that are potential sessions." (while who-info-list (if (eq sid (who-info->connection (car who-info-list))) (let* ((info (car who-info-list)) (client (if kom-deferred-printing (lyskom-create-defer-info 'get-client-name (who-info->connection info) 'lyskom-deferred-client-1 nil nil nil (who-info->connection info)) (blocking-do-multiple ((name (get-client-name (who-info->connection info))) (version (get-client-version (who-info->connection info)))) (concat name " " version))))) (lyskom-format-insert (lyskom-get-string 'session-status) (who-info->connection info) (who-info->pers-no info) (lyskom-return-username info) (if (not (eq (who-info->working-conf info) 0)) (who-info->working-conf info) (lyskom-get-string 'not-present-anywhere)) (let ((string (if (string-match "^\\(.*[^.]\\)\\.*$" (who-info->doing-what info)) (match-string 1 (who-info->doing-what info)) (who-info->doing-what info)))) (setq string (or (string-replace-match "\n" string " " t t) string)) (if (string= string "") (lyskom-get-string 'unknown-doing-what) string)) client (if (not (eq (who-info->working-conf info) 0)) (lyskom-get-string 'doing-where-conn) (lyskom-get-string 'doing-nowhere-conn))))) (setq who-info-list (cdr who-info-list)))) (defun lyskom-status-session-9 (sid who-info-list) "Show session status for session SID. WHO-INFO is a list of WHO-INFOS that are potential sessions." (let ((static (blocking-do 'get-static-session-info sid))) (while who-info-list (if (eq sid (dynamic-session-info->session (car who-info-list))) (let* ((info (car who-info-list)) (client (if kom-deferred-printing (lyskom-create-defer-info 'get-client-name (dynamic-session-info->session info) 'lyskom-deferred-client-1 nil nil nil (dynamic-session-info->session info)) (blocking-do-multiple ((name (get-client-name (dynamic-session-info->session info))) (version (get-client-version (dynamic-session-info->session info)))) (concat name " " version))))) (lyskom-format-insert (lyskom-get-string 'session-status-9) (dynamic-session-info->session info) (dynamic-session-info->person info) (lyskom-combine-username (static-session-info->username static) (static-session-info->ident-user static) (static-session-info->hostname static)) (if (not (eq (dynamic-session-info->working-conference info) 0)) (dynamic-session-info->working-conference info) (lyskom-get-string 'not-present-anywhere)) (let ((string (if (string-match "^\\(.*[^.]\\)\\.*$" (dynamic-session-info->what-am-i-doing info)) (match-string 1 (dynamic-session-info->what-am-i-doing info)) (dynamic-session-info->what-am-i-doing info)))) (setq string (or (string-replace-match "\n" string " " t t ) string)) (if (string= string "") (lyskom-get-string 'unknown-doing-what) string)) client (if (not (eq (dynamic-session-info->working-conference info) 0)) (lyskom-get-string 'doing-where-conn) (lyskom-get-string 'doing-nowhere-conn)) (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss (static-session-info->connection-time static)) (cond ((eq (/ (dynamic-session-info->idle-time info) 60) 0) (lyskom-get-string 'session-is-active)) ((not (session-flags->user_active_used (dynamic-session-info->flags info))) "\n") (t (lyskom-format (lyskom-get-string 'session-status-inactive) (lyskom-format-secs (dynamic-session-info->idle-time info)))))) (if (session-flags->invisible (dynamic-session-info->flags info)) (lyskom-insert (lyskom-get-string 'session-is-invisible))))) (setq who-info-list (cdr who-info-list))))) (defun lyskom-format-secs-aux (string num x1 x2 one many) (cond ((<= num 0) string) ((= num 1) (if (string= "" string) (concat string (lyskom-get-string one)) (concat string (if (and (= x1 0) (= x2 0)) (format " %s " (lyskom-get-string 'and)) ", ") (lyskom-get-string one)))) (t (if (string= "" string) (concat string (format "%d %s" num (lyskom-get-string many))) (concat string (if (and (= x1 0) (= x2 0)) (format " %s " (lyskom-get-string 'and)) ", ") (format "%d %s" num (lyskom-get-string many))))))) (defun lyskom-format-secs (time) "Format the number of seconds in TIME as a human-readable string." (let (;; (secs (% time 60)) (mins (% (/ time 60) 60)) (hrs (% (/ time 3600) 24)) (days (/ time 86400)) (string "")) (setq string (lyskom-format-secs-aux string days hrs mins 'one-day 'days)) (setq string (lyskom-format-secs-aux string hrs mins 0 'one-hour 'hours)) (setq string (lyskom-format-secs-aux string mins 0 0 'one-minute 'minutes)))) ;;; ================================================================ ;;; Hoppa - Jump over comments ;;; Author: Linus Tolke Y ;; Hoppa |ver alla inl{gg som {r kommentarer till detta inl{gg (recursivt) (defun kom-jump (&optional text-no) "Skips all comments to the selected text. Descends recursively in the comment tree, marking all texts found as read. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'jump-from-text))) (cond ((and (null current-prefix-arg) (or (eq 'REVIEW-TREE (read-info->type (read-list->first lyskom-reading-list))) (eq 'REVIEW-FAQ-TREE (read-info->type (read-list->first lyskom-reading-list))))) (lyskom-start-of-command 'kom-jump) (lyskom-format-insert 'jumping-from-text-review) (unwind-protect (progn (set-read-list-del-first lyskom-reading-list) (set-read-list-del-first lyskom-to-do-list)) (lyskom-end-of-command))) (text-no (lyskom-start-of-command 'kom-jump) (lyskom-format-insert 'jumping-from-text text-no) (initiate-get-text-stat 'main 'lyskom-jump text-no t) (lyskom-run 'main 'lyskom-end-of-command)) (t (lyskom-start-of-command 'kom-jump) (lyskom-insert-string 'have-to-read) (lyskom-end-of-command)))) (defun lyskom-jump (text-stat mark-as-read &optional sync) "Jump past TEXT-STAT and all comments to it. Remove TEXT-STAT from all internal tables in the client. If MARK-AS-READ is non-nil, also mark TEXT-STAT and all comments (and footnotes) to it as read in the server." (cond (text-stat ;+++ annan errorhantering. ;; Should check that we are a member of at least one of ;; the recipients, and stop otherwise. (if mark-as-read (lyskom-mark-as-read text-stat)) (lyskom-is-read (text-stat->text-no text-stat)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (cond ((and (memq (misc-info->type misc) lyskom-comment-types-list) (> (if (eq (misc-info->type misc) 'COMM-IN) (misc-info->comm-in misc) (misc-info->footn-in misc)) (text-stat->text-no text-stat))) (let ((comment (if (eq (misc-info->type misc) 'COMM-IN) (misc-info->comm-in misc) (misc-info->footn-in misc)))) (if sync (lyskom-jump (blocking-do 'get-text-stat comment) mark-as-read sync) (initiate-get-text-stat 'main 'lyskom-jump comment mark-as-read))))))))) ;;; ================================================================ ;;; Addera mottagare - Add recipient ;;; Subtrahera mottagare - Subtract recipient ;;; Author: David Byers (def-kom-command kom-add-recipient (text-no) "Add a recipient to a text. If the recipient already exists, this will convert the current recipient type to a regular copy recipient, if possible. See `kom-confirm-add-recipients'. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-recipient))) (lyskom-add-helper text-no 'who-to-add-q 'adding-name-as-recipient 'RECPT)) (def-kom-command kom-add-copy (text-no) "Add a carbon copy recipient to a text. If the recipient already exists, this will convert the current recipient type to a carbon copy recipient, if possible. See `kom-confirm-add-recipients'. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-copy))) (lyskom-add-helper text-no 'who-to-add-copy-q 'adding-name-as-copy 'CC-RECPT)) (def-kom-command kom-add-bcc (text-no) "Add a recipient to a text. If the recipient already exists, this will convert the current recipient type to a BCC recipient, if possible. See `kom-confirm-add-recipients'. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-bcc))) (lyskom-add-helper text-no 'who-to-add-bcc-q 'adding-name-as-copy 'BCC-RECPT)) (defun lyskom-add-helper (text-no who-prompt doing-prompt type) (let* ((text-stat (blocking-do 'get-text-stat text-no)) (attachments (lyskom-attachments-for-sub text-no)) (footnotes (lyskom-footnotes-for-sub text-no)) (move-footnotes nil) (move-attachments nil) (target (lyskom-read-conf-stat who-prompt '(all) nil nil t))) (when (and target text-no) (when (and (eq type 'RECPT) kom-confirm-add-recipients (not (lyskom-j-or-n-p (lyskom-format 'really-add-as-recpt-q target)))) (setq type 'CC-RECPT doing-prompt 'adding-name-as-copy)) (setq move-footnotes (and footnotes (lyskom-j-or-n-p 'add-footnotes-too-q))) (setq move-attachments (and attachments (lyskom-j-or-n-p 'add-attachments-too-q))) (lyskom-traverse text (append (list (cons text-no text-stat)) (and move-footnotes footnotes) (and move-attachments attachments)) (lyskom-format-insert doing-prompt target (car text)) (lyskom-move-recipient (car text) nil target type))))) (defun lyskom-footnotes-for-sub (text-no) "Return the list of footnotes to remove recipient from." (let ((result nil) (worklist (list text-no))) (while worklist (setq text-no (car worklist)) (setq worklist (cdr worklist)) (unless (assq text-no result) (let ((text-stat (blocking-do 'get-text-stat text-no))) (setq result (cons (cons text-no text-stat) result) worklist (nconc (mapcar 'misc-info->footn-in (lyskom-misc-infos-from-list 'FOOTN-IN (text-stat->misc-info-list text-stat))) worklist))))) (cdr (nreverse result)))) (defun lyskom-attachments-for-sub (text-no) "Return the list of attachments to remove recipient from." (let ((result nil) (worklist (list text-no))) (while worklist (setq text-no (car worklist)) (setq worklist (cdr worklist)) (unless (assq text-no result) (let ((text-stat (blocking-do 'get-text-stat text-no))) (setq result (cons (cons text-no text-stat) result) worklist (nconc (lyskom-get-text-attachments text-stat) worklist))))) (cdr (nreverse result)))) (def-kom-command kom-sub-recipient (text-no) "Remove a recipient from the selected text. Take care not to remove the last recipient, since this will make the text unreadable. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-delete-recipient))) (let* ((text-stat (blocking-do 'get-text-stat text-no)) (attachments (lyskom-attachments-for-sub text-no)) (footnotes (lyskom-footnotes-for-sub text-no)) (move-footnotes nil) (move-attachments nil)) (if text-stat (let ((recipients (sort (lyskom-text-recipients text-stat t) (lambda (a b) (> (length (memq (cdr a) lyskom-recpt-types-list)) (length (memq (cdr b) lyskom-recpt-types-list))))))) (if recipients (let* ((source (lyskom-read-conf-stat 'who-to-sub-q (list (cons 'restrict (mapcar 'car recipients))) nil nil t))) (when source (setq move-footnotes (and footnotes (lyskom-j-or-n-p 'sub-footnotes-too-q))) (setq move-attachments (and attachments (lyskom-j-or-n-p 'sub-attachments-too-q))) (lyskom-traverse text (append (list (cons text-no text-stat)) (and move-footnotes footnotes) (and move-attachments attachments)) (lyskom-format-insert 'remove-name-as-recipient source (cdr text)) (if (memq (conf-stat->conf-no source) (lyskom-text-recipients (cdr text))) (lyskom-move-recipient (car text) source nil nil) (lyskom-insert 'move-text-not-recipient))))) (lyskom-format-insert 'text-has-no-recipients-r text-no))) (lyskom-format-insert 'no-such-text-no text-no)))) (def-kom-command kom-move-text (text-no) "Move the selected text from one conference to another. If you want to move an entire comment tree, use `kom-move-text-tree' instead. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg'). Lisp documentation: CONTINUATION is the function that does the actual moving. It is called with three arguments: source, target and text-stat, where source is the recipient to remove and target the recipient to add to text-stat." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-move))) (let* ((text-stat (blocking-do 'get-text-stat text-no)) (attachments (lyskom-attachments-for-sub text-no)) (footnotes (lyskom-footnotes-for-sub text-no)) (move-footnotes nil) (move-attachments nil)) (if (null text-stat) (lyskom-format-insert 'no-such-text-no text-no) (let* ((recipients (sort (lyskom-text-recipients text-stat t) (lambda (a b) (> (length (memq (cdr a) lyskom-recpt-types-list)) (length (memq (cdr b) lyskom-recpt-types-list))))))) (if (null recipients) (lyskom-format-insert 'text-has-no-recipients-r text-no) (let ((source (lyskom-read-conf-stat 'who-to-move-from-q (list (cons 'restrict (mapcar 'car recipients))) nil nil t)) (target (lyskom-read-conf-stat 'who-to-move-to-q '(all) nil nil t))) (when (and source target) (if (eq (conf-stat->conf-no source) (conf-stat->conf-no target)) (lyskom-insert-before-prompt 'cant-move-from-to-same) (setq move-footnotes (and footnotes (lyskom-j-or-n-p 'move-footnotes-too-q))) (setq move-attachments (and attachments (lyskom-j-or-n-p 'move-attachments-too-q))) (lyskom-traverse text (append (list (cons text-no text-stat)) (and move-footnotes footnotes) (and move-attachments attachments)) (if (null (cdr text)) (lyskom-format-insert 'moving-cant-read (car text)) (lyskom-format-insert 'moving-name source target (cdr text)) (if (memq (conf-stat->conf-no source) (lyskom-text-recipients (cdr text))) (lyskom-move-recipient (car text) source target 'RECPT) (lyskom-insert 'move-text-not-recipient)) )))))))))) (def-kom-command kom-move-text-tree (text-no) "Move the selected text and all comments below it from one conference to another. This command can also be used to remove or add a recipient. Confirmation is required for each single move. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-tree-to-move))) (let ((root-text-stat (blocking-do 'get-text-stat text-no)) (last-move-tree-add-type 'move-tree-rcpt) (last-move-leave-cc 'abc-no) (last-move-tree-action nil)) (if root-text-stat ;; Set up default recipients for from and to. (let* ((recipients (sort (lyskom-text-recipients root-text-stat t) (lambda (a b) (> (length (memq (cdr a) lyskom-recpt-types-list)) (length (memq (cdr b) lyskom-recpt-types-list))))))) ;; Check that the text has recipients at all. (if (null recipients) (lyskom-format-insert 'text-has-no-recipients-r text-no) ;; Read the conference we are moving the tree away from. (let ((source (lyskom-read-conf-stat 'who-to-move-from-q (list (cons 'restrict (mapcar 'car recipients))) t nil t)) (to-do (list (text-stat->text-no root-text-stat))) (done nil)) ;; Now loop over the tree (while to-do (let* ((text-to-move (car to-do)) (text-stat (blocking-do 'get-text-stat text-to-move)) (text-to-move-recipients (lyskom-text-recipients text-stat))) (setq to-do (cdr to-do)) ;; Check that this text is a candidate for moving ;; If not, put it in done to fool the next control ;; structure. ;; ;; A text is candidate for moving if one of its ;; recipients is the source, or there is no ;; source (in which case we're just adding) (unless text-stat (setq done (cons text-to-move done))) (unless (or (null source) (memq (conf-stat->conf-no source) text-to-move-recipients)) (lyskom-format-insert 'moving-already-moved text-to-move source) (setq done (cons text-to-move done))) ;; Use memoing to ensure that we don't loop. (unless (memq text-to-move done) (setq done (cons text-to-move done)) ;; Check that the text has the source as a ;; recipient. If not, skip to the next in the ;; tree (and don't traverse downwards). ;; Show the text that we are planning on moving ;; Truncate it. This may be a bad idea, but it ;; kind of makes sense since we don't have the ;; opportunity to scroll the buffer. (let ((kom-truncate-show-lines (if (numberp kom-truncate-show-lines) (min kom-truncate-show-lines 10) 10)) (kom-truncate-threshold (if (numberp kom-truncate-threshold) (min kom-truncate-threshold 10) 10))) (lyskom-view-text text-to-move nil nil nil nil nil nil t) (setq lyskom-last-viewed (point-max))) ;; Ask the user what to do. Options: ;; source ;; -------------------------------------- ;; null add, quit, ign, jump ;; non-null sub, move, quit, ign, jump ;; -------------------------------------- (let* ((completion-ignore-case t) (action (lyskom-a-or-b-or-c-p (lyskom-get-string 'moving-tree-what-action-q) (if source '(move-tree-move move-tree-sub move-tree-ign move-tree-jump move-tree-quit) '(move-tree-add move-tree-ign move-tree-jump move-tree-quit)) (if source (if (memq last-move-tree-action '(move-tree-move move-tree-sub)) last-move-tree-action 'move-tree-move) 'move-tree-add)))) (setq last-move-tree-action action) (cond ;; Add recipient. ((eq action 'move-tree-add) (condition-case nil (let ((target (lyskom-read-conf-stat 'who-to-add-q '(all) nil nil t))) (setq last-move-tree-add-type (lyskom-a-or-b-or-c-p 'move-tree-add-rcpt-type '(move-tree-rcpt move-tree-cc move-tree-bcc) last-move-tree-add-type)) (when target (lyskom-format-insert (or (cdr (assq last-move-tree-add-type '((move-tree-rcpt . adding-name-as-recipient) (move-tree-cc . adding-name-as-copy) (move-tree-bcc . adding-name-as-bcc)))) 'adding-name-as-recipient) target (text-stat->text-no text-stat)) (lyskom-move-recipient text-to-move source target (or (cdr (assq last-move-tree-add-type '((move-tree-rcpt . RECPT) (move-tree-cc . CC-RECPT) (move-tree-bcc . BCC-RECPT)))) 'RECPT))) (setq to-do (nconc (lyskom-text-comments text-stat) to-do)) ) (quit (setq to-do (cons text-to-move to-do)))) ) ;; Move the text. ((or (eq action 'move-tree-move) (eq action 'move-tree-sub)) (condition-case nil (let ((target (when (eq action 'move-tree-move) (lyskom-read-conf-stat (if (> (length text-to-move-recipients) 1) 'who-to-move-to-or-sub-q 'who-to-move-to-q) '(all) (> (length text-to-move-recipients) 1) nil t)))) (if target (lyskom-format-insert 'moving-name source target text-stat) (lyskom-format-insert 'remove-name-as-recipient source (text-stat->text-no text-stat))) (lyskom-move-recipient text-to-move source target 'RECPT (cond ((eq last-move-leave-cc 'abc-yes-all) t) ((eq last-move-leave-cc 'abc-no-all) nil) (t (setq last-move-leave-cc (lyskom-a-or-b-or-c-p 'move-tree-leave-cc-q '(abc-yes abc-no abc-yes-all abc-no-all) last-move-leave-cc)) (cdr (assq last-move-leave-cc '((abc-yes . t) (abc-no . nil) (abc-yes-all . t) (abc-no-all . nil)))))) ) (setq to-do (nconc (lyskom-text-comments text-stat) to-do)) ) (quit (setq to-do (cons text-to-move to-do)))) ) ((eq action 'move-tree-ign) (setq to-do (nconc (lyskom-text-comments text-stat) to-do)) ) ((eq action 'move-tree-quit) (setq to-do nil)) ((eq action 'move-tree-jump)))))))))) (lyskom-format-insert 'no-such-text-no text-no) ))) (defun lyskom-move-recipient (text-no source target type &optional leave-cc) "Remove TEXT-NO from SOURCE and add it to TARGET as TYPE. This is the internal function for moving texts around. SOURCE or TARGET may be nil. TYPE is ignored if TARGET is nil. If optional LEAVE-CC is non-nil, then leave the original conference as a CC recipient. Calls lyskom-report-command-answer to report the result, to callers must have printed something without a newline at the end of the buffer." (let ((text-stat (blocking-do 'get-text-stat text-no))) (if text-stat (let* ((was-read (lyskom-text-read-p text-stat)) (add-result (if target (blocking-do 'add-recipient text-no (conf-stat->conf-no target) type) t)) (add-errno lyskom-errno) (sub-result (if (and source add-result) (if leave-cc (blocking-do 'add-recipient text-no (conf-stat->conf-no source) 'CC-RECPT) (blocking-do 'sub-recipient text-no (conf-stat->conf-no source)) ) t)) (sub-errno lyskom-errno)) (when (null add-result) ;; Can't add to target. Explain why. We have not removed from the ;; source conference, so no need to add it back (cond ((eq add-errno 27) ; already-recipient (lyskom-insert-string 'nope) (lyskom-format-insert 'error-already-recipient text-stat target) ) ((eq add-errno 33) ; recipient-limit (lyskom-insert-string 'nope) (lyskom-format-insert 'error-recipient-limit text-stat) ) ((eq add-errno 12) ; permission-denied (lyskom-insert-string 'nope) (lyskom-format-insert 'error-permission-denied-add-recpt text-stat target) ) ((eq add-errno 11) ; access-denied (lyskom-insert-string 'nope) (lyskom-format-insert 'error-access-denied-add-recpt text-stat target) ) (t (lyskom-report-command-answer nil add-errno))) ) (when (null sub-result) ;; Can't sub from souce. Explain why. (when target (blocking-do 'sub-recipient text-no (conf-stat->conf-no source))) (cond ((eq sub-errno 30) ;not-recipient (lyskom-insert-string 'nope) (lyskom-format-insert 'error-not-recipient text-stat source) ) ((eq sub-errno 12) ; permission-denied (lyskom-insert-string 'nope) (lyskom-format-insert 'error-permission-denied-sub-recpt text-stat source) ) (t (lyskom-report-command-answer nil sub-errno))) ) (when (and add-result sub-result) (lyskom-report-command-answer t)) ;; If the text was read prior to the move, it is afterwards too. (cache-del-text-stat text-no) (when (and add-result target was-read) (lyskom-mark-as-read (blocking-do 'get-text-stat text-no))) (and add-result sub-result)) (lyskom-format-insert 'no-such-text-no text-no) nil))) ;;; ================================================================ ;;; Addera kommentar - Add comment ;;; Subtrahera kommentar - Subtract comment ;;; Author: David Byers ;;; Heavily based on code by Lars Willf|r (def-kom-command kom-add-comment (text-no-arg) "Add one text as a comment to another text. This command is used to connect a text to another one after both have been created. If you want to write a new comment, use `kom-write-comment' instead. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-comment-to))) (lyskom-add-sub-comment text-no-arg t)) (def-kom-command kom-sub-comment (text-no-arg) "Remove a comment from a text. Be careful removing comments. If others have written comments to the comment being removed, the context of those comments may become hard to understand. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-delete-comment-from))) (if (lyskom-misc-infos-from-list 'COMM-IN (text-stat->misc-info-list (blocking-do 'get-text-stat text-no-arg))) (lyskom-add-sub-comment text-no-arg nil) (lyskom-format-insert 'text-has-no-comments text-no-arg))) (defun lyskom-add-sub-comment (text-no do-add) "Get the number of the text that is going to have a comment added to it or subtracted from it Arguments: TEXT-NO-ARG: an argument as it is gotten from (interactive P) DO-ADD: NIL if a comment should be subtracted. Otherwise a comment is added" (if text-no (let* ((completions (unless do-add (let ((text-stat (blocking-do 'get-text-stat text-no))) (when text-stat (mapcar 'misc-info->comm-in (lyskom-misc-infos-from-list 'COMM-IN (text-stat->misc-info-list text-stat))))))) (comment-text-no (lyskom-read-number (lyskom-format (if do-add 'text-to-add-q 'text-to-remove-q) text-no) (cond (do-add (if (eq text-no lyskom-current-text) nil lyskom-current-text)) ((eq (length completions) 1) (car completions)) ((memq lyskom-current-text completions) lyskom-current-text) (t nil)) nil nil completions ))) (lyskom-format-insert (if do-add 'add-comment-to 'sub-comment-to) comment-text-no text-no) (cache-del-text-stat text-no) (cache-del-text-stat comment-text-no) (lyskom-report-command-answer (blocking-do (if do-add 'add-comment 'sub-comment) comment-text-no text-no))) (lyskom-format-insert (if do-add 'confusion-what-to-add-comment-to 'confusion-what-to-sub-comment-from)))) (def-kom-command kom-add-footnote (text-no-arg) "Add a text as a footnote to another text. This command is used to add a text as a footnote to another text after both have been created. If you want to write a new footnote, use `kom-write-footnote' instead. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-footnote-to))) (lyskom-add-sub-footnote text-no-arg t)) (def-kom-command kom-sub-footnote (text-no-arg) "Remove a footnote from a text. Be careful removing comments. If others have written comments to the comment being removed, the context of those comments may become hard to understand. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-delete-footnote-from))) (if (lyskom-misc-infos-from-list 'FOOTN-IN (text-stat->misc-info-list (blocking-do 'get-text-stat text-no-arg))) (lyskom-add-sub-footnote text-no-arg nil) (lyskom-format-insert 'text-has-no-footnotes text-no-arg))) (defun lyskom-add-sub-footnote (text-no do-add) "Get the number of the text that is going to have a footnote added to it or subtracted from it Arguments: TEXT-NO-ARG: an argument as it is gotten from (interactive P) DO-ADD: NIL if a footnote should be subtracted. Otherwise a footnote is added" (if text-no (let* ((completions (unless do-add (let ((text-stat (blocking-do 'get-text-stat text-no))) (when text-stat (mapcar 'misc-info->footn-in (lyskom-misc-infos-from-list 'FOOTN-IN (text-stat->misc-info-list text-stat))))))) (footnote-text-no (lyskom-read-number (lyskom-format (if do-add 'text-to-add-footn-q 'text-to-remove-footn-q) text-no) (cond (do-add (if (eq text-no lyskom-current-text) nil lyskom-current-text)) ((eq (length completions) 1) (car completions)) ((memq lyskom-current-text completions) lyskom-current-text) (t nil)) nil nil completions ))) (lyskom-format-insert (if do-add 'add-footnote-to 'sub-footnote-to) footnote-text-no text-no) (cache-del-text-stat text-no) (cache-del-text-stat footnote-text-no) (lyskom-report-command-answer (blocking-do (if do-add 'add-footnote 'sub-footnote) footnote-text-no text-no))) (lyskom-insert (if do-add 'confusion-what-to-add-footnote-to 'confusion-what-to-sub-footnote-from)))) ;;; ================================================================ ;;; Addera referens - Add cross reference ;;; Author: Joel Rosdahl (def-kom-command kom-add-cross-reference (text-no-arg) "Add a cross reference to a text. The reference can be to another text, a conference or a person. This command accepts text number prefix arguments (see `lyskom-read-text-no-prefix-arg')." (interactive "P") (lyskom-add-cross-reference text-no-arg (lyskom-get-string 'text-to-add-cross-reference-to))) (defun lyskom-add-cross-reference (text-no-arg prompt) "Get the number of the text that is going to have a cross reference added to it, ask the user about cross reference type and value, and add the cross reference. Arguments: TEXT-NO-ARG: An argument as gotten from (interactive \"P\"). PROMPT: A string that is used when prompting for a text number." (let ((text-no (let ((current-prefix-arg text-no-arg)) (lyskom-read-text-no-prefix-arg prompt))) (aux-item (lyskom-read-cross-reference-and-get-aux-item))) (when (and text-no aux-item) (cache-del-text-stat text-no) (lyskom-insert 'adding-cross-reference) (lyskom-report-command-answer (blocking-do 'modify-text-info text-no nil (list aux-item)))))) (defun lyskom-read-cross-reference-and-get-aux-item () "Query user about cross reference type and value, and return the corresponding aux-item." (let* ((type (lyskom-a-or-b-or-c-p 'xref-type '(abc-conference abc-person abc-text) nil)) (obj nil) (char nil)) (cond ((eq type 'abc-text) (let ((prompt 'which-text-to-xref)) (while (null obj) (setq obj (text-stat->text-no (blocking-do 'get-text-stat (lyskom-read-number prompt)))) (setq prompt 'which-text-to-xref-err ))) (setq char "T")) ((eq type 'abc-conference) (while (null obj) (setq obj (lyskom-read-conf-no 'which-conf-to-xref '(conf) nil nil t))) (setq char "C")) ((eq type 'abc-person) (while (null obj) (setq obj (lyskom-read-conf-no 'which-pers-to-xref '(pers) nil nil t))) (setq char "P"))) (when obj (lyskom-create-aux-item 0 3 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (format "%s%d" char obj))))) ;;; ================================================================ ;;; Local Variables: ;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2) ;;; end: ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: commands2.el,v 44.215 2005/01/09 22:09:00 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: commands2.el ;;;; ;;;; This file contains the code for some high level commands. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: commands2.el,v 44.215 2005/01/09 22:09:00 byers Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) ;;; ================================================================ ;;; Lista medlemsskap - List membership (def-kom-command kom-membership () "Alias for `kom-prioritize'." (interactive) (lyskom-prioritize)) ;;; ================================================================ ;;; Status (f|r) M|te - Status for a conference ;;; Author: ceder (with some help by Linus) ;;; much enhanced by Inge Wallin (lyskom-status-conf-2 and beyond) (defun lyskom-conf-type-marker (conf-stat) "Return a pretty string describing the type of CONF-STAT." (let* ((type (conf-stat->conf-type conf-stat)) (box (conf-type->letterbox type)) (ori (conf-type->original type)) (pro (conf-type->rd_prot type)) (sec (conf-type->secret type))) (cond ((or box ori pro sec) (concat " (" (if box (lyskom-get-string 'Mailbox) "") (if (and box (or sec ori pro)) ", " "") (if sec (lyskom-get-string 'Protected) "") (if (and sec (or ori pro)) ", " "") (if ori (lyskom-get-string 'no-comments) "") (if (and ori pro) ", " "") (if pro (lyskom-get-string 'closed) "") ")")) (t "")))) (def-kom-command kom-status-conf (&optional conf-no) "Print information about a conference. The information listed may be taken from the client's cache and therefore slightly out of date. See `kom-extended-status-information'. Lisp documentation: If argument CONF-NO is existing and non-nil then this conference is used. otherwise: the conference is read with lyskom-completing-read." (interactive) (let ((conf-no (or conf-no (lyskom-read-conf-no 'conf-for-status '(all) nil nil t))) (kom-print-seconds-in-time-strings nil) (kom-extended-status-information (lyskom-extended-status-override 'conf))) (cache-del-conf-stat conf-no) (cache-del-uconf-stat conf-no) (blocking-do-multiple ((conf-stat (get-conf-stat conf-no)) (uconf-stat (get-uconf-stat conf-no))) (if (null conf-stat) (lyskom-insert-string 'no-such-conf) (lyskom-format-insert 'status-record conf-stat (lyskom-conf-type-marker conf-stat)) (let ((creator (conf-stat->creator conf-stat))) (lyskom-format-insert 'created-by creator creator (if (and (lyskom-conf-stat-p creator) (> (lyskom-string-width (conf-stat->name creator)) (- (lyskom-window-width) 46))) "\n" ""))) (lyskom-format-insert 'created-at (lyskom-format-time 'date-and-time (conf-stat->creation-time conf-stat))) (lyskom-format-insert 'members (conf-stat->no-of-members conf-stat)) (lyskom-format-insert 'conf-allows-secret-members (lyskom-get-string (if (conf-type->forbid-secret (uconf-stat->conf-type uconf-stat)) 'secret-members-not-permitted 'secret-members-permitted))) (lyskom-format-insert 'conf-allows-anon-texts (lyskom-get-string (if (conf-type->anarchy (uconf-stat->conf-type uconf-stat)) 'anon-texts-permitted 'anon-texts-not-permitted))) (lyskom-format-insert 'garb-nice (conf-stat->garb-nice conf-stat)) (lyskom-format-insert 'keep-commented (conf-stat->keep-commented conf-stat)) (lyskom-format-insert 'lowest-local-no (conf-stat->first-local-no conf-stat)) (lyskom-format-insert 'highest-local-no (1- (+ (conf-stat->no-of-texts conf-stat) (conf-stat->first-local-no conf-stat)))) (lyskom-format-insert 'last-text-time (lyskom-format-time 'date-and-time (conf-stat->last-written conf-stat))) (lyskom-format-insert 'no-of-motd (conf-stat->msg-of-day conf-stat)) (let ((superconf (conf-stat->super-conf conf-stat))) (lyskom-format-insert 'superconf-is-no-name superconf superconf (if (and (lyskom-conf-stat-p superconf) (> (lyskom-string-width (conf-stat->name superconf)) (- (lyskom-window-width) 46))) "\n" ""))) (let ((permitted-submitters (conf-stat->permitted-submitters conf-stat))) (lyskom-format-insert 'permitted-submitters-no-name permitted-submitters (if (zerop permitted-submitters) (lyskom-get-string 'Everybody) permitted-submitters) "")) (let ((supervisor (conf-stat->supervisor conf-stat))) (lyskom-format-insert 'supervisor-is-no-name supervisor supervisor "")) (lyskom-format-insert 'presentation-no (conf-stat->presentation conf-stat)) (if (zerop (conf-stat->msg-of-day conf-stat)) nil (lyskom-format-insert 'conf-has-motd conf-stat) (lyskom-view-text (conf-stat->msg-of-day conf-stat))) ;; Show aux items (lyskom-traverse-aux item (conf-stat->aux-items conf-stat) (if (lyskom-aux-item-definition-field item 'status-print) (lyskom-aux-item-call item 'status-print item conf-stat) (lyskom-format-insert 'status-aux-item (format "%d/%d" (aux-item->aux-no item) (aux-item->tag item)) (aux-item->creator item) (lyskom-aux-item-terminating-button item conf-stat)) )) (let ((mship (lyskom-try-get-membership (conf-stat->conf-no conf-stat) t))) (when mship (lyskom-format-insert 'conf-mship-priority (membership->priority mship) (lyskom-return-membership-type (membership->type mship))))) ;; Show all members of CONF-STAT if the user so wishes." (lyskom-scroll) (if (lyskom-j-or-n-p (lyskom-get-string 'show-members-list-also-q)) (let ((member-list (blocking-do 'get-members (conf-stat->conf-no conf-stat) 0 lyskom-max-int))) (if (null member-list) (lyskom-format-insert 'conf-has-no-members conf-stat) (lyskom-format-insert 'conf-has-these-members conf-stat) (if (lyskom-j-or-n-p (lyskom-get-string 'show-membership-info-q)) (progn (lyskom-insert-string 'member-list-header) (lyskom-traverse member (member-list->members member-list) (let ((membership (blocking-do 'query-read-texts (member->pers-no member) (conf-stat->conf-no conf-stat) t 0))) ;; Print a row describing the membership of MEMBER ;; (described by MEMBERSHIP) in CONF-STAT. (if (or (null membership)) (lyskom-insert-string 'secret-membership) (lyskom-format-insert "%#1@%-17#2s" (if (membership-type->passive (member->membership-type member)) `(face ,kom-dim-face) nil) (lyskom-format-time 'date-and-time (membership->last-time-read membership))) (let ((unread (- (+ (conf-stat->first-local-no conf-stat) (conf-stat->no-of-texts conf-stat)) (membership->last-text-read membership) (length (membership->read-texts membership)) 1))) (lyskom-format-insert 'conf-membership-line (if (zerop unread) " " (format "%9d " unread)) (member->pers-no member) (lyskom-return-membership-type (member->membership-type member)) (if (membership-type->passive (member->membership-type member)) `(face ,kom-dim-face) nil) ) (when (and (member->created-by member) (not (zerop (member->created-by member))) (not (eq (member->pers-no member) (member->created-by member)))) (lyskom-format-insert 'conf-membership-line-2 (lyskom-format-time 'date-and-time (member->created-at member)) (member->created-by member))) ))))) ;; Don't show membership info (lyskom-insert "\n") (lyskom-traverse member (member-list->members member-list) (lyskom-format-insert " %#1P\n" (member->pers-no member))))))))))) ;;; ================================================================ ;;; Status (f|r) Person - status for a person ;;; Author: ceder ;;; Heavily enhanced: Inge Wallin (lyskom-status-pers-3 and beyond) (def-kom-command kom-status-person (&optional text-or-pers-no) "Show information about a person. If a prefix argument is given, the status of the author of that text will be shown. See `kom-extended-status-information'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (and current-prefix-arg ; only peek at textno:s when prefixed! (list (lyskom-read-text-no-prefix-arg 'text-to-see-author-status-of)))) (let ((pers-no (or (when (interactive-p) (text-stat->author (blocking-do 'get-text-stat text-or-pers-no))) text-or-pers-no (lyskom-read-conf-no 'pers-for-status '(pers) nil nil t))) (kom-print-seconds-in-time-strings nil) (kom-extended-status-information (lyskom-extended-status-override 'pers)) conf-stat pers-stat) (cache-del-conf-stat pers-no) (cache-del-pers-stat pers-no) (setq pers-stat (blocking-do 'get-pers-stat pers-no)) (setq conf-stat (blocking-do 'get-conf-stat pers-no)) ;; "Print status about PERS-STAT. The name is in CONF-STAT" (if (or (null pers-stat) (null conf-stat)) (lyskom-insert-string 'no-such-pers) (lyskom-format-insert 'pers-status-record conf-stat) (lyskom-format-insert 'created-time (lyskom-format-time 'date-and-time (conf-stat->creation-time conf-stat))) (lyskom-format-insert 'created-confs (pers-stat->created-confs pers-stat)) (lyskom-format-insert 'created-persons (pers-stat->created-persons pers-stat)) (lyskom-format-insert 'created-texts (1- (+ (pers-stat->no-of-created-texts pers-stat) (pers-stat->first-created-text pers-stat)))) (lyskom-format-insert 'created-lines (pers-stat->created-lines pers-stat)) (lyskom-format-insert 'created-chars (pers-stat->created-bytes pers-stat)) (lyskom-format-insert 'no-of-sessions (pers-stat->sessions pers-stat)) (let ((time (pers-stat->total-time-present pers-stat))) (unless (zerop time) ;; Why not let it print "0 d 00:00:00"? (lyskom-format-insert 'present-time-d-h-m-s (floor time (* 24 3600)) (mod (floor time 3600) 24) (mod (floor time 60) 60) (round (mod time 60))))) (lyskom-format-insert 'last-log-in (lyskom-format-time 'date-and-time (pers-stat->last-login pers-stat))) (lyskom-format-insert 'user-name (pers-stat->username pers-stat)) (lyskom-format-insert 'read-texts (pers-stat->read-texts pers-stat)) (if (= (pers-stat->pers-no pers-stat) lyskom-pers-no) (lyskom-format-insert 'marked-texts (pers-stat->no-of-marks pers-stat))) (lyskom-format-insert 'time-for-last-letter (lyskom-format-time 'date-and-time (conf-stat->last-written conf-stat))) (let* ((a (lyskom-format 'pers-has-privileges "")) (b (concat "\n" (make-string (lyskom-string-width a) ?\ )))) (lyskom-format-insert 'pers-has-privileges (lyskom-privilege-string (pers-stat->privileges pers-stat) 'pers-has-privileges-2 b))) (let ((superconf (conf-stat->super-conf conf-stat))) (lyskom-format-insert 'superconf superconf superconf "")) (if (not (zerop (conf-stat->supervisor conf-stat))) (let ((supervisor (conf-stat->supervisor conf-stat))) (lyskom-format-insert 'supervisor supervisor supervisor ""))) (lyskom-format-insert 'member-of-confs (pers-stat->no-of-confs pers-stat)) (lyskom-format-insert 'presentation (conf-stat->presentation conf-stat)) ;; Show aux items (lyskom-traverse-aux item (conf-stat->aux-items conf-stat) (lyskom-aux-item-call item 'status-print item conf-stat)) ;; Show motd (if (not (zerop (conf-stat->msg-of-day conf-stat))) (progn (lyskom-format-insert 'has-motd conf-stat) (lyskom-view-text (conf-stat->msg-of-day conf-stat)))) ;; "Show all conferences CONF-STAT is a member of if the user so wishes." (lyskom-scroll) (if (null (lyskom-j-or-n-p (lyskom-get-string 'show-membership-list-also-q))) nil (let ((membership-list (blocking-do 'get-membership (conf-stat->conf-no conf-stat))) (deferred-mships nil) (lyskom-count-var 0) (lyskom-passive-count-var 0)) (if (null membership-list) (lyskom-format-insert 'not-allowed-see-confs conf-stat) (lyskom-format-insert 'is-member-of conf-stat) (lyskom-insert-string 'membership-list-header) (setq lyskom-count-var 0) (setq lyskom-passive-count-var 0) (lyskom-traverse membership membership-list (let ((cs (cache-get-conf-stat (membership->conf-no membership)))) (and cs (lyskom-time-greater (membership->last-time-read membership) (conf-stat->last-written conf-stat)) (cache-del-conf-stat (membership->conf-no membership)))) ;; "Print a row describing the membership of ;; MEMBER-CONF-STAT (if (membership-type->passive (membership->type membership)) (setq deferred-mships (cons membership deferred-mships)) (setq lyskom-count-var (+ lyskom-count-var (lyskom-status-pers-list-one-membership conf-stat membership))))) (lyskom-traverse membership (nreverse deferred-mships) (setq lyskom-passive-count-var (+ lyskom-passive-count-var (lyskom-status-pers-list-one-membership conf-stat membership))))) ;; "Print the total number of unread texts for the person CONF-STAT." (lyskom-format-insert 'his-total-unread conf-stat lyskom-count-var lyskom-passive-count-var)))))) (defun lyskom-status-pers-list-one-membership (conf-stat membership) (let ((member-conf-stat (blocking-do 'get-conf-stat (membership->conf-no membership)))) (if (or (null member-conf-stat) (null membership)) (lyskom-insert-string 'secret-membership) (lyskom-format-insert "%#1@%-17#2s" (if (membership-type->passive (membership->type membership)) `(face ,kom-dim-face) nil) (lyskom-format-time 'date-and-time (membership->last-time-read membership))) (let ((unread (- (+ (conf-stat->first-local-no member-conf-stat) (conf-stat->no-of-texts member-conf-stat)) (membership->last-text-read membership) (length (membership->read-texts membership)) 1))) (lyskom-format-insert 'pers-membership-line (if (zerop unread) " " (format "%9d " unread)) (if (= (conf-stat->conf-no conf-stat) (conf-stat->supervisor member-conf-stat)) (lyskom-get-string 'is-supervisor-mark) " ") member-conf-stat (lyskom-return-membership-type (membership->type membership)) (if (membership-type->passive (membership->type membership)) `(face ,kom-dim-face) nil) ) (when (and (membership->created-by membership) (not (zerop (membership->created-by membership))) (not (eq (conf-stat->conf-no conf-stat) (membership->created-by membership)))) (lyskom-format-insert 'pers-membership-line-2 (lyskom-format-time 'date-and-time (membership->created-at membership)) (membership->created-by membership))) unread)))) ;;; ================================================================ ;;; Skicka meddelande - Send message ;;; Author: Inge Wallin ;;; Rewritten to use lyskom-read-conf-no by Linus Tolke ;;; Modified to use default recipient by David Byers (defun lyskom-default-conference-for-send-message (&rest args) (let ((tmp (cond ((eq kom-default-message-recipient 'everybody) nil) ((and (eq kom-default-message-recipient 'group) lyskom-last-group-message-recipient) lyskom-last-group-message-recipient) ((or (and (eq kom-default-message-recipient 'group) (null lyskom-last-group-message-recipient)) (and (eq kom-default-message-recipient 'sender) lyskom-last-personal-message-sender)) lyskom-last-personal-message-sender) ((and (eq kom-default-message-recipient 'last-recipient) lyskom-last-message-recipient (not (eq 0 lyskom-last-message-recipient)) lyskom-last-message-recipient)) (t (if lyskom-last-personal-message-sender lyskom-last-personal-message-sender nil))))) (and tmp (list tmp)))) (def-kom-command kom-send-message (&optional who message) "Send a message to another user or all members of a conference. Messages sent with this command are not texts and are not stored in the database. If you don't know if you should use this or write a text, write a text \(see `kom-write-text' instead). Remember that messages of this type are intrusive, yet may not be read by all users. Runs `kom-send-message-setup-hook' when entering the minibuffer. See `kom-default-message-recipient'." (interactive) (lyskom-interactive-send-message who message nil)) (def-kom-command kom-send-alarm (&optional message) "Send a message to all of the users in LysKOM. Don't use this command unless what you have to say is really important to everyone who is logged on. Runs `kom-send-message-setup-hook' when entering the minibuffer." (interactive) (lyskom-interactive-send-message nil message t)) (defun lyskom-interactive-send-message (who message alarm-ok) "Implementation of kom-send-message and kom-send-alarm." (let* ((target (or who (lyskom-read-conf-no (list 'who-to-send-message-to (lyskom-get-string (if alarm-ok 'everybody 'nobody))) (if kom-permissive-completion '(all) '(login conf)) t nil t)))) (cond ((and (zerop target) (not alarm-ok)) (lyskom-format-insert 'message-use-alarm-instead (lyskom-command-name 'kom-send-alarm))) ((not (zerop target)) (setq lyskom-last-message-recipient target) (lyskom-format-insert 'message-recipient-info target) (lyskom-send-message target message)) (t (lyskom-format-insert 'message-all-info `(face ,kom-warning-face) 'kom-send-message (max 20 (- (window-width) 8))) (lyskom-beep t) (lyskom-send-message target message))))) (defvar lyskom-message-recipient) (defvar lyskom-message-string) (defun lyskom-send-message-minibuffer-setup-hook () (unwind-protect (progn (run-hooks 'lyskom-send-message-setup-hook) (run-hooks 'kom-send-message-setup-hook)) (remove-hook 'minibuffer-setup-hook 'lyskom-send-message-minibuffer-setup-hook))) (defun lyskom-send-message-minibuffer-exit-hook () (unwind-protect (progn (run-hooks 'lyskom-send-message-exit-hook) (run-hooks 'kom-send-message-exit-hook)) (remove-hook 'minibuffer-exit-hook 'lyskom-send-message-minibuffer-exit-hook))) (defun lyskom-send-message (pers-no message &optional dontshow) "Send a message to the person with the number PERS-NO. PERS-NO == 0 means send the message to everybody. MESSAGE is the message to send. If DONTSHOW is non-nil, don't display the sent message." (let* ((lyskom-message-string nil) (reply nil) (lyskom-message-recipient nil) (lyskom-last-text-format-flags nil)) (add-hook 'minibuffer-setup-hook 'lyskom-send-message-minibuffer-setup-hook) (add-hook 'minibuffer-exit-hook 'lyskom-send-message-minibuffer-exit-hook) (setq lyskom-message-string (or message (lyskom-read-string (lyskom-format 'message-prompt pers-no) nil 'lyskom-message-history))) (setq lyskom-message-recipient (if (zerop pers-no) nil (blocking-do 'get-conf-stat pers-no))) (run-hooks 'lyskom-send-message-hook) (run-hooks 'kom-send-message-hook) (if lyskom-message-string (progn (setq reply (blocking-do 'send-message pers-no lyskom-message-string)) (if reply (if (not dontshow) (lyskom-handle-as-personal-message (lyskom-format (if lyskom-message-recipient (lyskom-get-string-sol 'message-sent-to-user) (lyskom-get-string-sol 'message-sent-to-all)) lyskom-message-string lyskom-message-recipient (when kom-async-highlight-dashed-lines `(face ,(or kom-async-dashed-lines-face lyskom-default-async-dashed-lines-face))) (when kom-async-highlight-text-body `(face ,(or kom-async-text-body-face lyskom-default-async-text-body-face)))) lyskom-pers-no kom-filter-outgoing-messages)) (lyskom-format-insert-before-prompt 'message-nope (or lyskom-message-recipient (lyskom-get-string 'everybody)) lyskom-message-string (lyskom-format 'error-code (lyskom-get-error-text lyskom-errno) lyskom-errno lyskom-err-stat)))) (lyskom-insert-string 'interrupted)) ;+++ lyskom-errno )) (defun lyskom-send-message-trim-newlines () (when (stringp lyskom-message-string) (let ((size (length lyskom-message-string))) (while (and (> size 0) (eq ?\n (aref lyskom-message-string (1- size)))) (setq size (1- size))) (cond ((and (eq size 0) (not (lyskom-j-or-n-p (lyskom-get-string 'send-empty-message-p)))) (setq lyskom-message-string nil)) ((eq size 0) (setq lyskom-message-string "")) (t (setq lyskom-message-string (substring lyskom-message-string 0 size))))))) (defun lyskom-send-message-turn-off-resize-on-exit () (resize-minibuffer-mode -1) (remove-hook 'kom-send-message-exit-hook 'lyskom-send-message-turn-off-resize-on-exit)) ;; USER-HOOK: lyskom-send-message-resize-minibuffer (defvar resize-minibuffer-mode) (lyskom-with-external-functions (resize-minibuffer-setup) (defun lyskom-send-message-resize-minibuffer () "Temporarily turn on resizing of minibuffer" (unless resize-minibuffer-mode (resize-minibuffer-mode 1) (resize-minibuffer-setup) (add-hook 'kom-send-message-exit-hook 'kom-send-message-turn-off-resize-on-exit))) ) ;; USER-HOOK: lyskom-send-message-auto-fill (defun lyskom-send-message-auto-fill () "Temporarily turn on auto fill in minibuffer" (setq fill-column 78) ;+++ Ta bort? (auto-fill-mode 1)) ;;; ================================================================ ;;; Endast l{sa senaste - Set unread articles in a conf. ;;; (Skip or re-read articles). ;;; Author: Linus Tolke ;;; Rehacked: David K}gedal (def-kom-command kom-set-unread (&optional arg conf-no) "Set number of unread articles in current conference." (interactive "P") (setq conf-no (or conf-no lyskom-current-conf)) (when conf-no (cache-del-conf-stat conf-no)) (if (or (null conf-no) (zerop conf-no)) (progn (lyskom-insert-string 'not-present-anywhere) (lyskom-insert-string "\n")) (let ((conf-stat (blocking-do 'get-conf-stat conf-no))) (if (null conf-stat) (lyskom-insert 'somebody-deleted-that-conf) (let* ((narg (prefix-numeric-value arg)) (n (if (and arg (<= 0 narg) (<= narg (conf-stat->no-of-texts conf-stat))) narg (lyskom-read-num-range-or-date 0 (conf-stat->no-of-texts conf-stat) (lyskom-format 'only-last (conf-stat->name conf-stat))))) (membership nil)) (cond ((listp n) (lyskom-format-insert 'set-unread-date (elt n 0) (car (rassq (elt n 1) lyskom-month-names)) (elt n 2)) (let* ((target-date (lyskom-create-time 0 0 0 (elt n 2) (elt n 1) (elt n 0) 0 0 nil)) (text (lyskom-find-text-by-date conf-stat target-date))) (when text (blocking-do 'set-last-read (conf-stat->conf-no conf-stat) (car text))))) ((numberp n) (lyskom-format-insert 'set-unread-n n) (blocking-do 'set-unread conf-no n))) (setq membership (blocking-do 'query-read-texts lyskom-pers-no conf-no t 0)) (lyskom-replace-membership membership) (if (= conf-no lyskom-current-conf) (set-read-list-empty lyskom-reading-list)) (read-list-delete-read-info conf-no lyskom-to-do-list) (if (= conf-no lyskom-current-conf) (progn (lyskom-fetch-start-of-map conf-stat membership) (lyskom-go-to-conf lyskom-current-conf t)) (lyskom-prefetch-map conf-no membership)) ))))) (def-kom-command kom-list-sessions () "List current LysKOM sessions and unread messages for each session. See `kom-session-nickname' for a setting that affects display." (interactive) (let ((total-letters 0) (total-texts 0) (total-confs 0) (buflist (buffer-list)) (session-list nil)) (lyskom-save-excursion (lyskom-traverse buf buflist (when (lyskom-buffer-p buf) (set-buffer buf) (let ((letters 0) (texts 0) (confs 0)) (lyskom-traverse entry (lyskom-list-news) (unless (or (not entry) ; Happens sometimes (zerop (car entry))) ; Ignore confs with 0 unread (setq texts (+ (car entry) texts)) (setq confs (1+ confs)) (when (= (conf-stat->conf-no (cdr entry)) lyskom-pers-no) (setq letters (+ (car entry) letters))))) (setq total-texts (+ texts total-texts)) (setq total-letters (+ letters total-letters)) (setq total-confs (+ confs total-confs)) (setq session-list (append (list (list (lyskom-session-nickname) (lyskom-format "%#1P" lyskom-pers-no) texts letters confs kom-server-priority)) session-list)))))) (setq session-list (sort session-list (lambda (s1 s2) (if (= (nth 5 s1) ; Same priority? (nth 5 s2)) (string< (nth 0 s1) (nth 0 s2)) ; Sort on name (< (nth 5 s1) ; Different priority - sort on that (nth 5 s2)))))) (lyskom-traverse session session-list (if (zerop (nth 2 session)) (lyskom-format-insert 'session-list-no-unread-in (nth 0 session)) (lyskom-format-insert 'session-list-unreads-in-confs (nth 0 session) (nth 3 session) (nth 2 session) (nth 4 session)))))) ;;; ================================================================ ;;; Lista Nyheter - List News ;;; Author: Linus Tolke ;;; Rehacked: Inge Wallin, Johan Sundström (defvar lyskom-special-conf-name "\\`\\(Inl.gg .t mig\\|NL:\\)\\'" "Regexp to match conf names that are special.") (defvar lyskom-iter-list-news-total-confs) (defvar lyskom-iter-list-news-mship-confs) (defvar lyskom-iter-list-news-shown-unreads) (defvar lyskom-iter-list-news-shown-confs) (defvar lyskom-iter-list-news-total-unreads) (defvar lyskom-iter-list-news-total-confs) (defun lyskom-iter-list-news (unreads conf-stat at-least at-most) "Callback function used to show the number of unread messages of a conference. It heavily relies on (and destructively modifies) its environment." (when (and (or (not at-least) (>= unreads at-least)) ; unreads within lower bound (or (not at-most) (<= unreads at-most))) ; unreads within upper bound (when lyskom-iter-list-news-mship-confs ; remember all read conferences? (setq lyskom-iter-list-news-mship-confs (delq (conf-stat->conf-no conf-stat) lyskom-iter-list-news-mship-confs))) (cond ((and (boundp 'lyskom-special-conf-name) (stringp lyskom-special-conf-name) (string-match lyskom-special-conf-name (conf-stat->name conf-stat))) (lyskom-format-insert 'you-have-unreads-special unreads conf-stat)) (t (lyskom-format-insert 'you-have-unreads unreads conf-stat))) (setq lyskom-iter-list-news-shown-unreads (+ lyskom-iter-list-news-shown-unreads unreads) lyskom-iter-list-news-shown-confs (1+ lyskom-iter-list-news-shown-confs))) (setq lyskom-iter-list-news-total-unreads (+ lyskom-iter-list-news-total-unreads unreads) lyskom-iter-list-news-total-confs (1+ lyskom-iter-list-news-total-confs))) (def-kom-command kom-list-news (&optional num) "Print the number of unread texts in each conference. If the prefix argument is zero, show all conferences, including those with no unread textts. With a positiv prefix argument, only show conferences with at least that many unread texts. With a negative prefix argument, only show conferences with no more than that many unread texts. See `kom-allow-incompleteness'." (interactive "P") (let ((num-arg (cond ((numberp num) num) ((and (listp num) (numberp (car num))) (car num)) (t nil))) (lyskom-iter-list-news-mship-confs nil) (at-least 1) (at-most nil) (lyskom-iter-list-news-shown-unreads 0) (lyskom-iter-list-news-total-unreads 0) (lyskom-iter-list-news-shown-confs 0) (lyskom-iter-list-news-total-confs 0)) (when num-arg (cond ((= num-arg 0) (lyskom-traverse-membership el (when (not (membership-type->passive (membership->type el))) (setq lyskom-iter-list-news-mship-confs (cons (membership->conf-no el) lyskom-iter-list-news-mship-confs)))) (setq at-least nil lyskom-iter-list-news-mship-confs (nreverse lyskom-iter-list-news-mship-confs))) ((> num-arg 0) (lyskom-format-insert 'list-unread-with-n-unread (setq at-least num-arg))) ((< num-arg 0) (lyskom-format-insert 'list-unread-with-at-most-n-unread (setq at-most (- num-arg)))))) ;; The following variables are bound in the callback ;; lyskom-iter-list-news-total-unreads ;; lyskom-iter-list-news-shown-unreads ;; lyskom-iter-list-news-total-confs ;; lyskom-iter-list-news-shown-confs ;; lyskom-iter-list-news-mship-confs (lyskom-list-news 'lyskom-iter-list-news (list at-least at-most)) (when lyskom-iter-list-news-mship-confs ; then list all read conferences too (lyskom-traverse conf-no lyskom-iter-list-news-mship-confs (lyskom-format-insert 'you-have-no-unreads conf-no))) (if (= 0 lyskom-iter-list-news-total-unreads) (lyskom-insert-string 'you-have-read-everything) (if (= 0 lyskom-iter-list-news-shown-unreads) (lyskom-insert-string 'no-unreads-shown) (lyskom-insert "\n")) ; separate the shown list from the summary message (when (and (> lyskom-iter-list-news-shown-unreads 0) (< lyskom-iter-list-news-shown-unreads lyskom-iter-list-news-total-unreads)) (lyskom-format-insert 'shown-unreads lyskom-iter-list-news-shown-unreads lyskom-iter-list-news-shown-confs)) (lyskom-format-insert 'total-unreads lyskom-iter-list-news-total-unreads lyskom-iter-list-news-total-confs)))) (defun lyskom-list-news (&optional callback &optional callback-args) "With no arguments, returns a list of tuples (unread . conf-stat). When called with a CALLBACK function, this function is called iteratively as the list is built up. This function should take the two arguments `number-of-unread-messages-in-conference' and `conf-stat' and optionally any other arguments sent in the list CALLBACK-ARGS, and its return value will form the elements of the list returned from lyskom-list-news. The callback will only be fed conferences with at least one unread message in them." (unless kom-allow-incompleteness (sit-for 0) (lyskom-prefetch-all-confs)) (mapcar (function (lambda (info) (let ((unreads (length (text-list->texts (read-info->text-list info)))) (conf-stat (read-info->conf-stat info))) (when (eq (read-info->type info) 'CONF) (if callback (apply callback unreads conf-stat callback-args) (cons unreads conf-stat)))))) (read-list->all-entries lyskom-to-do-list))) ;;; ================================================================ ;;; V{nta - Idle wait (defun kom-busy-wait (arg) "Wait for new texts. Waiting is interrupted when a text in a conference with higher priority than that of the next text to be read. If you want another priority to break that the ones higher that the next text to be read, give the priority as a prefix argument. When a text is received the new text is displayed. This command is semi-obsolete and may be removed in a future version of the client. See `kom-ding-on-wait-done'." (interactive "P") (lyskom-start-of-command 'kom-busy-wait) (unwind-protect (let ((waitfor (or (cond ((integerp arg) arg) ((listp arg) (car arg))) (read-info->priority (read-list->first lyskom-to-do-list)) -2))) (lyskom-tell-server kom-mercial) (if (not (read-list-isempty lyskom-reading-list)) (set-read-list-empty lyskom-reading-list)) (if (= waitfor -2) (lyskom-insert-string 'waiting-for-anything) (lyskom-format-insert 'waiting-higher-than waitfor)) (lyskom-scroll) (setq lyskom-is-waiting (list '> '(or (read-info->priority (read-list->first lyskom-reading-list)) (read-info->priority (read-list->first lyskom-to-do-list)) 257) waitfor)) (while lyskom-is-waiting ;; This is a bit trial-and-error stuff at the momemt. ;; o How to make personal messages appear *fast* ;; o How to enable C-g with a quick response (sit-for 0) (accept-process-output nil 1) (sit-for 0) (if lyskom-quit-flag (signal 'quit nil)))) (lyskom-end-of-command)) ;; We are done waiting (lyskom-beep kom-ding-on-wait-done) (if (read-list-isempty lyskom-reading-list) (kom-go-to-next-conf)) (kom-next-command)) (defun lyskom-time-greater (time1 time2) "Returns t if TIME2 is before TIME1 chronologically." (cond ((< (time->year time2) (time->year time1))) ((> (time->year time2) (time->year time1)) nil) ((< (time->mon time2) (time->mon time1))) ((> (time->mon time2) (time->mon time1)) nil) ((< (time->mday time2) (time->mday time1))) ((> (time->mday time2) (time->mday time1)) nil) ((< (time->hour time2) (time->hour time1))) ((> (time->hour time2) (time->hour time1)) nil) ((< (time->min time2) (time->min time1))) ((> (time->min time2) (time->min time1)) nil) ((< (time->sec time2) (time->sec time1))) ((> (time->sec time2) (time->sec time1)) nil) (t nil))) ;;; ================================================================ ;;; Lista {rende - list summary ;;; Author: Linus Tolke (def-kom-command kom-list-summary (prefix) "List a summary of the unread texts in the current conference. The summary contains the date, number of lines, author and subject of the text on one line. with a prefix argument, list each unique subject only once." (interactive "P") (if (read-list-isempty lyskom-reading-list) (lyskom-insert-string 'have-to-be-in-conf-with-unread) (lyskom-list-summary nil prefix))) (defun lyskom-list-summary (conf-no &optional unique) "List a summary of unread texts in conference CONF-NO. If CONF-NO is nil, list the first text-list element in lyskom-reading-list. If UNIQUE is non-nil, list only the first text with a particular subject. The summary contains the date, number of lines, author and subject of the text on one line." (let* ((read-info nil) (read-list (if conf-no lyskom-to-do-list lyskom-reading-list)) (len (read-list-length read-list)) (r 0)) (while (< r len) (if (or (and conf-no (eq (read-info->type (read-list->nth read-list r)) 'CONF) (eq conf-no (conf-stat->conf-no (read-info->conf-stat (read-list->nth read-list r))))) (and (null conf-no) (memq (read-info->type (read-list->nth read-list r)) '(CONF REVIEW-MARK REVIEW REVIEW-TREE REVIEW-FAQ REVIEW-FAQ-TREE)))) (setq len 0) (setq r (1+ r)))) (setq read-info (read-list->nth read-list r)) (when read-info (lyskom-list-text-summary (text-list->texts (read-info->text-list read-info)) '(text-no " " written " " lines " " comments " " author " " subject) (if unique :unique :comment-order))))) ;;; ============================================================ ;;; kom-list-marks Lista markeringar ;;; Author: David Byers ;;; Modified by: Joel Rosdahl (def-kom-command kom-list-marks (&optional which-mark) "List texts marked with a particular mark. Use `kom-mark-text' to mark texts and `kom-unmark-text' to unmark them. A numeric prefix argument indicated the mark to list. With no prefix argument, you will be prompted for the mark." (interactive "P") (when (not (numberp which-mark)) (setq which-mark (lyskom-read-mark-type (lyskom-get-string 'list-which-mark) t))) ;; Start fetching all text-stats and text to list them. (lyskom-list-text-summary (sort (listify-vector (blocking-do 'get-marks)) (lambda (a b) (< (mark->mark-type a) (mark->mark-type b)))) '(mark-type " " text-no " " written " " lines " " mark-count " " author " " subject) :filter (lambda (mark which-mark) (or (null which-mark) (eq (mark->mark-type mark) which-mark))) :filter-args (list which-mark))) ;;; ============================================================ ;;; kom-who-am-i - Vem är jag ;;; ;;; Author: David Byers (def-kom-command kom-who-am-i () "Show your name and information about your sessions." (interactive) (if (and lyskom-current-conf (not (zerop lyskom-current-conf))) (lyskom-format-insert 'who-i-am-present lyskom-pers-no lyskom-current-conf) (lyskom-format-insert 'who-i-am-not-present lyskom-pers-no)) (lyskom-format-insert 'who-i-am-server lyskom-server-name (version-info->software-version lyskom-server-version-info)) (lyskom-format-insert 'who-i-am-client lyskom-clientversion lyskom-mule-compiled) (lyskom-format-insert 'who-i-am-emacs (emacs-version) enable-multibyte-characters)) ;;; ================================================================ ;;; Hj{lp vid del av kommando - Help function ;;; Author: Linus Tolke (defun lyskom-help () "Prints a short list of alternatives when you don't know what you can do." (interactive) (let* ((tohere (cond ((stringp (this-command-keys)) (substring (this-command-keys) 0 -1)) (t ;This is the case in the lucid-emacs. (let* ((tck (this-command-keys)) (newvec (make-vector (1- (length tck)) nil)) (r 0)) (while (< r (length newvec)) (aset newvec r (aref tck r)) (++ r)) newvec)))) (binding (key-binding tohere)) (keymap (cond ((and (symbolp binding) (fboundp binding)) (symbol-function binding)) (t binding))) (keylis (lyskom-help-get-keylist keymap)) (text (format "\n%s: \n%s\n" (mapconcat 'single-key-description tohere " ") (mapconcat (function (lambda (arg) (format "%s - %s" (if (fboundp 'key-description) (if (not (vectorp (car arg))) (key-description (vector (car arg))) (key-description (car arg))) (cond ((symbolp (car arg)) (format "%s" (car arg))) ((lyskom-characterp (car arg)) (format "%c" (car arg))) (t (format "%S" (car arg))))) (or (lyskom-command-name (cdr arg)) (and (keymapp (cdr arg)) (lyskom-get-string 'multiple-choice)) (cdr arg))))) keylis "\n"))) ;; next-char ) (if (eq major-mode 'lyskom-mode) (progn (lyskom-insert text) (lyskom-end-of-command)) (with-output-to-temp-buffer "*Help*" (princ text))))) (defun lyskom-help-get-keylist (keymap) (and keymap (let (list) (lyskom-map-keymap (lambda (event function) (setq list (cons (cons event function) list))) keymap t) (nreverse list)))) ;;; ================================================================ ;;; [ndra livsl{ngd - Set lifespan of texts in a conference ;;; Author: Inge Wallin (def-kom-command kom-set-garb-nice () "Set the garbage collection time for a conference. Texts in a conference will eventually be deleted automatically \(this process is called garbage collection). This can only happen when a text is older than the garbage collection time of all its recipients." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'conf-to-set-garb-nice-q '(all) nil nil t))) (if (not conf-stat) (lyskom-insert-string 'somebody-deleted-that-conf) (let ((garb-nice (lyskom-read-number 'new-garb-nice-q (conf-stat->garb-nice conf-stat))) (keep-commented (lyskom-read-number 'new-keep-commented-q (conf-stat->keep-commented conf-stat)))) (lyskom-format-insert 'garb-nice-for-is conf-stat garb-nice) (if (not (blocking-do 'set-garb-nice (conf-stat->conf-no conf-stat) garb-nice)) (lyskom-insert-string 'nope) ;+++lyskom-errno (lyskom-insert-string 'done) (cache-del-conf-stat (conf-stat->conf-no conf-stat)) (sit-for 0) (lyskom-format-insert 'keep-commented-for-is conf-stat keep-commented) (if (not (blocking-do 'set-keep-commented (conf-stat->conf-no conf-stat) keep-commented)) (lyskom-insert-string 'nope) ;+++lyskom-errno (lyskom-insert-string 'done) (cache-del-conf-stat (conf-stat->conf-no conf-stat)))))))) ;;; ================================================================ ;;; S{tt till}tna f|rfattare - set-permitted-submitters ;;; Author: Linus Tolke (def-kom-command kom-set-permitted-submitters () "Set the permitted submitters of a conference. The permitted submitters of a conference is another conference. Only members of the permitted submitters may submit texts to the conference." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'conf-to-set-permitted-submitters-q '(all) nil nil t))) (if (not conf-stat) (lyskom-insert-string 'somebody-deleted-that-conf) (let ((new-conf (lyskom-read-conf-stat `(new-permitted-submitters-q ,(conf-stat->name conf-stat)) '(all) t nil t))) (if (eq new-conf nil) (lyskom-format-insert 'permitted-submitters-removed-for-conf conf-stat) (lyskom-format-insert 'submitters-conf-for-is conf-stat new-conf)) (if (not (blocking-do 'set-permitted-submitters (conf-stat->conf-no conf-stat) (if (eq new-conf nil) ;Allowing all to write there 0 (conf-stat->conf-no new-conf)))) (lyskom-insert-string 'nope) ;+++ lyskom-errno (lyskom-insert-string 'done) (cache-del-conf-stat (conf-stat->conf-no conf-stat))))))) ;;; ================================================================ ;;; [ndra superm|te - Set super conference ;;; Author: Inge Wallin (def-kom-command kom-set-super-conf () "Set the super conference for a conference. If a conference is set to only accept new texts, and not comments, any comments submitted to the conference will be sent to the super conference instead." (interactive) (let ((conf-stat (lyskom-read-conf-stat 'conf-to-set-super-conf-q '(all) nil nil t))) (if (not conf-stat) (lyskom-insert-string 'somebody-deleted-that-conf) (let ((new-conf (lyskom-read-conf-stat `(new-super-conf-q ,(conf-stat->name conf-stat)) '(all) nil nil t))) ;; Set the super conference for conf-stat to new-conf. (lyskom-format-insert 'super-conf-for-is conf-stat new-conf) (if (not (blocking-do 'set-super-conf (conf-stat->conf-no conf-stat) (conf-stat->conf-no new-conf))) (lyskom-insert-string 'nope) ;+++ lyskom-errno (lyskom-insert-string 'done) (cache-del-conf-stat (conf-stat->conf-no conf-stat))))))) ;;; ================================================================ ;;; Spara databasen - Save database ;;; (def-kom-command kom-sync-database () "Save the LysKOM database. You can only run this command if you have administrative rights. See `kom-enable-adm-caps'." (interactive) (if (and (>= (version-info->protocol-version lyskom-server-version-info) 8) (lyskom-ja-or-nej-p (lyskom-get-string 'really-sync))) (progn (lyskom-insert-string 'syncing-server) (lyskom-report-command-answer (blocking-do 'sync))) (setq lyskom-errno 12) (lyskom-report-command-answer nil))) ;;; ================================================================ ;;; St{ng av servern - Shutdown ;;; Author: Inge Wallin (def-kom-command kom-shutdown-server () "Shutdown the LysKOM server. You can only run this command if you have administrative rights. See `kom-enable-adm-caps'." (interactive) (if (lyskom-ja-or-nej-p (lyskom-get-string 'really-shutdown)) (progn (lyskom-insert-string 'closing-server) (lyskom-report-command-answer (blocking-do 'shutdown 0))))) ;;; ================================================================ ;;; \verg} till adm.mod - Enable administrator capabilities ;;; \verg} till normalmod - Disable administrator capabilities ;;; Author: Inge Wallin (def-kom-command kom-enable-adm-caps () "Enable the adminstrator commands for the current user. You can use this command even if you don't have administrative rights on the system, but you still won't be able to use privileged commands. Use `kom-disable-adm-caps' to return to normal mode." (interactive) (lyskom-enable-adm-caps (blocking-do 'enable 255) (lyskom-get-string 'administrator) t)) (def-kom-command kom-disable-adm-caps () "Disable the LysKOM adminstrator commands for the current user." (interactive) (lyskom-enable-adm-caps (blocking-do 'enable 0) (lyskom-get-string 'no-longer-administrator) nil)) (defun lyskom-enable-adm-caps (answer string is-administrator) "Tell the user if the call succeded." (if answer (progn (lyskom-format-insert 'you-are-now string) (setq lyskom-is-administrator is-administrator)) (lyskom-insert-string 'nope))) ;+++ lyskom-errno ;;; ================================================================ ;;; S{tt loginmeddelande - Set message of the day ;;; Author: Inge Wallin (def-kom-command kom-set-motd () "Set the notice for the server. You can only use this command if you have administrative rights. See `kom-enable-adm-caps'." (interactive) (let* ((old-motd-text-stat (and (server-info->motd-of-lyskom lyskom-server-info) (blocking-do 'get-text-stat (server-info->motd-of-lyskom lyskom-server-info)))) (old-motd-text (and (server-info->motd-of-lyskom lyskom-server-info) (blocking-do 'get-text (server-info->motd-of-lyskom lyskom-server-info)))) (str (and old-motd-text old-motd-text-stat (text->decoded-text-mass old-motd-text old-motd-text-stat))) (recpt (if old-motd-text-stat (lyskom-get-recipients-from-misc-list (text-stat->misc-info-list old-motd-text-stat)) (apply 'nconc (mapcar (lambda (x) (list 'RECPT x)) (and lyskom-server-info (server-info->kom-news-conf lyskom-server-info) (not (eq 0 (server-info->kom-news-conf lyskom-server-info))) (list (server-info->kom-news-conf lyskom-server-info)))))))) (lyskom-edit-text lyskom-proc (apply 'lyskom-create-misc-list recpt) (if (and str (string-match "\n" str)) (substring str 0 (1- (match-end 0))) "") (if (and str (string-match "\n" str)) (substring str (match-end 0)) "") 'lyskom-set-motd-2))) ;; Should really fix lyskom-edit text instead of the ugly IGNORE (defun lyskom-set-motd-2 (text-no ignore) "Set motd of LysKOM to the newly created text TEXT-NO." (lyskom-insert-before-prompt (lyskom-format 'setting-motd text-no)) (initiate-set-motd-of-lyskom 'background 'lyskom-set-motd-3 text-no text-no)) (defun lyskom-set-motd-3 (result text-no) "Handle the return from the initiate-set-motd-of-lyskom call." (if result (progn (lyskom-insert-before-prompt (lyskom-get-string (if (zerop text-no) 'removed-motd 'set-motd-success))) (set-server-info->motd-of-lyskom lyskom-server-info text-no)) (lyskom-insert-before-prompt (lyskom-get-string 'set-motd-failed)))) ;;; ================================================================ ;;; Ta bort loginmeddelande - Remove message of the day ;;; Author: Inge Wallin (def-kom-command kom-remove-motd () "Remove the notice for the LysKOM server. You can only use this command if you have administrative rights. See `kom-enable-adm-caps'." (interactive) (lyskom-insert-string 'removing-motd) (initiate-set-motd-of-lyskom 'background 'lyskom-set-motd-3 0 0)) ;;; ================================================================ ;;; Kasta ut - force logout ;;; Author: Inge Wallin (def-kom-command kom-force-logout () "Force another session to log out. You can log out any sessions logged on as users you are the supervisor of. With administrative rights you can log out any user." (interactive) (let ((session (car-safe (lyskom-read-session-no 'who-to-throw-out nil nil t)))) (cond ((> session 0) (lyskom-format-insert 'throwing-out session) (lyskom-report-command-answer (blocking-do 'disconnect session))) ((< session 0) (lyskom-format-insert 'person-not-logged-in-r (- session) nil)) (t nil)))) ;;; ================================================================ ;;; Skjut upp l{sning - postpone ;;; Author: Per Cederqvist (def-kom-command kom-postpone (today) "Postpone the reading of all but the last N texts in the current conference. The postponed texts will be removed from the read list for this session but return in your next session or when you do a `kom-recover'. A numeric prefix argument is the number of texts to read now. Without a prefix argument this command will prompt for the number of texts." (interactive (list (cond ((null current-prefix-arg) (lyskom-read-number 'postpone-prompt kom-postpone-default)) (t (prefix-numeric-value current-prefix-arg))))) (let ((len (read-list-length lyskom-reading-list)) (finished nil)) (while (and (not finished) (> len 0)) (let ((type (read-info->type (read-list->first lyskom-reading-list)))) (cond ((memq type lyskom-review-types-list) (read-list-rotate lyskom-reading-list)) ((memq type lyskom-comment-types-list) (set-read-list-del-first lyskom-reading-list)) ((eq type 'CONF) (text-list->trim-head (read-info->text-list (read-list->first lyskom-reading-list)) today) (setq finished t)) ((eq type 'RE-EDIT-TEXT)) ((eq type 'PRI-SESSION)) (t (signal 'lyskom-internal-error '("lyskom-remove-comment-chains"))))) (-- len))) ;; Delete the 'CONF entry if we selected 0 entries. (cond ((zerop today) (read-list-delete-text nil lyskom-reading-list) (read-list-delete-text nil lyskom-to-do-list)))) ;;; ================================================================ ;;; S{tt l{sniv} - Sess session priority ;;; Author: David K}gedal (def-kom-command kom-set-session-priority (priority) "Set the priority level of the current session and refetch all memberships. Conferences whose priorities are lower than the session priority will not be included when reading. This is useful to separate conferences to read while at work from conferences to not read at work. A numeric prefix argument specifies the new session priority. Without prefix argument, you will be prompted for a priority. See `kom-default-session-priority'." (interactive "P") (let ((pri (or priority (lyskom-read-num-range 0 255 (lyskom-get-string 'set-session-priority) t (or kom-default-session-priority 100))))) (setq lyskom-session-priority pri) (lyskom-refetch))) ;;; ================================================================ ;;; Begrav lyskom-sessionen - kom-bury ;;; Author: Linus Tolke (defun kom-bury () "Puts the kom-session in the background." (interactive) (let ((session-name (buffer-name (current-buffer))) (buffer (current-buffer))) (bury-buffer) (while (and (string-match (regexp-quote session-name) (buffer-name (current-buffer))) (not (eq buffer (current-buffer)))) (bury-buffer)))) (defun lyskom-buffer-p (buf &optional may-be-dead) "Returns non-nil if BUF is an active LysKOM buffer If optional second argument MAY-BE-DEAD is non-nil, this function returns t whether the session is alive or not. Otherwise it checks that the session is alive." (when (buffer-live-p buf) (save-excursion (set-buffer buf) (and (eq major-mode 'lyskom-mode) (boundp 'lyskom-proc) lyskom-proc (processp lyskom-proc) (or (and may-be-dead (memq (process-status lyskom-proc) '(run open closed))) (memq (process-status lyskom-proc) '(run open))))))) (defun lyskom-next-kom (buffer-list-name direction) "Internal version of kom-next-kom BUFFER-LIST-NAME is the list of buffers to rotate through. It must be a name since this function may modify the list. DIRECTION should be one of 'forward or 'backward and is the direction to rotate through the buffer list. Return-value: 'no-session if there is no suitable session to switch to 'same-session if the current buffer is the only suitable one nil if everything went well" ;; Clean the buffer lists (lyskom-clean-all-buffer-lists) (let ((current (lyskom-buffer-root-ancestor (current-buffer))) (buffer-list (symbol-value buffer-list-name)) (result nil)) ;; Figure out the start buffer. The target buffer will be the ;; following buffer in lyskom-buffer-list (cond ((null buffer-list) (setq result 'no-session current nil)) ;; If we are in a lyskom buffer that is in lyskom-buffer-list ;; switch from the current buffer. If unlisted, list it. ((lyskom-buffer-p current) (unless (memq current buffer-list) (setq buffer-list (cons current buffer-list)))) ;; If we are in a non-LysKOM buffer, the start buffer is the ;; last one in the list (t (setq current (car buffer-list)))) ;; Rotate the buffer list so the target buffer is first (when current (cond ((eq direction 'forward) (setq buffer-list (lyskom-rotate-list buffer-list (car (cdr (memq current buffer-list)))))) (t (setq buffer-list (lyskom-rotate-list buffer-list (or (car (lyskom-preceding-cons buffer-list current)) (car (last buffer-list))))))) (set buffer-list-name buffer-list) ;; If the current buffer and the target buffer are the same ;; do nothing. Otherwise, flip around the buffers (if (eq (current-buffer) (car buffer-list)) (setq result 'same-session) (lyskom-switch-to-kom-buffer (car buffer-list) current) (setq result nil))) result)) (def-kom-emacs-command kom-next-kom () "Pop up the next LysKOM-session. This command can be run from any buffer to go to the next available LysKOM session. See `kom-previous-kom' and `kom-next-unread-kom' for related commands." (interactive) (let ((result (lyskom-next-kom 'lyskom-buffer-list 'forward))) (cond ((eq result 'no-session) (error (lyskom-get-string 'no-lyskom-session))) ((eq result 'same-session) (if kom-next-kom-running-as-kom-command (lyskom-insert-before-prompt (lyskom-get-string 'no-other-lyskom-r)) (error (lyskom-get-string 'no-lyskom-session)))) (t nil)))) (def-kom-emacs-command kom-previous-kom () "Pop up the previous LysKOM-session. This command can be run from any buffer to go to the next available LysKOM session. See `kom-next-kom' and `kom-next-unread-kom' for related commands." (interactive) (let ((result (lyskom-next-kom 'lyskom-buffer-list 'backward))) (cond ((eq result 'no-session) (error (lyskom-get-string 'no-lyskom-session))) ((eq result 'same-session) (if kom-previous-kom-running-as-kom-command (lyskom-insert-before-prompt (lyskom-get-string 'no-other-lyskom-r)) (error (lyskom-get-string 'no-lyskom-session)))) (t nil)))) (def-kom-emacs-command kom-next-unread-kom () "Pop up the next LysKOM-session with unread texts. This command can be run from any buffer to go to the next available LysKOM session. See `kom-next-kom' and `kom-previous-kom' for related commands." (interactive) (let ((result (lyskom-next-kom 'lyskom-sessions-with-unread 'forward))) (cond ((eq result 'no-session) (if kom-next-unread-kom-running-as-kom-command (lyskom-insert-before-prompt (lyskom-get-string 'no-unread-lyskom-r)) (error (lyskom-get-string 'no-unread-lyskom)))) ((eq result 'same-session) (if kom-next-unread-kom-running-as-kom-command (lyskom-insert-before-prompt (lyskom-get-string ;; Are there are any other sessions at all? (if (= 1 (length lyskom-buffer-list)) 'no-other-lyskom-r 'no-other-unread-lyskom-r))) (error (lyskom-get-string 'no-lyskom-session)))) (t nil)))) (defun kom-modeline-next-unread-kom () "Pop up the previous unread lyskom session, if there is one" (interactive) (lyskom-next-kom 'lyskom-sessions-with-unread 'forward)) (defun kom-modeline-select-unread-kom (event) "Pop up a menu of sessions with unreads" (interactive "@e") (when lyskom-sessions-with-unread (let ((unreads (mapcar (lambda (buffer) (save-excursion (set-buffer buffer) (vector (lyskom-format "%#1P, %#2s%#3?b%[ (%#4s)%]%[%]" lyskom-pers-no (lyskom-session-nickname) (memq buffer lyskom-sessions-with-unread-letters) (lyskom-get-string 'unread-letters)) (list 'lyskom-switch-to-kom-buffer buffer) :active t))) lyskom-sessions-with-unread))) (popup-menu (cons (lyskom-get-string 'sessions-with-unreads) unreads) event)))) (defun lyskom-switch-to-kom-buffer (buffer &optional current) (when buffer (when (and kom-bury-buffers (or (null current) (eq current (current-buffer)))) (kom-bury)) ;; Switch to the new buffer (switch-to-buffer buffer))) ;;; ============================================================ ;;; Var finns kommandot (kom-where-is) ;;; Author: David Byers (def-kom-emacs-command kom-where-is (cmd) "Show on which key a LysKOM command is. Prompts for a command name and displays all key bindings for the command. This is similar to the Emacs function `where-is', but reads localized LysKOM command names, not function names." (interactive (list (lyskom-read-extended-command))) (let ((w (where-is-internal cmd)) (msg nil)) (cond ((null cmd) (setq msg (lyskom-format (lyskom-get-string 'where-is-doesnt-exist) (lyskom-command-name cmd)))) ((null w) (setq msg (lyskom-format (lyskom-get-string 'where-is-on-no-key) (lyskom-command-name cmd)))) (t (setq msg (lyskom-format (lyskom-get-string 'where-is-on-key) (lyskom-command-name cmd) (mapconcat (lambda (x) (format "`%s'" (key-description x))) w ", "))))) (if kom-where-is-running-as-kom-command (lyskom-insert-before-prompt (concat msg "\n")) (message msg)))) ;;;============================================================ ;;; Visa user-arean (kom-show-user-area) ;;; ;;; Author: David Byers (def-kom-command kom-show-user-area () "Get and display the user area of the current person. The user area is a regular text used to store all settings. The format of this text is documented in the LysKOM protocol specification. This command is primarily intended for use by developers." (interactive) (let ((pers-stat (blocking-do 'get-pers-stat lyskom-pers-no))) (lyskom-view-text (pers-stat->user-area pers-stat) nil nil nil nil nil) (lyskom-wait-queue 'main))) ;;;============================================================ ;;; Bli anonym (def-kom-command kom-become-anonymous () "Become pseudo-anonymous. When this mode is in effect, your movements in LysKOM will not be reported as usual, and when writing texts you will have the option of sending them anonymously. Depending on what you do, it may still be possible to deduce that you are the author of an anonymous text. To summarize, texts you create while in this mode should be difficult to trace back to you, if you are careful. It is not foolproof. Use `kom-become-nonanonymous' to return to normal mode." (interactive) (if lyskom-is-anonymous (lyskom-insert 'you-are-already-anonymous) ; (initiate-pepsi 'main nil 0) (setq lyskom-is-anonymous t) (lyskom-tell-server kom-mercial) (lyskom-insert 'you-are-anonymous) (lyskom-update-prompt t))) (def-kom-command kom-become-nonanonymous () "Leave pseudo-anonymous mode. See `kom-become-anonymous' for information on anonymous mode." (interactive) (if lyskom-is-anonymous (progn (when (and lyskom-current-conf (not (zerop lyskom-current-conf))) (initiate-pepsi 'main nil lyskom-current-conf)) (setq lyskom-is-anonymous nil) (lyskom-update-prompt t) (lyskom-insert 'you-are-nonanonymous)) (lyskom-insert 'you-are-already-nonanonymous))) ;;;============================================================ ;;; Ändra mötestyp (kom-change-conf-type) ;;; ;;; Author: Tomas Abrahamsson & David Byers (def-kom-command kom-change-conf-type () "Change type of a conference. Using this command you can set all flags of a conference, with the exception of the letterbox flag (which cannot be modified)." (interactive) (let* ((uconf-stat (lyskom-read-uconf-stat 'what-conf-to-change '(conf pers) nil "" t)) (type (uconf-stat->conf-type uconf-stat)) (box (conf-type->letterbox type)) (ori (conf-type->original type)) (pro (conf-type->rd_prot type)) (sec (conf-type->secret type)) (ano (conf-type->anarchy type)) (ope (conf-type->forbid-secret type))) (lyskom-format-insert 'change-type-prompt uconf-stat (mapconcat 'identity (delq nil (list (and box (lyskom-get-string 'Mailbox)) (and sec (lyskom-get-string 'Protected)) (and ori (lyskom-get-string 'no-comments)) (and pro (lyskom-get-string 'closed)) (and ano (lyskom-get-string 'allow-anon)) (and (not ope) (lyskom-get-string 'allow-secret)))) ", ")) (let* ((open (lyskom-j-or-n-p (lyskom-get-string 'anyone-member))) (secret (if (not open) (lyskom-j-or-n-p (lyskom-get-string 'secret-conf)))) (orig (lyskom-j-or-n-p (lyskom-get-string 'comments-allowed))) (anarchy (lyskom-j-or-n-p (lyskom-get-string 'anonymous-allowed))) (secmem (and (lyskom-have-feature long-conf-types) (not (lyskom-j-or-n-p (lyskom-get-string 'secret-members-allowed)))))) (cache-del-conf-stat (uconf-stat->conf-no uconf-stat)) (cache-del-uconf-stat (uconf-stat->conf-no uconf-stat)) (if (not (blocking-do 'set-conf-type (uconf-stat->conf-no uconf-stat) (lyskom-create-conf-type (not open) (not orig) secret (conf-type->letterbox (uconf-stat->conf-type uconf-stat)) anarchy (if (lyskom-have-feature long-conf-types) secmem (conf-type->forbid-secret (uconf-stat->conf-type uconf-stat))) (conf-type->rsv2 (uconf-stat->conf-type uconf-stat)) (conf-type->rsv3 (uconf-stat->conf-type uconf-stat))))) (progn (lyskom-insert-string 'nope) (lyskom-insert-error)) (lyskom-insert-string 'done))))) ;;; ============================================================ ;;; Ändra språk ;;; (defun kom-change-global-language () "Use kom-change-language instead." (interactive) (kom-change-language t)) (defun kom-change-local-language () "Use kom-change-language instead" (interactive) (kom-change-language)) (def-kom-command kom-change-language (&optional global) "Change the current language in the current LysKOM session. With a prefix argument, also make changes that would affect all sessions, such as key bindings. The selected language is not saved between sessions. To permanently set and save language settings. use `kom-customize' instead. See `kom-default-language'. Lisp documentation: The optional argument GLOBAL indicates that the change should have a global effect, including changes to key binding." (interactive "P") (let* ((completion-ignore-case t) (table (lyskom-available-language-list)) (language (lyskom-completing-read (lyskom-get-string 'which-language) (lyskom-maybe-frob-completion-table table) nil t nil 'lyskom-language-history))) (when (lyskom-string-assoc language table) (lyskom-set-language (cdr (lyskom-string-assoc language table)) 'local) (when global (lyskom-set-language (cdr (lyskom-string-assoc language table)) 'global)) (lyskom-format-insert 'language-set-to (lyskom-language-name (cdr (lyskom-string-assoc language table))))))) (defun lyskom-available-language-list () "Return an alist suitable for completing read of available language names." (let ((tmp (mapcar (function (lambda (el) (cons (car el) (eval (cdr el))))) (get 'lyskom-language-codes 'lyskom-language-var))) (codes (mapcar 'car lyskom-languages)) (result nil)) (mapcar (function (lambda (code) (mapcar (function (lambda (codelist) (when (assq code codelist) (setq result (cons (cons (cdr (assq code codelist)) code) result))))) tmp))) codes) result)) ;;; ============================================================ ;;; Beräkna (lyskom-with-external-functions (calc-eval) (def-kom-command kom-calculate (&optional exprx) "Calculate a mathematical expression. This function requires the `calc' package to be installed, and is really only a simple interface to the basic functionality of calc." (interactive) (when (lyskom-try-require 'calc (lyskom-get-string 'need-library)) (let* ((expr (or exprx (lyskom-read-from-minibuffer (lyskom-get-string 'calc-expression) nil nil nil 'lyskom-expression-history))) (result (calc-eval expr))) (cond ((stringp result) (lyskom-format-insert-before-prompt "%#1s = \n %#2s\n" expr result)) (t (lyskom-format-insert-before-prompt "%#1s = \n%#2s^ %#3s\n" expr (make-string (car result) ?\ ) (car (cdr result))))))))) ;;; ============================================================ ;;; Ändra namn (def-kom-command kom-set-personal-label () "This command is obsolete, broken and doesn't work. Don't use it. Sets a personal label on an object of some kind." (interactive) (let* ((completions (list (cons (lyskom-get-string 'Conference) 'conf) (cons (lyskom-get-string 'Person) 'pers) (cons (lyskom-get-string 'Text) 'text))) (completion-ignore-case t) (type (cdr (lyskom-string-assoc (completing-read (lyskom-get-string 'label-what-kind) (lyskom-maybe-frob-completion-table completions) nil t) completions))) (objno nil) (label nil) (object nil) (secret nil) (aux nil)) (cond ((eq type 'text) (setq objno (lyskom-read-number 'label-what-text)) (setq object (blocking-do 'get-text-stat objno)) (when (null object) (lyskom-error 'no-such-text-no objno)) (setq aux (text-stat-find-aux object 10 lyskom-pers-no)) (setq secret (not (lyskom-j-or-n-p (lyskom-get-string 'label-secret)))) (setq label (lyskom-read-from-minibuffer (lyskom-get-string 'label-what-label))) (blocking-do 'modify-text-info objno (mapcar 'aux-item->aux-no aux) (list (lyskom-create-aux-item 0 10 0 0 (lyskom-create-aux-item-flags nil nil secret nil nil nil nil nil) 0 label))) (cache-del-text-stat objno)) ((memq type '(conf pers)) (setq object (lyskom-read-conf-stat (if (eq type 'pers) 'label-what-pers 'label-what-conf) (if (eq type 'pers) '(pers) '(all)) nil nil t)) (setq objno (conf-stat->conf-no object)) (setq aux (conf-stat-find-aux object 10 lyskom-pers-no)) (setq secret (not (lyskom-j-or-n-p (lyskom-get-string 'label-secret)))) (setq label (lyskom-read-from-minibuffer (lyskom-get-string 'label-what-label))) (blocking-do 'modify-conf-info objno (mapcar 'aux-item->aux-no aux) (list (lyskom-create-aux-item 0 10 0 0 (lyskom-create-aux-item-flags nil nil secret nil nil nil nil nil) 0 label))) (cache-del-conf-stat objno))))) (def-kom-command kom-fast-reply (text-no) "Add a remark to a text. Note that remarks may not be seen by all users. Users are not notified when remarks are created, and not all clients support remarks. See `kom-agree' for a variant of this command. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-fast-reply-no))) (if text-no (progn (lyskom-format-insert 'fast-replying text-no) (lyskom-fast-reply text-no (lyskom-read-string (lyskom-get-string 'fast-reply-prompt) nil 'lyskom-fast-reply-history))) (lyskom-insert-string 'confusion-what-to-reply-to))) (defun lyskom-default-agree-string (&optional text) (unless text (setq text kom-agree-text)) (cond ((null text) (lyskom-get-string 'default-agree-string)) ((stringp text) text) ((functionp text) (funcall text)) ((listp text) (lyskom-default-agree-string (elt text (random (length kom-agree-text))))))) (def-kom-command kom-agree (text-no) "Add a predefined remark to a text. Note that remarks may not be seen by all users. Users are not notified when remarks are created, and not all clients support remarks. The remark to add is defined by `kom-agree-text'. See `kom-fast-reply' for a general variant of this command. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-agree-no))) (if text-no (progn (lyskom-format-insert 'agreeing text-no) (lyskom-fast-reply text-no (lyskom-read-string (lyskom-get-string 'agree-prompt) (lyskom-default-agree-string) 'lyskom-fast-reply-history))) (lyskom-insert-string 'confusion-what-to-agree-to))) (defun lyskom-fast-reply (text-no message) "To text TEXT-NO add MESSAGE as a fast reply." (cache-del-text-stat text-no) (if (lyskom-check-fast-reply-message message) (lyskom-report-command-answer (blocking-do 'modify-text-info text-no nil (list (lyskom-create-aux-item 0 2 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 message)))) (lyskom-insert 'nope) (lyskom-insert 'fast-reply-too-long))) (defun lyskom-check-fast-reply-message (message) "Return non-nil if MESSAGE is a valid fast reply." (not (string-match "\n" message))) ;;; ============================================================ ;;; Various aux-item stuff (def-kom-command kom-add-no-comments (&optional text-no) "Add a request for no comments to the selected text. Such a request is advisory; clients may ignore them. Be restrictive with requests for no comments as other users may find them annoying or even insulting \(they can be seen as the LysKOM equivalent of telling someone to shut up and get out after making them listen to you). This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-no-comments-no))) (let ((text-stat (blocking-do 'get-text-stat text-no))) ;; Make sure there is a text there in the first place (if (null text-stat) (lyskom-format-insert 'no-such-text-no text-no) ;; Make sure that the text doesn't already have this kind of item ;; created by the same person (if (lyskom-match-aux-items (text-stat->aux-items text-stat) (lambda (el) (and (eq (aux-item->tag el) 4) (eq (aux-item->creator el) lyskom-pers-no)))) (lyskom-format-insert 'already-no-comments text-no) ;; If the author of the text is not the current user, ask if the ;; user wants to try anyway (it might work...) (if (or (eq (text-stat->author text-stat) lyskom-pers-no) (lyskom-j-or-n-p 'not-author-try-anyway-p)) (progn (lyskom-format-insert 'adding-no-comments text-no) (lyskom-report-command-answer (blocking-do 'modify-text-info text-no nil (list (lyskom-create-aux-item 0 4 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 "")))) (cache-del-text-stat text-no))))))) (def-kom-command kom-add-private-answer (text-no) "Add a request for private replies only to the selected text. Note that such requests are advisory; clients may ignore them. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-private-answer-no))) (if text-no (let ((text-stat (blocking-do 'get-text-stat text-no))) ;; Make sure there is a text there in the first place (if (null text-stat) (lyskom-format-insert 'no-such-text-no text-no) ;; Make sure that the text doesn't already have this kind of item ;; created by the same person (if (lyskom-match-aux-items (text-stat->aux-items text-stat) (lambda (el) (and (eq (aux-item->tag el) 5) (eq (aux-item->creator el) lyskom-pers-no)))) (lyskom-format-insert 'already-private-answer text-no) ;; If the author of the text is not the current user, ask if the ;; user wants to try anyway (it might work...) (if (or (eq (text-stat->author text-stat) lyskom-pers-no) (lyskom-j-or-n-p 'not-author-try-anyway-p)) (progn (lyskom-format-insert 'adding-private-answer text-no) (lyskom-report-command-answer (blocking-do 'modify-text-info text-no nil (list (lyskom-create-aux-item 0 5 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 "")))) (cache-del-text-stat text-no)))))) (lyskom-insert 'confusion-what-to-comment))) (def-kom-command kom-add-request-confirm (text-no) "Add confirmation request to the selected text. Note that such requests are advisory; clients may ignore them. Use confirmation requests very sparingly. If unmotivated use of them becomes widespread, then they will be ignored even when they are used appropriately. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'what-request-confirm-no))) (if text-no (let ((text-stat (blocking-do 'get-text-stat text-no))) ;; Make sure there is a text there in the first place (if (null text-stat) (lyskom-format-insert 'no-such-text-no text-no) ;; Make sure that the text doesn't already have this kind of item ;; created by the same person (if (lyskom-match-aux-items (text-stat->aux-items text-stat) (lambda (el) (and (eq (aux-item->tag el) 6) (eq (aux-item->creator el) lyskom-pers-no)))) (lyskom-format-insert 'already-request-confirm text-no) ;; If the author of the text is not the current user, ask if the ;; user wants to try anyway (it might work...) (if (or (eq (text-stat->author text-stat) lyskom-pers-no) (lyskom-j-or-n-p 'not-author-try-anyway-p)) (progn (lyskom-format-insert 'adding-request-confirm text-no) (lyskom-report-command-answer (blocking-do 'modify-text-info text-no nil (list (lyskom-create-aux-item 0 6 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 "")))) (cache-del-text-stat text-no)))))) (lyskom-insert 'confusion-what-to-request-confirmation))) (def-kom-command kom-review-mail-headers (text-no) "Show all mail headers of an imported message. Mail headers are also shown when you use the `kom-review-noconversion' command. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'review-mail-headers-to-what))) (if text-no (let* ((text-stat (blocking-do 'get-text-stat text-no)) (headers (and text-stat (lyskom-get-aux-item (text-stat->aux-items text-stat) 24))) (lyskom-transforming-external-text t)) (cond ((null text-stat) (lyskom-format-insert 'no-such-text-no text-no)) ((null headers) (lyskom-format-insert 'no-mail-headers text-no)) (t (lyskom-format-insert 'mail-headers-for text-no) (mapcar (lambda (el) (let ((kom-autowrap nil)) (lyskom-format-insert "%#1t" (aux-item->data el)) (lyskom-insert "\n"))) headers)))) (lyskom-insert 'confusion-what-to-review-mail-headers))) ;;; ============================================================ ;;; Keep-alive ;;; Author: ceder, byers (def-kom-var lyskom-keep-alive-timers nil "List of all active keep alive timers" local) (defun lyskom-keep-alive-callback (buffer) (condition-case nil (save-excursion (set-buffer buffer) (if (eq (process-status lyskom-proc) 'open) (initiate-get-time 'keep nil) (lyskom-stop-keep-alive))) (error (lyskom-stop-keep-alive)))) (def-kom-command kom-keep-alive () "Keep the LysKOM session alive by sending a request every once in a while. The variable `kom-keep-alive-interval' controls the frequency of the request. This command may be useful for users with brain-dead broadband access that disconnects when the line has been inactive for too long. Use `kom-stop-keep-alive' to turn off this mode." (interactive) (set-buffer lyskom-buffer) (lyskom-stop-keep-alive) (lyskom-keep-alive) (unless (eq (current-buffer) lyskom-buffer) (lyskom-message 'start-keep-alive kom-keep-alive-interval)) (lyskom-format-insert 'start-keep-alive kom-keep-alive-interval) (lyskom-insert "\n")) (defun lyskom-keep-alive () (setq lyskom-keep-alive-timers (cons (add-timeout kom-keep-alive-interval 'lyskom-keep-alive-callback (current-buffer) kom-keep-alive-interval) lyskom-keep-alive-timers))) (def-kom-command kom-stop-keep-alive () "Stop sending periodic requests to keep the session alive. See `kom-keep-alive' for more information." (interactive) (lyskom-stop-keep-alive) (unless (eq (current-buffer) lyskom-buffer) (lyskom-message "%#1s" 'stop-keep-alive)) (lyskom-insert 'stop-keep-alive) (lyskom-insert "\n")) (defun lyskom-stop-keep-alive () (mapcar 'disable-timeout lyskom-keep-alive-timers) (setq lyskom-keep-alive-timers nil)) ;;; ======================================================================== ;;; Check (if Person is a) member (of Conference) ;;; Quickly finds out whether a person is a member of a given conference ;;; Author: Johan Sundström (def-kom-command kom-is-person-member-of-conference (&optional pers-no conf-no) "Check if a particular person is a member of a particular conference." (interactive) (let* ((pers-no (or pers-no (lyskom-read-conf-no 'pers-to-check-mship-for '(pers) nil nil t))) (conf-stat (if conf-no (blocking-do 'get-conf-stat conf-no) (lyskom-read-conf-stat 'conf-to-check-mship-of '(all) nil nil t))) (mship (lyskom-is-member (conf-stat->conf-no conf-stat) pers-no))) (if (null mship) (lyskom-format-insert 'pers-is-not-member-of-conf pers-no (conf-stat->conf-no conf-stat)) (if (membership-type->passive (membership->type mship)) (progn (lyskom-format-insert 'pers-is-passive-member-of-conf pers-no conf-stat) (lyskom-format-insert 'pers-will-receive-async (membership-type->message-flag (membership->type mship)))) (lyskom-format-insert 'pers-is-member-of-conf pers-no conf-stat) (lyskom-format-insert 'pers-will-receive-async (membership-type->message-flag (membership->type mship))) (lyskom-format-insert 'pers-mship-priority (membership->priority mship)) (when kom-deferred-printing (lyskom-format-insert 'pers-is-member-of-conf-2 (lyskom-format-time 'date-and-time (membership->last-time-read mship)) (lyskom-create-defer-info 'query-read-texts (list pers-no (conf-stat->conf-no conf-stat) t 0) (lambda (membership defer-info) (if (null membership) (lyskom-replace-deferred defer-info (lyskom-get-string 'Unknown-number)) (let ((conf-stat (defer-info->data defer-info))) (lyskom-replace-deferred defer-info (number-to-string (- (+ (conf-stat->first-local-no conf-stat) (conf-stat->no-of-texts conf-stat)) (membership->last-text-read membership) (length (membership->read-texts membership)) 1)))))) nil nil "%#1s" conf-stat)))) ))) (def-kom-command kom-will-person-read-text (pers-no text-no) "Check if a particular person is a member of any recipient of a text.. If a prefix argument is given, that text will be checked. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-conf-no 'pers-to-check-will-read-for '(all) nil nil t) (lyskom-read-text-no-prefix-arg 'text-to-check-will-read-for))) (let* ((text-stat (blocking-do 'get-text-stat text-no)) (recipients (and text-stat (lyskom-text-recipients text-stat))) (result nil)) (lyskom-traverse rcpt recipients (let ((mship (lyskom-is-member rcpt pers-no))) (when mship (if (membership-type->passive (membership->type mship)) (setq result 'passive) (setq result t) (lyskom-traverse-break))))) (cond ((null result) (lyskom-format-insert 'pers-is-not-member-of-rcpt pers-no text-stat)) ((eq result 'passive) (lyskom-format-insert 'pers-is-passive-member-of-rcpt pers-no text-stat)) (t (lyskom-format-insert 'pers-is-member-of-rcpt pers-no text-stat))))) ;;; ================================================================ ;;; Help (def-kom-command kom-help (&optional section) "Run the built-in help system." (interactive) (let* ((alternatives (delq nil (mapcar (lambda (section) (unless (string= "" (elt section 1)) (cons (elt section 1) (elt section 0)))) lyskom-help-data))) (completion-ignore-case t) (section section)) (while (null section) (setq section (lyskom-string-assoc (lyskom-completing-read (lyskom-get-string 'help-with-what) alternatives nil t nil 'lyskom-help-history) alternatives))) (lyskom-format-insert 'help-for (car section)) (lyskom-help-show-section (cdr section)))) (def-kom-command kom-make-review-mark-as-read () "Makes all review commands mark texts as read. Overrides the value of the configurable variable `kom-review-marks-texts-as-read' in the current buffer." (interactive) (setq kom-review-marks-texts-as-read t)) (def-kom-command kom-make-review-not-mark-as-read () "Makes all review commands not mark texts as read. Overrides the value of the configurable variable `kom-review-marks-texts-as-read' in the current buffer." (interactive) (setq kom-review-marks-texts-as-read nil)) ;;; ================================================================ ;;; Jämför två texter - Compare two texts ;;; Run ediff-buffers on two texts. ;;; Author: Per Cederqvist (defun lyskom-create-text-buffer (text-no text text-stat) "Create and return a buffer containing TEXT." (let ((buf (generate-new-buffer (format "%d" text-no)))) (set-buffer buf) (insert (text->decoded-text-mass text text-stat)) ;; Add a terminating newline. Ediff works better that way, and it ;; should not harm any other applications of this function. (insert "\n") (set-buffer-modified-p nil) buf)) (defvar diff-command) (defvar ediff-diff-program) (def-kom-command kom-compare-texts (old new) "Show differences between two texts, OLD and NEW. When called interactively, it will prompt for the NEW text first, defaulting to the last viewed texts. The OLD text number will default to the first text that NEW is a comment or footnote to. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg') for the NEW text." (interactive (let* ((n (lyskom-read-text-no-prefix-arg 'diff-what-text-new)) (new-stat (blocking-do 'get-text-stat n)) (o (lyskom-read-number 'diff-what-text-old (if (null new-stat) (lyskom-error (lyskom-get-string 'no-such-text-no n)) (car (lyskom-text-stat-commented-texts new-stat)))))) (list o n))) (blocking-do-multiple ((old-text (get-text old)) (new-text (get-text new)) (old-text-stat (get-text-stat old)) (new-text-stat (get-text-stat new))) (cond ((or (null old-text) (null old-text-stat)) (lyskom-format-insert 'no-such-text-no old)) ((or (null new-text) (null new-text-stat)) (lyskom-format-insert 'no-such-text-no new)) (t (condition-case nil (ediff-buffers (lyskom-create-text-buffer old old-text old-text-stat) (lyskom-create-text-buffer new new-text new-text-stat)) (file-error (lyskom-error (lyskom-get-string 'external-program-missing) (cond ((boundp 'ediff-diff-program) ediff-diff-program) ((boundp 'diff-command) diff-command) (t "diff (gissningsvis)"))))))))) ;;; ================================================================ ;;; Se diff - View diff ;;; Run diff on two texts and insert the result. ;;; Author: Per Cederqvist (defun lyskom-create-temp-file (text-no text text-stat) "Create a temporary file containing TEXT, and return its file name." (let ((file (make-temp-file (format "kom-diff-%d." text-no))) (buf (lyskom-create-text-buffer text-no text text-stat))) (write-region (point-min) (point-max) file) (kill-buffer buf) file)) (defvar diff-command) (def-kom-command kom-diff-texts (old new &optional switches) "Show differences between two texts, OLD and NEW. When called interactively, it will prompt for the NEW text first, defaulting to the last viewed texts. The OLD text number will default to the first text that NEW is a comment or footnote to. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg') for the NEW text." (interactive (let* ((n (lyskom-read-text-no-prefix-arg 'diff-what-text-new)) (new-stat (blocking-do 'get-text-stat n)) (o (lyskom-read-number 'diff-what-text-old (if (null new-stat) (lyskom-error (lyskom-get-string 'no-such-text-no n)) (car (lyskom-text-stat-commented-texts new-stat)))))) (list o n (if current-prefix-arg (list (read-string "Diff switches: " (if (stringp diff-switches) diff-switches (mapconcat 'identity diff-switches " ")))) nil)))) (blocking-do-multiple ((old-text (get-text old)) (new-text (get-text new)) (old-text-stat (get-text-stat old)) (new-text-stat (get-text-stat new))) (cond ((or (null old-text) (null old-text-stat)) (lyskom-format-insert 'no-such-text-no old)) ((or (null new-text) (null new-text-stat)) (lyskom-format-insert 'no-such-text-no new)) (t (let* ((buf (current-buffer)) (oldfile (lyskom-create-temp-file old old-text old-text-stat)) (newfile (lyskom-create-temp-file new new-text new-text-stat)) (args (list "-L" (format "%d\t%s" old (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm-ss (text-stat->creation-time old-text-stat))) "-L" (format "%d\t%s" new (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm-ss (text-stat->creation-time new-text-stat))) oldfile newfile))) (if switches (setq args (append (lyskom-split-string (if (consp switches) (mapconcat 'identity switches " ") switches)) args)) (if diff-switches (setq args (append (lyskom-split-string (if (consp diff-switches) (mapconcat 'identity diff-switches " ") diff-switches)) args)))) (set-buffer buf) (let ((buffer-read-only nil)) (apply 'call-process (if (boundp 'diff-command) diff-command "diff") nil buf nil args)) (delete-file oldfile) (delete-file newfile)))))) ;;; ================================================================ ;;; Skapa aux-item (def-kom-command kom-create-aux-item () "Creates arbitrary aux-items. This command is primarily targeted at advanced users and developers who want access to aux-item-based features before they are implemented properly in the client." (interactive) (let* ((completions (mapcar (lambda (x) (cons (lyskom-get-string x) x)) '(server conference text))) (completion-ignore-case t) (object-type (cdr (lyskom-string-assoc (lyskom-completing-read (lyskom-get-string 'what-kind-to-add-aux-to) completions nil t) completions))) (object-id (cond ((eq object-type 'server) nil) ((eq object-type 'conference) (lyskom-read-conf-no 'which-conf-to-add-aux-to '(pers conf) nil nil t)) ((eq object-type 'text) (lyskom-read-number 'which-text-to-add-aux-to (if (and lyskom-current-text (not (zerop lyskom-current-text))) lyskom-current-text nil))))) (tag (lyskom-read-number 'which-aux-item-tag)) (inherit (lyskom-j-or-n-p 'which-aux-item-inherit)) (secret (lyskom-j-or-n-p 'which-aux-item-secret)) (anonymous (lyskom-j-or-n-p 'which-aux-item-anonymous)) (rsv1 (lyskom-j-or-n-p 'which-aux-item-rsv1)) (rsv2 (lyskom-j-or-n-p 'which-aux-item-rsv2)) (rsv3 (lyskom-j-or-n-p 'which-aux-item-rsv3)) (rsv4 (lyskom-j-or-n-p 'which-aux-item-rsv4)) (inherit-limit (lyskom-read-number 'which-aux-item-inherit-limit)) (data (lyskom-read-string (lyskom-get-string 'which-aux-item-data))) (flags (lyskom-create-aux-item-flags nil inherit secret anonymous rsv1 rsv2 rsv3 rsv4)) (item (lyskom-create-aux-item 0 tag 0 0 flags inherit-limit data))) (lyskom-report-command-answer (cond ((eq object-type 'server) (blocking-do 'modify-server-info nil (list item))) ((eq object-type 'conference) (progn (cache-del-conf-stat object-id) (blocking-do 'modify-conf-info object-id nil (list item)))) ((eq object-type 'text) (progn (cache-del-text-stat object-id) (blocking-do 'modify-text-info object-id nil (list item)))))) (when (eq object-type 'server) (setq lyskom-server-info (blocking-do 'get-server-info))))) ;;; ================================================================ ;;; Status för LysKOM ;;; ;;; Skriv ut: ;;; * Serverns kanoniska namn (canonical-name eller ud kom-server-alist) ;;; * Serverns DNS-namn/IP och port ;;; * Serverns programvara och version ;;; * Högsta existerande inläggsnummer ;;; * Antal sessioner ;;; * Serverns tid ;;; (def-kom-command kom-status-server () "Show status information for the LysKOM server." (interactive) (blocking-do-multiple ((server-info (get-server-info)) (server-version (get-version-info)) (server-time (get-time)) (highest-text (find-previous-text-no lyskom-max-int)) (first-text (find-next-text-no 0)) (session-info (who-is-on-dynamic t t 0)) (stats-desc (get-stats-description)) (text-stats (get-stats "texts")) (conf-stats (get-stats "confs")) (pers-stats (get-stats "persons")) (boottime-info (get-boottime-info))) (setq lyskom-server-info (blocking-do 'get-server-info)) (setq lyskom-server-version-info (blocking-do 'get-version-info)) (let* ((aux-items (server-info->aux-item-list lyskom-server-info)) (canonical-name-aux (car (lyskom-get-aux-item aux-items 31))) (invisible-sessions 0) (anonymous-sessions 0) (active-sessions 0) (inactive-sessions 0) (unknown-activity-sessions 0) (total-sessions (length session-info)) (idle-hide (* 60 (if (numberp kom-idle-hide) kom-idle-hide 30))) (kom-extended-status-information (lyskom-extended-status-override 'server)) momentary-index periodic-index) (setq aux-items (delq canonical-name-aux aux-items)) ;; Compute the index into statistics that represents the ;; momentary value (when equals zero) and the periodic ;; value (when is at least five minutes). (when stats-desc (let ((min-time (apply 'min (listify-vector (stats-description->when stats-desc)))) (max-time (apply 'max (listify-vector (stats-description->when stats-desc)))) (i 0) (min-diff lyskom-max-int) max-time-index) (lyskom-traverse val (stats-description->when stats-desc) (when (eq val min-time) (setq momentary-index i)) (when (eq val max-time) (setq max-time-index i)) (when (and (>= val 300) (< (- val 300) min-diff)) (setq min-diff (- val 300) periodic-index i)) (setq i (1+ i))) (unless periodic-index (setq periodic-index max-time-index)))) ;; ---------------------------------------- ;; Compute session statistics (lyskom-traverse session session-info ;; Record anonymity (when (zerop (dynamic-session-info->person session)) (setq anonymous-sessions (1+ anonymous-sessions))) ;; Record activity (if (session-flags->user_active_used (dynamic-session-info->flags session)) (if (> (dynamic-session-info->idle-time session) idle-hide) (setq inactive-sessions (1+ inactive-sessions)) (setq active-sessions (1+ active-sessions))) (setq unknown-activity-sessions (1+ unknown-activity-sessions))) ;; Record invisibility (when (session-flags->invisible (dynamic-session-info->flags session)) (setq invisible-sessions (1+ invisible-sessions))) ) ;; ---------------------------------------- ;; Print header (lyskom-format-insert 'server-status-header (lyskom-session-nickname) lyskom-server-name lyskom-server-port) ;; ---------------------------------------- ;; Print software name and version (lyskom-format-insert 'server-status-version (version-info->server-software server-version) (version-info->software-version server-version)) (lyskom-format-insert 'server-status-protocol (version-info->protocol-version server-version)) ;; ---------------------------------------- ;; Print canonical name, if we have one (when canonical-name-aux (let ((canonical-name nil) (canonical-port nil)) (if (string-match ":" (aux-item->data canonical-name-aux)) (setq canonical-name (substring (aux-item->data canonical-name-aux) 0 (match-beginning 0)) canonical-port (substring (aux-item->data canonical-name-aux) (1+ (match-beginning 0)))) (setq canonical-name (aux-item->data canonical-name-aux))) (lyskom-format-insert 'server-status-server canonical-name canonical-port))) ;; ---------------------------------------- ;; Print start time and such (when boottime-info (lyskom-format-insert 'server-status-boot-time (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time (static-server-info->boot-time boottime-info)))) (lyskom-format-insert 'server-status-save-time (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time (static-server-info->save-time boottime-info))) (cond ((equal "clean" (static-server-info->db-status boottime-info)) nil) (t (condition-case nil (lyskom-get-string (intern (concat "db-status-" (static-server-info->db-status boottime-info)))) (error (static-server-info->db-status boottime-info)))))) ) ;; ---------------------------------------- ;; Print time (lyskom-format-insert 'server-status-time (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time server-time))) ;; ---------------------------------------- ;; Print session statistics (lyskom-format-insert 'server-status-sessions total-sessions active-sessions inactive-sessions unknown-activity-sessions invisible-sessions anonymous-sessions (/ idle-hide 60)) ;; ---------------------------------------- ;; Print stats for confs and persons (when pers-stats (lyskom-format-insert 'server-status-pers (stats->average (elt pers-stats momentary-index)) (lyskom-format-time-units (stats->ascent-rate (elt pers-stats periodic-index))) (static-server-info->existing-persons boottime-info))) (when conf-stats (lyskom-format-insert 'server-status-confs (stats->average (elt conf-stats momentary-index)) (lyskom-format-time-units (stats->ascent-rate (elt conf-stats periodic-index))) (static-server-info->existing-confs boottime-info))) ;; ---------------------------------------- ;; Print info on text numbers (when text-stats (lyskom-format-insert 'server-status-texts (stats->average (elt text-stats momentary-index)) (lyskom-format-time-units (stats->ascent-rate (elt text-stats periodic-index))) (static-server-info->existing-texts boottime-info))) (lyskom-format-insert 'server-status-first-text first-text) (lyskom-format-insert 'server-status-last-text highest-text (when boottime-info (static-server-info->highest-text-no boottime-info))) ;; ---------------------------------------- ;; Print remaining aux-items (lyskom-traverse-aux item aux-items (if (lyskom-aux-item-definition-field item 'status-print) (lyskom-aux-item-call item 'status-print item 'server) (lyskom-format-insert 'status-aux-item (format "%d/%d" (aux-item->aux-no item) (aux-item->tag item)) (aux-item->creator item) (lyskom-aux-item-terminating-button item 'server)) )) ;; ---------------------------------------- ;; Print statistics (when (lyskom-extended-status-information 'raw-server-stats) (let* ((stats (lyskom-get-server-stats)) (what (server-stats->what stats)) (maxlen (and stats (apply 'max (mapcar 'length what)))) (fmt (and maxlen (format "%%=%d#1s " maxlen)))) (when stats (lyskom-format-insert 'status-server-stats) (lyskom-insert (lyskom-format fmt "")) (lyskom-traverse period (server-stats->when stats) (lyskom-format-insert " %=8#1s" (if (eq 0 period) (lyskom-get-string 'current-average) (lyskom-format-units period '((604800 . "w") (86400 . "d") (3600 . "h") (60 . "m")) "s")))) (lyskom-insert "\n") (lyskom-traverse item (server-stats->values stats) (let ((start (point-max)) (inhibit-read-only t)) (lyskom-format-insert fmt (car item)) (lyskom-traverse val (cdr item) (lyskom-format-insert " %=8.2.7#1f" (stats->average val))) (lyskom-format-insert "\n") (add-text-properties start (point-max) `(face ,kom-mark-face))) (lyskom-format-insert fmt "") (lyskom-insert " ") (let ((index 0)) (lyskom-traverse val (cdr item) (if (eq (elt (server-stats->when stats) index) 0) (lyskom-insert " ") (lyskom-format-insert " %=8.2.7#1f+" (stats->ascent-rate val))) (setq index (1+ index)))) (lyskom-format-insert "\n") (lyskom-format-insert fmt "") (lyskom-insert " ") (let ((index 0)) (lyskom-traverse val (cdr item) (if (eq (elt (server-stats->when stats) index) 0) (lyskom-insert " ") (lyskom-format-insert " %=8.2.7#1f-" (stats->descent-rate val))) (setq index (1+ index)))) (lyskom-format-insert "\n") )))) ;; ---------------------------------------- ;; Print MOTD (if there is one) (when (not (zerop (server-info->motd-of-lyskom server-info))) (lyskom-insert 'server-status-has-motd) (lyskom-view-text (server-info->motd-of-lyskom server-info))) ))) ;;; ================================================================ ;;; Rekommendera möte (def-kom-command kom-recommend-conference () "Recommend a conference to new LysKOM users. Thie command can only be used if you have administrative rights to the LysKOM server." (interactive) (let* ((conf-stat (lyskom-read-conf-stat 'recommend-which-conf '(conf) nil nil t)) (priority (and (lyskom-j-or-n-p 'recommend-set-priority-q) (lyskom-read-num-range 0 255 'priority-q))) (mship-type (and priority (lyskom-j-or-n-p 'recommend-set-mship-type-q) (lyskom-read-membership-type))) (aux-item (lyskom-create-aux-item 0 29 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (mapconcat 'lyskom-format-object (delq nil (list (conf-stat->conf-no conf-stat) priority mship-type)) " ")))) (lyskom-format-insert 'recommending-conf conf-stat priority (and mship-type (lyskom-return-membership-type mship-type))) (lyskom-report-command-answer (blocking-do 'modify-server-info nil (list aux-item))))) ;;; ================================================================ ;;; Add send-comments-to ;;; (def-kom-command kom-redirect-comments () "Add extended information to your letterbox that causes some other conference to be added as a recipient to comments to your texts when someone posts them to a conference you are not a member of. Note that this is advisory only; clients may ignore your redirection." (interactive) (let* ((conf-stat (lyskom-read-conf-stat 'redirect-for-whom '(pers) nil nil t)) (redirect-to (lyskom-read-conf-stat 'redirect-to-which-conf '(pers conf) nil nil t)) (old-redirect (car (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 33)))) (lyskom-format-insert 'redirecting-comments-to conf-stat redirect-to old-redirect) (lyskom-report-command-answer (blocking-do 'modify-conf-info (conf-stat->conf-no conf-stat) (and old-redirect (list (aux-item->aux-no old-redirect))) (list (lyskom-create-aux-item 0 33 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (format "%d" (conf-stat->conf-no redirect-to))))) nil '((illegal-aux-item . kom-redirect-comments-e48) (aux-item-permission . kom-redirect-comments-e48)))) ) ;;; ================================================================ ;;; Kamikaze functions! (def-kom-command kom-join-all-conferences () "Join all conferences. You want to be really careful doing this. It will take a while and is probably not what you really want to do." (interactive) (let* ((conf-nos (lyskom-get-all-conferences t)) (confirm-each (or (lyskom-j-or-n-p 'confirm-each-join) (not (lyskom-j-or-n-p (lyskom-format 'no-confirm-each-sure (length conf-nos)))))) (mship-type (unless (lyskom-j-or-n-p 'confirm-each-msg) (lyskom-create-membership-type nil nil nil (lyskom-j-or-n-p 'receive-each-msg) nil nil nil nil))) (no-of-unread (lyskom-read-num-range-or-date 0 lyskom-max-int (lyskom-format 'initial-unread) nil t nil)) (kom-membership-default-priority (lyskom-read-num-range 0 255 (lyskom-get-string 'priority-q) nil nil))) (while conf-nos (unless (or (lyskom-get-membership (car conf-nos) t) (and confirm-each (not (lyskom-j-or-n-p (lyskom-format 'confirm-join (car conf-nos)))))) (lyskom-add-member-by-no (car conf-nos) lyskom-pers-no no-of-unread mship-type) (sit-for 0)) (setq conf-nos (cdr conf-nos))))) (def-kom-command kom-leave-all-conferences () "Leave all conferences. This command will ignore certain conferences. It will not leave your letterbox, secret or closed conferences without confirmation. Note that this command could take a very long time to complete." (interactive) (let* ((auto-regular nil) (auto-secret nil) (auto-closed nil) (confs nil)) (lyskom-message (lyskom-get-string 'getting-all-confs)) (let* ((xlist (lyskom-get-all-conferences)) (count (length xlist)) (index 0)) (setq confs (delq nil (mapcar (lambda (conf-no) (setq index (1+ index)) (lyskom-message (lyskom-format 'getting-all-confs-progress index count)) (when (or (lyskom-try-get-membership conf-no t) (lyskom-is-member conf-no lyskom-pers-no)) conf-no)) xlist))) (lyskom-message (lyskom-get-string 'getting-all-confs-done))) (while confs (let* ((conf (car confs)) (conf-stat (blocking-do 'get-conf-stat conf)) (conf-type (conf-stat->conf-type conf-stat))) (setq lyskom-last-viewed (point-max)) (lyskom-format-insert 'unsubscribe-to-2 conf-stat (lyskom-conf-type-marker conf-stat)) (when (cond ;; Won't auto-unsub letterbox ((= (conf-stat->conf-no conf-stat) lyskom-pers-no) (lyskom-insert (lyskom-get-string 'unsub-all-skipping-letterbox)) nil) ;; Won't unsub if we are supervisor ((lyskom-i-am-supervisor conf-stat t) (lyskom-insert-string 'unsub-all-skipping-supervised) nil) ;; Check secret conferences ((conf-type->secret conf-type) (if auto-secret t (let ((ans (lyskom-a-or-b-or-c-p (lyskom-format 'unsub-secret-conf-q conf-stat) '(abc-yes abc-no unsub-all-secret) 'abc-no))) (cond ((eq ans 'abc-no) (lyskom-insert-string 'cancelled) nil) ((eq ans 'abc-yes) t) ((eq ans 'unsub-all-secret) (setq auto-secret t) t))))) ;; Skip closed only if doit is ((conf-type->rd_prot conf-type) (if auto-closed t (let ((ans (lyskom-a-or-b-or-c-p (lyskom-format 'unsub-closed-conf-q conf-stat) '(abc-yes abc-no unsub-all-closed) 'abc-no))) (cond ((eq ans 'abc-no) (lyskom-insert-string 'cancelled) nil) ((eq ans 'abc-yes) t) ((eq ans 'unsub-all-closed) (setq auto-closed t) t))))) ;; Regular conference (t (if auto-regular t (let ((ans (lyskom-a-or-b-or-c-p (lyskom-format 'unsub-open-conf-q conf-stat) '(abc-yes abc-no unsub-all-open) 'abc-no))) (cond ((eq ans 'abc-no) (lyskom-insert-string 'cancelled) nil) ((eq ans 'abc-yes) t) ((eq ans 'unsub-all-open) (setq auto-regular t) t)))))) ;; How's that for a really long condition? Lots of ;; cool side effects and user interactions. Don't ;; you just love functional programming? ;; Now we've either printed a message or we've ;; decided to unsubscribe. (lyskom-sub-member (blocking-do 'get-conf-stat lyskom-pers-no) conf-stat t) )) (sit-for 0) (setq confs (cdr confs))) )) (def-kom-command kom-limit-import (conf-stat) "Specify restrictions on importing e-mail. Note that such restrictions are advisory; clients may ignore them." (interactive (list (lyskom-read-conf-stat 'limit-import-to-conf '(conf pers) nil nil t))) (when conf-stat (let* ((what (lyskom-a-or-b-or-c-p 'limit-import-of-what '(abc-spam abc-html abc-everything) 'abc-spam)) (data (cond ((eq what 'abc-spam) "spam") ((eq what 'abc-html) "html") ((eq what 'abc-everything) "all")))) (when (or (lyskom-is-supervisor (conf-stat->conf-no conf-stat) lyskom-pers-no) (lyskom-j-or-n-p 'limit-import-not-super)) (when data (lyskom-format-insert 'limiting-import (substring (lyskom-get-string what) 1) conf-stat) (lyskom-report-command-answer (blocking-do 'modify-conf-info (conf-stat->conf-no conf-stat) nil (list (lyskom-create-aux-item 0 35 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 data)))) (cache-del-conf-stat (conf-stat->conf-no conf-stat))))))) (def-kom-command kom-change-message-flag (uconf-stat) "Specify whether to receive group messages to a particular conference." (interactive (list (lyskom-read-uconf-stat 'set-message-flag-for-conf '(membership) nil lyskom-current-conf t))) (when uconf-stat (let* ((mship (lyskom-get-membership (uconf-stat->conf-no uconf-stat) t))) (if (null mship) (lyskom-format-insert 'not-member-of-conf uconf-stat) (set-membership-type->message-flag (membership->type mship) (lyskom-j-or-n-p (lyskom-format 'set-message-flag-to-what uconf-stat))) (lyskom-format-insert 'setting-message-flag (membership-type->message-flag (membership->type mship)) uconf-stat) (lyskom-report-command-answer (blocking-do 'set-membership-type lyskom-pers-no (uconf-stat->conf-no uconf-stat) (membership->type mship))) (lp--update-buffer (uconf-stat->conf-no uconf-stat)))))) (def-kom-command kom-list-new-conferences (arg) "List conferences created since the last time this command was given. With prefix argument, prompt for a date to start at." (interactive "P") (lyskom-list-new-conferences 'lyskom-last-known-conf-no 'conferences (lambda (el) (not (conf-type->letterbox (conf-stat->conf-type el)))) arg)) (def-kom-command kom-list-new-persons (arg) "List persons created since the last time this command was given. With prefix argument, prompt for a date to start at." (interactive "P") (lyskom-list-new-conferences 'lyskom-last-known-pers-no 'persons (lambda (el) (conf-type->letterbox (conf-stat->conf-type el))) arg)) (defun lyskom-list-new-conferences (varsym obj filter &optional list-from-date) "List conferences created since a particular point in history. VARSYM is the name of a variable that should be bound to a cons of the last conference number displayed and the date when it was displayed \(lyskom-time structure). OBJ is the type of object. It should be a symbol that can be passed to lyskom-get-string to get a text representation of the object type. FILTER is a function called on each conference. It should return non-nil for conferences that should be displayed. If optional LIST-FROM-DATE is non-nil, prompt for a date and list all conferences from that date forward." (interactive) (let* ((last-conf-no (blocking-do 'first-unused-conf-no)) (var (or (and (null list-from-date) (symbol-value varsym)) (let* ((n (lyskom-read-date (lyskom-format 'list-confs-from-date (lyskom-get-string obj)) t)) (date (and n (lyskom-create-time 0 0 0 (elt n 2) (elt n 1) (elt n 0) 0 0 nil))) (conf (and n (lyskom-find-conf-by-date date)))) (cond ;; No date -- we want it all! ((null n) (cons 1 nil)) ;; Date but no conf -- no confs to list! ((null conf) (cons last-conf-no date)) ;; Date and conf -- list from this conf (t (cons (conf-stat->conf-no conf) date)))))) (conf-no (car var)) (time-string (condition-case nil (and (cdr var) (lyskom-format-time 'date-and-time (cdr var))) (error nil)))) (if (null last-conf-no) (lyskom-format-insert 'no-support-in-server)) ;; There's a serious bug here: we can't cancel! ;; That *has* to be fixed. (let ((count (cons 0 (make-marker))) (calls nil)) (condition-case nil (progn (while (< conf-no last-conf-no) (setq calls (cons (initiate-get-conf-stat 'main (lambda (conf filter count time-string) (when (and conf (funcall filter conf)) (when (eq (car count) 0) (lyskom-format-insert 'new-conferences-since time-string (lyskom-get-string obj))) (rplaca count (1+ (car count))) (lyskom-format-insert "%5#1m %#2c %#1M\n" conf (lyskom-list-conf-membership-char (conf-stat->conf-no conf))) (set-marker (cdr count) (point)))) conf-no filter count time-string) calls)) (setq conf-no (1+ conf-no))) (lyskom-wait-queue 'main)) (quit (lyskom-message (lyskom-get-string 'canceling-command)) (lyskom-cancel-calls calls) (signal 'quit nil))) (when (marker-position (cdr count)) (goto-char (cdr count))) (cond ((eq 0 (car count)) (lyskom-format-insert 'no-new-conferences time-string (lyskom-get-string obj))) (t (when (or kom-auto-confirm-new-conferences (lyskom-j-or-n-p (lyskom-format 'mark-confs-as-known (lyskom-get-string obj) (car count)))) (set varsym (cons conf-no (lyskom-current-client-time))) (lyskom-save-options lyskom-buffer nil nil nil))))))) (def-kom-command kom-change-privileges (&optional set-all) "Change privileges for a user. Using this command you can change all privileges for a user." (interactive "P") (let* ((uconf-stat (lyskom-read-uconf-stat 'what-pers-privs-to-change '(pers) nil "" t)) (pers-stat (blocking-do 'get-pers-stat (uconf-stat->conf-no uconf-stat))) (privs (pers-stat->privileges pers-stat))) (lyskom-format-insert 'change-pers-privs-prompt uconf-stat (lyskom-privilege-string privs nil "\n ")) (let* ((wheel (lyskom-j-or-n-p (lyskom-get-string 'set-wheel-priv-q))) (admin (lyskom-j-or-n-p (lyskom-get-string 'set-admin-priv-q))) (statistic (lyskom-j-or-n-p (lyskom-get-string 'set-statistic-priv-q))) (create-pers (lyskom-j-or-n-p (lyskom-get-string 'set-create-pers-priv-q))) (create-conf (lyskom-j-or-n-p (lyskom-get-string 'set-create-conf-priv-q))) (change-name (lyskom-j-or-n-p (lyskom-get-string 'set-change-name-priv-q))) (flg7 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg7-priv-q)) (privs->flg7 privs))) (flg8 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg8-priv-q)) (privs->flg8 privs))) (flg9 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg9-priv-q)) (privs->flg9 privs))) (flg10 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg10-priv-q)) (privs->flg10 privs))) (flg11 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg11-priv-q)) (privs->flg11 privs))) (flg12 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg12-priv-q)) (privs->flg12 privs))) (flg13 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg13-priv-q)) (privs->flg13 privs))) (flg14 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg14-priv-q)) (privs->flg14 privs))) (flg15 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg15-priv-q)) (privs->flg15 privs))) (flg16 (if set-all (lyskom-j-or-n-p (lyskom-get-string 'set-flg16-priv-q)) (privs->flg16 privs))) (new-privs (lyskom-create-privs wheel admin statistic create-pers create-conf change-name flg7 flg8 flg9 flg10 flg11 flg12 flg13 flg14 flg15 flg16))) (if (not (blocking-do 'set-priv-bits (pers-stat->pers-no pers-stat) new-privs)) (progn (lyskom-insert-string 'nope) (lyskom-insert-error)) (when (setq pers-stat (cache-get-pers-stat (pers-stat->pers-no pers-stat))) (set-pers-stat->privileges pers-stat new-privs)) (lyskom-insert-string 'done))))) ;;; ================================================================ ;;; Temporary function for when we moved kom-extended-command from a ;;; to x. (defun kom-obsolete-extended-command-binding () "Temporary function for when we moved kom-extended-command from a" (interactive) (lyskom-format-insert-before-prompt "\ %#1@---------------------------------------------------------------- Tangenten för inmatning av kommandon har flyttat från a till x. Använd x istället för a om du vill ange LysKOM-kommandon vid namn. För att undvika att du kör oönskade LysKOM-kommandon så ignoreras all inmatning tills du trycker enter nästa gång. Tryck på enter för att fortsätta. ---------------------------------------------------------------- " `(face ,kom-warning-face)) ;; Beep both visibly and audibly, if possible. We *want* to be annoying. (let ((visible-bell t)) (ding)) (let ((visible-bell nil)) (ding)) (read-from-minibuffer (lyskom-format "%#1@Tryck return eller enter för att gå vidare: " `(face ,kom-warning-face)))) (defun kom-obsolete-who-is-on-in-conference () "Temporary function for when we moved kom-who-is-on-in-conference from l v to v m" (interactive) (lyskom-insert-before-prompt "Kommandot \"Vilka (är inloggade i) möte\" är flyttat till v m\n")) (defun kom-apropos (re do-all) "List LysKOM-related symbols whose name or documentation matches a regexp. With prefix argument, also list symbols that are not part of the semi-stable interface (i.e. symbols whose name starts with \"lyskom\"). This command is intended primarily for developers and advanced users." (interactive "sLysKOM-apropos (regexp): \nP") (message "Searching for %s..." re) (let ((result nil) (case-fold-search t)) (mapatoms (lambda (atom) (when (and (or (boundp atom) (fboundp atom)) (or (and do-all (string-match "^lyskom-" (symbol-name atom))) (string-match "^kom-" (symbol-name atom))) (or (string-match re (symbol-name atom)) (and (fboundp atom) (string-match re (or (documentation atom) ""))) (and (boundp atom) (string-match re (or (documentation-property atom 'variable-documentation) ""))))) (setq result (cons atom result))))) (setq result (sort result (lambda (a b) (string-lessp (symbol-name a) (symbol-name b))))) (message "Searching for %s...formatting..." re) (if result (let ((buffer (get-buffer-create "*LysKOM-Apropos*"))) (save-window-excursion (let ((inhibit-read-only t)) (set-buffer buffer) (help-mode) (lyskom-view-mode) (erase-buffer) (insert "\ In this buffer, go to the name of the symbol and type * to get full documentation. ") (lyskom-traverse el result (lyskom-apropos-insert el)) (toggle-read-only 1)) (message "Searching for %s...formatting...done" re) (display-buffer buffer) (goto-char (point-min)))) (message "Nothing found that matches \"%s\"" re)))) (defun lyskom-apropos-insert (sym) (let ((start (point))) (insert (symbol-name sym)) (add-text-properties start (point) `(face bold mouse-face highlight lyskom-button t lyskom-button-text ,(symbol-name sym) lyskom-button-type func lyskom-buffer ,(current-buffer) lyskom-button-arg (lyskom-apropos-item ,sym))) (insert "\n") (lyskom-apropos-insert-docstring 'func sym (when (fboundp sym) (documentation sym))) (lyskom-apropos-insert-docstring 'var sym (when (boundp sym) (documentation-property sym 'variable-documentation))) (insert "\n"))) (defun lyskom-apropos-insert-docstring (type sym doc) (when doc (insert " ") (let ((start (point))) (cond ((eq type 'func) (insert "Func: ")) ((eq type 'var) (insert "Var: "))) (when (not (eq start (point))) (add-text-properties start (point) `(face italic mouse-face highlight lyskom-button t lyskom-button-text "" lyskom-button-type func lyskom-buffer ,(current-buffer) lyskom-button-arg (lyskom-apropos-item (,sym ,type))))) (insert (lyskom-truncate-string-to-width (if (string-match "\\(\r\\|\n\\)" doc) (substring doc 0 (string-match "\\(\r\\|\n\\)" doc)) doc) (- (window-width) 12))) (insert "\n")))) (defun lyskom-apropos-item (args) (let ((sym (elt args 0)) (type (elt args 1))) (cond ((eq type 'func) (describe-function sym)) ((eq type 'var) (describe-variable sym)) (t (cond ((fboundp sym) (describe-function sym)) ((boundp sym) (describe-variable sym))))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: review.el,v 44.63 2005/01/12 18:15:32 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: review.el ;;;; ;;;; This file contains functions to review articles in different ways. ;;;; Both the review commands themselves, the functions called by them ;;;; and the underlying functions are here. ;;;; ;;;; Most, if not all, of these functions are written by Linus Tolke. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: review.el,v 44.63 2005/01/12 18:15:32 byers Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) (put 'lyskom-cant-review-error 'error-conditions '(error lyskom-error lyskom-review-error)) (put 'lyskom-cant-review-error 'error-message "Can't review") (put 'lyskom-review-error 'error-condiions '(error lyskom-error)) (put 'lyskom-review-error 'error-message "Review error") ;;; ====================================================================== ;;; State-saving variables ;;; ;;; All these need to be buffer-local (def-kom-var lyskom-last-review-by nil local) (def-kom-var lyskom-last-review-to nil local) (def-kom-var lyskom-last-review-num nil local) (def-kom-var lyskom-last-review-pmark nil local) (def-kom-var lyskom-last-review-cmark nil local) (def-kom-var lyskom-last-review-saved-result-list nil local) (def-kom-var lyskom-last-review-saved-by-list nil local) (def-kom-var lyskom-last-review-saved-to-list nil local) (def-kom-var lyskom-last-review-saved-result-size 0 local) (def-kom-var lyskom-last-review-saved-smallest nil local) (def-kom-var lyskom-last-review-saved-largest nil local) (def-kom-var lyskom-have-review nil local) (def-kom-var lyskom-last-unread-by nil local) (def-kom-var lyskom-last-unread-to nil local) (def-kom-var lyskom-last-unread-num nil local) (def-kom-var lyskom-last-unread-pmark nil local) (def-kom-var lyskom-last-unread-cmark nil local) (def-kom-var lyskom-last-unread-saved-result-list nil local) (def-kom-var lyskom-last-unread-saved-by-list nil local) (def-kom-var lyskom-last-unread-saved-to-list nil local) (def-kom-var lyskom-last-unread-saved-result-size 0 local) (def-kom-var lyskom-last-unread-saved-smallest nil local) (def-kom-var lyskom-last-unread-saved-largest nil local) (def-kom-var lyskom-have-unread nil local) (defun lyskom-remove-zeroes (a) "Returns a copy of list where all zeroes are removed." (delq 0 (copy-sequence a))) ;;; ================================================================ ;;; Temoporary change of mark-as-read (defun kom-toggle-mark-as-read-prefix () "Read one key sequence and run one command with state of kom-review-marks-texts-as-read toggled." (interactive) (let* ((kom-review-marks-texts-as-read (not kom-review-marks-texts-as-read)) (sequence (read-key-sequence (format "%s: " (lyskom-get-string (if kom-review-marks-texts-as-read 'review-marking-as-read 'review-not-marking-as-read))))) (command (lookup-key (current-local-map) sequence))) (when (commandp command) (call-interactively command)))) (defun kom-toggle-cache-prefix () "Read one key sequence and run one command with state of kom-review-marks-texts-as-read toggled." (interactive) (let* ((kom-review-uses-cache (not kom-review-uses-cache)) (sequence (read-key-sequence (format "%s: " (lyskom-get-string (if kom-review-uses-cache 'review-using-cache 'review-not-using-cache))))) (command (lookup-key (current-local-map) sequence))) (when (commandp command) (call-interactively command)))) ;;; ================================================================ ;;; ]terse av, till - Review by X to Conference Y. ;;; Author: David Byers (def-kom-command kom-review-all () "Review all texts written by a particular author to a particular conference. This can also be accomplished by using `kom-review-by-to' and specifying zero texts. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive) (lyskom-tell-internat 'kom-tell-review) (lyskom-review-by-to 0)) (def-kom-command kom-unread-all () "Mark all texts written by a particular author to a particular conference as unread. This can also be accomplished by using `kom-unread-by-to' and specifying zero texts." (interactive) (lyskom-unread-by-to 0)) (def-kom-command kom-review-more (count) "Review more texts using the same critera as the last review performed with `kom-review-by-to'. The review will be resumed where the previous review finished. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive "P") (if (not lyskom-have-review) (lyskom-format-insert 'no-review-done) (let* ((count (or count (lyskom-read-number (lyskom-get-string 'review-how-many-more) (abs lyskom-last-review-num)))) (info (progn (if (and (listp count) (integerp (car count)) (null (cdr count))) (setq count (car count))) (cond ((zerop count) (setq count nil) (lyskom-get-string 'review-rest)) ((> count 0) (lyskom-format (lyskom-get-string 'review-more) count))))) (by lyskom-last-review-by) (to lyskom-last-review-to)) (lyskom-format-insert 'review-more-info-by-to info (if (zerop by) (lyskom-get-string 'anybody) by) (if (zerop to) (lyskom-get-string 'all-confs) to)) (condition-case arg (let ((list (lyskom-get-texts-by-to by to count t))) (setq lyskom-last-review-num (if (< lyskom-last-review-num 0) (- count) count)) (if list (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list list) nil t) t) (lyskom-insert-string 'no-such-text))) (lyskom-review-error (if arg nil (lyskom-insert-string 'no-such-text))))))) (def-kom-command kom-unread-more (count) "Mark more texts unread using the same critera as the last mark unread performed with `kom-unread-by-to'." (interactive "P") (if (not lyskom-have-unread) (lyskom-format-insert 'no-unread-done) (let* ((count (or count (lyskom-read-number (lyskom-get-string 'unread-how-many-more) (abs lyskom-last-unread-num)))) (info (progn (if (and (listp count) (integerp (car count)) (null (cdr count))) (setq count (car count))) (cond ((zerop count) (setq count nil) (lyskom-get-string 'unread-rest)) ((> count 0) (lyskom-format (lyskom-get-string 'unread-more) count))))) (by lyskom-last-unread-by) (to lyskom-last-unread-to)) (lyskom-format-insert 'unread-more-info-by-to info (if (zerop by) (lyskom-get-string 'anybody) by) (if (zerop to) (lyskom-get-string 'all-confs) to)) (condition-case arg (let ((list (lyskom-get-texts-by-to by to count t t))) (setq lyskom-last-unread-num (if (< lyskom-last-unread-num 0) (- count) count)) (if list (lyskom-traverse text-no list (unless (lyskom-mark-unread text-no) (lyskom-format-insert 'cant-mark-text-unread text-no (lyskom-get-error-text lyskom-errno)))) (lyskom-insert-string 'no-such-text))) (lyskom-review-error (if arg nil (lyskom-insert-string 'no-such-text))))))) (def-kom-command kom-review-first (&optional count) "Review the first N texts written by a particular author to some conference. With no author specified, review texts by all authors. With zero texts specified, review all text. With no conference specified, review texts to all conferences. With a negative number of texts, review the last N texts instead of the first (you can use `kom-review-by-to' instead. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive "P") (lyskom-tell-internat 'kom-tell-review) (lyskom-review-by-to (- (or count (lyskom-read-number (lyskom-get-string 'review-how-many) 1))))) (def-kom-command kom-unread-first (&optional count) "Mark the first N texts written by a particular author to some conference as unread. With no author specified, review texts by all authors. With zero texts specified, review all text. With no conference specified, review texts to all conferences. With a negative number of texts, review the last N texts instead of the first (you can use `kom-unread-by-to' instead." (interactive "P") (lyskom-unread-by-to (- (or count (lyskom-read-number (lyskom-get-string 'unread-how-many) 1))))) (def-kom-command kom-review-by-to (&optional count) "Review the last N texts written by a particular author to some conference. With no author specified, review texts by all authors. With zero texts specified, review all text. With no conference specified, review texts to all conferences. With a negative number of texts, review the last N texts instead of the first (you can use `kom-review-first' instead. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive "P") (lyskom-review-by-to (or count (lyskom-read-number (lyskom-get-string 'review-how-many) 1)))) (defun lyskom-review-by-to (count) "Common function for kom-review-by-to and kom-review-first" (let* ((info (progn (if (and (listp count) (integerp (car count)) (null (cdr count))) (setq count (car count))) (cond ((zerop count) (setq count nil) (lyskom-get-string 'everything)) ((> count 0) (lyskom-format 'latest-n count)) ((< count 0) (lyskom-format 'first-n (- count)))))) (by (lyskom-read-conf-no `(review-by-whom ,info) '(pers) t nil t)) (to (lyskom-read-conf-no `(review-to-conf ,info) '(all) t nil t))) (if (not (zerop to)) (cache-del-conf-stat to)) (if (not (zerop by)) (cache-del-pers-stat by)) (lyskom-format-insert 'review-info-by-to info (if (zerop by) (lyskom-get-string 'anybody) by) (if (zerop to) (lyskom-get-string 'all-confs) to)) (setq lyskom-last-review-by by) (setq lyskom-last-review-to to) (setq lyskom-last-review-num count) (setq lyskom-last-review-pmark nil) (setq lyskom-last-review-cmark nil) (setq lyskom-last-review-saved-result-list nil) (setq lyskom-last-review-saved-by-list nil) (setq lyskom-last-review-saved-to-list nil) (setq lyskom-last-review-saved-result-size 0) (setq lyskom-last-review-saved-smallest nil) (setq lyskom-last-review-saved-largest nil) (setq lyskom-have-review t) (condition-case arg (let ((list (lyskom-get-texts-by-to by to count))) (if list (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list list) nil t) t) (lyskom-insert-string 'no-such-text))) (lyskom-review-error (if arg nil (lyskom-insert-string 'no-such-text)))))) (def-kom-command kom-unread-by-to (&optional count) "Mark the last N texts written by a particular author to some conference as unread. With no author specified, review texts by all authors. With zero texts specified, review all text. With no conference specified, review texts to all conferences. With a negative number of texts, review the last N texts instead of the first (you can use `kom-unread-first' instead." (interactive "P") (lyskom-unread-by-to (or count (lyskom-read-number (lyskom-get-string 'unread-how-many) 1)))) (defun lyskom-unread-by-to (count) "Common function for kom-review-by-to and kom-review-first" (let* ((info (progn (if (and (listp count) (integerp (car count)) (null (cdr count))) (setq count (car count))) (cond ((zerop count) (setq count nil) (lyskom-get-string 'everything)) ((> count 0) (lyskom-format 'latest-n count)) ((< count 0) (lyskom-format 'first-n (- count)))))) (by (lyskom-read-conf-no `(unread-by-whom ,info) '(pers) t nil t)) (to (lyskom-read-conf-no `(unread-to-conf ,info) '(all) t nil t))) (if (not (zerop to)) (cache-del-conf-stat to)) (if (not (zerop by)) (cache-del-pers-stat by)) (lyskom-format-insert 'unread-info-by-to info (if (zerop by) (lyskom-get-string 'anybody) by) (if (zerop to) (lyskom-get-string 'all-confs) to)) (setq lyskom-last-unread-by by) (setq lyskom-last-unread-to to) (setq lyskom-last-unread-num count) (setq lyskom-last-unread-pmark nil) (setq lyskom-last-unread-cmark nil) (setq lyskom-last-unread-saved-result-list nil) (setq lyskom-last-unread-saved-by-list nil) (setq lyskom-last-unread-saved-to-list nil) (setq lyskom-last-unread-saved-result-size 0) (setq lyskom-last-unread-saved-smallest nil) (setq lyskom-last-unread-saved-largest nil) (setq lyskom-have-unread t) (condition-case arg (let ((list (lyskom-get-texts-by-to by to count nil t))) (if list (lyskom-traverse text-no list (unless (lyskom-mark-unread text-no) (lyskom-format-insert 'cant-mark-text-unread text-no (lyskom-get-error-text lyskom-errno)))) (lyskom-insert-string 'no-such-text))) (lyskom-review-error (if arg nil (lyskom-insert-string 'no-such-text)))))) ;;; ================================================================ ;;; lyskom-get-texts-by-to ;;; Author: David Byers ;;; ;;; Call lyskom-get-texts-by, lyskom-get-texts-to or ;;; lyskom-get-texts-by-and-to to get NUM texts by person ;;; BY to conference TO. ;;; (defun lyskom-get-texts-by-to (by to num &optional again do-unread) "Get NUM texts written by person number BY in conference number TO Args: BY TO NUM AGAIN DO-UNREAD" (cond ((and (zerop by) (zerop to)) (lyskom-get-texts-globally num again do-unread)) ((zerop to) (lyskom-get-texts-by by num again)) ((zerop by) (lyskom-get-texts-to to num again)) ((and (eq by lyskom-pers-no) (not (eq to by)) (let ((conf (blocking-do 'get-conf-stat to))) (and (conf-type->letterbox (conf-stat->conf-type conf)) (null (map->text-nos (blocking-do 'get-map (conf-stat->conf-no conf) (conf-stat->first-local-no conf) 1)))))) (lyskom-get-texts-by-generic by num (function (lambda (x to) (let ((found nil)) (lyskom-traverse misc (text-stat->misc-info-list x) (setq found (or found (and (memq (misc-info->type misc) lyskom-recpt-types-list) (eq (misc-info->recipient-no misc) to))))) found))) (list to) again)) (t (lyskom-get-texts-by-and-to by to num again)))) ;;; ============================================================ ;;; lyskom-check-review-access ;;; Author: David Byers ;;; ;;; Check that we can access the conference map. If we can't some ;;; review functions are just not much fun ;;; (defun lyskom-check-review-access (conf pers) "Check that we can review texts to CONF by PERS. CONF is a conf-stat or t if we know we can access that conference. PERS is a pers-stat or t if we know we can access that person. This function signals an error if review is impossible" (cond ((null conf) (lyskom-format-insert 'review-conf-gone) (signal 'lyskom-cant-review-error t)) ((null pers) (lyskom-format-insert 'review-pers-gone) (signal 'lyskom-cant-review-error t)) ((lyskom-conf-stat-p conf) (cond ((= 0 (conf-stat->no-of-texts conf)) (lyskom-format-insert 'review-cant-read-empty) (signal 'lyskom-cant-review-error t)) ((null (map->text-nos (blocking-do 'get-map (conf-stat->conf-no conf) (conf-stat->first-local-no conf) 1))) (if (conf-type->letterbox (conf-stat->conf-type conf)) (lyskom-format-insert 'review-cant-read-letterbox) (lyskom-format-insert 'review-cant-read-conf)) (signal 'lyskom-cant-review-error t)))))) ;;; ============================================================ ;;; lyskom-get-texts-globally ;;; Author: Per Cederquist, David Byers ;;; (defun lyskom-get-texts-globally (num &optional again do-unread) "Get the last NUM texts created in LysKOM. If AGAIN is non-nil, keep going from where we were before." (cond ((and again (null num)) (setq num lyskom-last-review-num)) ((and again (< lyskom-last-review-num 0)) (setq num (- num))) ((null num) (lyskom-format-insert (if do-unread 'cant-unread-everything 'cant-review-everything)) (signal 'lyskom-cant-review-error t))) (let ((result nil) (textno (cond (again lyskom-last-review-cmark) ((< num 0) 1) (t (lyskom-maxint)))) (op (if (< num 0) 'find-next-text-no 'find-previous-text-no))) (while (and (not (eq textno 0)) (not (null textno)) (< (length result) (abs num))) (setq textno (blocking-do op textno)) (if textno (setq result (cons textno result)))) (setq lyskom-last-review-cmark textno) (if (< num 0) (nreverse result) result))) ;;; ================================================================ ;;; lyskom-get-letters-to ;;; Author: David Byers ;;; ;;; Get letters by self that have a specified letterbox as ;;; recipient. Do this by linearly searching selfs letterbox ;;; map and look as every single doggone text-stat. What a drag. ;;; ;;; +++ FIXME: This is just get-texts-by right now. Need to filter stuff. ;;; (defun lyskom-get-letters-to (persno recipient num &optional again pstart) "Get NUM texts written by PERSNO. Args: persno num Cannot be called from a callback." (let ((persstat (blocking-do 'get-pers-stat persno))) (lyskom-check-review-access t persstat) (cond ((and again (null num)) (setq num lyskom-last-review-num)) ((and again (< lyskom-last-review-num 0)) (setq num (- num)))) (let* ((plow (or pstart (pers-stat->first-created-text persstat))) (phigh (1- (+ plow (pers-stat->no-of-created-texts persstat)))) (result (if again lyskom-last-review-saved-result-list nil)) (increment (if num (abs num))) (mark (cond (again lyskom-last-review-pmark) ((and num (< num 0)) plow) (t phigh))) (collector nil) (found nil) (start nil) (data nil)) (if (null num) (setq num (1+ phigh) mark phigh increment (1+ phigh))) (while (and (<= mark phigh) (>= mark plow) (> (abs num) (length result))) (setq increment (min lyskom-fetch-map-nos increment)) (setq start (if (< num 0) mark (- mark (1- increment)))) (if (< start 0) (progn (setq increment (- increment start)) (setq start 0))) (setq data (lyskom-remove-zeroes (listify-vector (map->text-nos (blocking-do 'get-created-texts persno start increment))))) (setq collector (make-collector)) (mapcar (function (lambda (x) (initiate-get-text-stat 'main (function (lambda (x collector pers-no) (if (and x (lyskom-is-recipient x pers-no)) (collector-push (text-stat->text-no x) collector)))) x collector recipient))) data) (lyskom-wait-queue 'main) (setq found (nreverse (collector->value collector))) (if (> num 0) (setq result (nconc found result) mark (- mark increment)) (setq result (nconc result found) mark (+ mark increment))) (if (null found) (setq increment (min lyskom-fetch-map-nos (* increment 2))) (setq increment (- (abs num) (length result))))) (setq lyskom-last-review-pmark mark) (if (> num 0) (progn (setq lyskom-last-review-saved-result-list (nfirst (- (length result) num) result)) (nthcdr (max 0 (- (length result) num)) result)) (progn (setq lyskom-last-review-saved-result-list (nthcdr (- num) result)) (nfirst (- num) result)))))) ;;; ================================================================ ;;; lyskom-get-texts-by-and-to ;;; Author: David Byers ;;; ;;; Note: We can't assume that the conference's map of texts is ;;; sorted. If we could, it would be possible to simplify this ;;; function considerably without making it slower. ;;; ;;; Problem: Construct part of the intersection between the user's ;;; created texts (the by-list) and the texts in a conference (the ;;; to-list) without bogging down the client, server or network and ;;; do it quickly! ;;; ;;; Idea: Construct the intersection incrementally without doing more ;;; work comparing things than we would if we had the full maps to ;;; start with. ;;; ;;; Solution: Get one segment of the by-list (call the nth segment ;;; by_n) and to-list (call the nth segment to_n) at a time until we ;;; are done or until both are exhausted. ;;; ;;; In each iteration do the following: Calculate the intersection ;;; between to_n with each of the previous by_i leaving r_n: ;;; r_n = \prod_{i=1}^{n-1} by_i \cap to_n ;;; where \prod denotes list concatenation. Next calculate the ;;; intersection of by_n with each to_i 0letterbox (conf-stat->conf-type confstat)) (and (conf-type->rd_prot (conf-stat->conf-type confstat)) (null (map->text-nos (blocking-do 'get-map (conf-stat->conf-no confstat) (conf-stat->first-local-no confstat) 1))))) (not (eq persno confno))) (lyskom-get-letters-to persno confno num again pstart)) ;; ;; General case ;; (t (lyskom-check-review-access confstat persstat) (cond ((and again (null num)) (setq num lyskom-last-review-num)) ((and again (< lyskom-last-review-num 0) (setq num (- num))))) (let* ((result-list (if again lyskom-last-review-saved-result-list nil)) (by-list (if again lyskom-last-review-saved-by-list nil)) (to-list (if again lyskom-last-review-saved-to-list nil)) (result-size (if again lyskom-last-review-saved-result-size 0)) (by nil) (to nil) (increment lyskom-fetch-map-nos) (plow (or pstart (pers-stat->first-created-text persstat))) (phigh (1- (+ plow (pers-stat->no-of-created-texts persstat)))) (pmark (cond (again lyskom-last-review-pmark) ((and num (< num 0)) plow) (t phigh))) (clow (or cstart (conf-stat->first-local-no confstat))) (chigh (1- (+ clow (conf-stat->no-of-texts confstat)))) (cmark (cond (again lyskom-last-review-cmark) ((and num (< num 0)) clow) (t chigh))) (smallest (if again lyskom-last-review-saved-smallest nil)) (largest (if again lyskom-last-review-saved-largest nil)) (abort-loop nil)) (if (null num) (setq num (1+ phigh))) (while (and (or (and (<= pmark phigh) (>= pmark plow)) (and (<= cmark chigh) (>= cmark clow))) (> (abs num) result-size) (not abort-loop)) (setq by (and (<= pmark phigh) (>= pmark plow) (lyskom-remove-zeroes (listify-vector (map->text-nos (blocking-do 'get-created-texts (pers-stat->pers-no persstat) (if (< num 0) pmark (max 0 (- pmark (1- increment)))) increment))))) to (and (<= cmark chigh) (>= cmark clow) (lyskom-remove-zeroes (listify-vector (map->text-nos (blocking-do 'get-map (conf-stat->conf-no confstat) (if (< num 0) cmark (max 0 (- cmark (1- increment)))) increment)))))) (if (> num 0) (if (and smallest by (> smallest (car by))) (setq abort-loop t)) (if (and largest by (< largest (car (nthcdr (1- (length by)) by)))) (setq abort-loop t))) ;; ;; Add intersection between new TO and old BYs ;; to the results list. ;; (setq result-list (cons (apply 'nconc (mapcar (function (lambda (x) (lyskom-intersection to x))) by-list)) result-list)) ;; ;; Add new BY and TO to the by-list and to-list ;; (setq by-list (cons by by-list) to-list (cons to to-list)) ;; ;; Add intersections between new BY and all TOs ;; (setq result-list (lyskom-mapcar2 (function (lambda (x y) (lyskom-intersection y (nconc x by)))) result-list to-list)) (setq result-size (apply '+ (mapcar 'length result-list))) ;; ;; Adjust the marks ;; (if (> num 0) (setq pmark (- pmark increment) cmark (- cmark increment)) (setq pmark (+ pmark increment) cmark (+ cmark increment))) ;; ;; If we have exhausted the conference, calculate smallest and ;; largest ;; (if (and (null smallest) (null largest) (or (> cmark chigh) (< cmark clow))) (setq smallest (apply 'min (mapcar (function (lambda (x) (if x (apply 'min x) (lyskom-maxint)))) to-list)) largest (apply 'max (mapcar (function (lambda (x) (if x (apply 'max x) -1))) to-list)))) ;; ;; This is the end of the while loop ;; ) (setq lyskom-last-review-pmark pmark) (setq lyskom-last-review-cmark cmark) (setq lyskom-last-review-saved-by-list by-list) (setq lyskom-last-review-saved-to-list to-list) (setq lyskom-last-review-saved-smallest smallest) (setq lyskom-last-review-saved-largest largest) ;; ;; Extract results ;; (setq result-list (apply 'nconc (if (< num 0) (nreverse result-list) result-list))) ;; ;; Save discarded results and return retained results ;; (if (> num 0) (progn (setq lyskom-last-review-saved-result-list (nfirst (- (length result-list) num) result-list)) (setq lyskom-last-review-saved-result-size (length lyskom-last-review-saved-result-list)) (setq lyskom-last-review-saved-result-list (cons lyskom-last-review-saved-result-list (make-list (- (length by-list) 1) nil))) (nthcdr (max 0 (- (length result-list) num)) result-list)) (progn (setq lyskom-last-review-saved-result-list (nthcdr (- num) result-list)) (setq lyskom-last-review-saved-result-size (length lyskom-last-review-saved-result-list)) (setq lyskom-last-review-saved-result-list (cons lyskom-last-review-saved-result-list (make-list (- (length by-list) 1) nil))) (nfirst (- num) result-list)))))))) ;;; =============================================================== ;;; lyskom-get-texts-by, lyskom-get-texts-to ;;; Author: David Byers ;;; ;;; These functions get data in chunks, starting with the number of ;;; texts requested. If they come up empty (which is common when ;;; scanning from the beginning of a map), the increment is ;;; exponentially increased up to a maximum of 150. ;;; ;;; lyskom-get-texts-by is also careful to filter out those texts that ;;; are not readable, hence the added complexity in that function. ;;; (defun lyskom-get-texts-by (persno num &optional again pstart) "Get NUM texts written by PERSNO. Args: persno num" (let* ((persstat (blocking-do 'get-pers-stat persno))) (lyskom-check-review-access t persstat) (lyskom-get-texts-by-generic persno num nil nil again pstart))) (defun lyskom-get-texts-by-generic (persno num pred args &optional again pstart) "Get NUM texts written by PERSNO. Args: persno num Cannot be called from a callback." (let* ((persstat (blocking-do 'get-pers-stat persno)) (user-area (pers-stat->user-area persstat))) (cond ((and again (null num)) (setq num lyskom-last-review-num)) ((and again (< lyskom-last-review-num 0)) (setq num (- num)))) (let* ((plow (or pstart (pers-stat->first-created-text persstat))) (phigh (1- (+ plow (pers-stat->no-of-created-texts persstat)))) (result (if again lyskom-last-review-saved-result-list nil)) (increment (if num (abs num))) (mark (cond (again lyskom-last-review-pmark) ((and num (< num 0)) plow) (t phigh))) (collector nil) (found nil) (start nil) (data nil)) (if (null num) (setq num (1+ phigh) mark phigh increment (1+ phigh))) (while (and (<= mark phigh) (>= mark plow) (> (abs num) (length result))) (setq increment (min lyskom-fetch-map-nos increment)) (setq start (if (< num 0) mark (- mark (1- increment)))) (if (< start 0) (progn (setq increment (- increment start)) (setq start 0))) (setq data (delq user-area (lyskom-remove-zeroes (listify-vector (map->text-nos (blocking-do 'get-created-texts persno start increment)))))) (setq collector (make-collector)) (mapcar (function (lambda (x) (initiate-get-text-stat 'main (function (lambda (x collector pred args) (when (and x (or (null pred) (apply pred x args))) (collector-push (text-stat->text-no x) collector)))) x collector pred args))) data) (lyskom-wait-queue 'main) (setq found (nreverse (collector->value collector))) (if (> num 0) (setq result (nconc found result) mark (- mark increment)) (setq result (nconc result found) mark (+ mark increment))) (if (null found) (setq increment (min lyskom-fetch-map-nos (* increment 2))) (setq increment (- (abs num) (length result))))) (setq lyskom-last-review-pmark mark) (if (> num 0) (progn (setq lyskom-last-review-saved-result-list (nfirst (- (length result) num) result)) (nthcdr (max 0 (- (length result) num)) result)) (progn (setq lyskom-last-review-saved-result-list (nthcdr (- num) result)) (nfirst (- num) result)))))) (defun lyskom-get-texts-to (confno num &optional again cstart) "From CONFNO get NUM texts." (let ((confstat (blocking-do 'get-conf-stat confno))) (lyskom-check-review-access confstat t) (cond ((and again (null num)) (setq num lyskom-last-review-num)) ((and again (< lyskom-last-review-num 0)) (setq num (- num)))) (let* ((clow (or cstart (conf-stat->first-local-no confstat))) (chigh (1- (+ clow (conf-stat->no-of-texts confstat)))) (result (if again lyskom-last-review-saved-result-list nil)) (start nil) (increment (and num (abs num))) (mark (cond (again lyskom-last-review-cmark) ((and num (< num 0)) clow) (t chigh)))) (if (null num) (setq num (1+ chigh) increment (1+ chigh) mark chigh)) (while (and (<= mark chigh) (>= mark clow) (> (abs num) (length result))) (setq increment (min lyskom-fetch-map-nos increment)) (setq start (if (< num 0) mark (- mark (1- increment)))) (if (< start 0) (progn (setq increment (- increment start)) (setq start 0))) (let ((found (lyskom-remove-zeroes (listify-vector (map->text-nos (blocking-do 'get-map confno start increment)))))) (if (> num 0) (setq result (nconc found result) mark (- mark increment) increment (- (abs num) (length result))) (setq result (nconc result found) mark (+ mark increment))) (if (null found) (setq increment (min lyskom-fetch-map-nos (* increment 2))) (setq increment (- (abs num) (length result)))))) (setq lyskom-last-review-cmark mark) (if (> num 0) (progn (setq lyskom-last-review-saved-result-list (nfirst (- (length result) num) result)) (nthcdr (max 0 (- (length result) num)) result)) (progn (setq lyskom-last-review-saved-result-list (nthcdr (- num) result)) (nfirst (- num) result)))))) ;;; ============================================================ ;;; Återse baklänges ;;; (def-kom-command kom-review-backward () "Toggles the reviewing order. If you are currently reviewing texts oldest to newest, review newest to oldest instead. When reviewing newest to oldest, change to oldest to newest. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive) (cond ((and (not (read-list-isempty lyskom-reading-list)) (memq (read-info->type (read-list->first lyskom-reading-list)) '(REVIEW REVIEW-MARK))) (let* ((info (read-list->first lyskom-reading-list)) (list (read-info->text-list info)) (texts (text-list->texts list)) (forward (read-info->forward info))) (set-text-list->texts list (nreverse texts)) (set-read-info->forward info (not forward)) (lyskom-format-insert 'you-review (lyskom-get-string (if (not forward) 'forward 'backward))))) (t (lyskom-insert-string 'illegal-command)))) ;;; ================================================================ ;;; ]terse tr{det - review tree ;;; Author: Linus Tolke (def-kom-command kom-review-tree (&optional text-no) "Recursively review all comments to the selected text. This command will descend recursively in the comment tree, as when reading texts normally. Unlike when reading normally, filters are not applied and circular structures are not dealt with gracefully. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-text-no-prefix-arg 'review-tree-q))) (lyskom-tell-internat 'kom-tell-review) (if text-no (progn (unless kom-review-uses-cache (cache-del-text-stat text-no)) (let ((ts (blocking-do 'get-text-stat text-no))) (lyskom-follow-comments ts nil 'review (lyskom-review-get-priority) t))) (lyskom-insert-string 'read-text-first))) (def-kom-command kom-unread-tree (text-no) "Recursively mark all comments to the selected text as unread. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-tree-q))) (lyskom-unread-tree text-no nil)) (defun lyskom-unread-tree (text-no visited-list) "Perform the function of kom-unread-tree." (let* ((text-stat (blocking-do 'get-text-stat text-no)) (worklist (and text-stat (lyskom-text-comments text-stat)))) (if (null (car worklist)) (lyskom-format-insert 'no-such-text-no text-no) (while worklist (let ((cur (car worklist))) (setq worklist (cdr worklist)) (unless (memq cur visited-list) (setq visited-list (cons cur visited-list) cur (blocking-do 'get-text-stat cur)) (when cur (when (delq nil (mapcar 'lyskom-get-membership (lyskom-text-recipients cur))) (lyskom-format-insert 'marking-text-unread (text-stat->text-no cur)) (lyskom-report-command-answer (lyskom-mark-unread (text-stat->text-no cur)))) (lyskom-traverse text-no (lyskom-text-comments cur) (unless (or (memq text-no visited-list) (memq text-no worklist) (setq worklist (cons text-no worklist))))))))))) visited-list) (def-kom-command kom-find-root (text-no) "Finds the root text of the tree containing the selected text. When there is more than one root, all will be included in a review operation. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-text-no-prefix-arg 'find-root-q))) (lyskom-tell-internat 'kom-tell-review) (cond (text-no (unless kom-review-uses-cache (cache-del-text-stat text-no)) (let* ((ts (blocking-do 'get-text-stat text-no)) (r (lyskom-find-root ts t))) (cond ((> (length r) 1) (lyskom-format-insert-before-prompt (lyskom-get-string 'more-than-one-root) ts) (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list r) nil t) t)) (r (unless kom-review-uses-cache (cache-del-text-stat (car r))) (lyskom-view-text (car r))) (t (lyskom-insert-string 'could-not-find-root))) ) ) (t (lyskom-insert-string 'confusion-what-to-find-root)))) (def-kom-command kom-unread-root (text-no) "Finds the root text of the tree containing the selected text and marks it as unread. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-root-q))) (if text-no (let* ((ts (blocking-do 'get-text-stat text-no)) (r (lyskom-find-root ts t))) (if r (lyskom-traverse text-no r (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no))) (lyskom-insert-string 'could-not-find-root))) (lyskom-insert-string 'confusion-what-to-unread-root))) (def-kom-command kom-find-root-review (text-no) "Finds the root of the comment tree containing the selected texts and then recursively reviews all its comments. For texts with a single root, this is equivalent to doing `kom-find-root' followed by `kom-review-tree'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-text-no-prefix-arg 'find-root-review-q))) (lyskom-tell-internat 'kom-tell-review) (cond (text-no (unless kom-review-uses-cache (cache-del-text-stat text-no)) (let* ((ts (blocking-do 'get-text-stat text-no)) (start (lyskom-find-root ts t))) (cond ((> (length start) 1) (lyskom-format-insert-before-prompt (lyskom-get-string 'more-than-one-root-review) ts) (lyskom-review-tree (car start))) (start (lyskom-review-tree (car start))) (t (lyskom-insert-string 'could-not-find-root))))) (t (lyskom-insert-string 'confusion-what-to-find-root-review)))) (def-kom-command kom-unread-root-review (text-no) "Finds the root of the comment tree containing the selected texts and then recursively marks all its comments as unread. For texts with a single root, this is equivalent to doing `kom-find-root' followed by `kom-unread-tree'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-root-review-q))) (if text-no (let* ((ts (blocking-do 'get-text-stat text-no)) (start (lyskom-find-root ts t)) (marked nil)) (lyskom-traverse text-no start (setq marked (lyskom-unread-tree text-no marked)))) (lyskom-insert-string 'confusion-what-to-unread-root-review))) (defun lyskom-find-root (text-stat &optional all) "Finds the root text of the tree containing the text TEXT-STAT. Args: TEXT-STAT &optional ALL If ALL is set, return a list of all root texts." (cond (text-stat (let ((queue (list text-stat)) (head nil) (misclist nil) (tmp nil) (seen nil) (result nil)) (while queue (setq head (car queue)) (setq queue (cdr queue)) (setq tmp nil) ;; ;; For each parent, add it to the queue ;; (setq misclist (text-stat->misc-info-list head)) (while misclist (cond ((eq (misc-info->type (car misclist)) 'COMM-TO) (if (memq (misc-info->comm-to (car misclist)) seen) (setq tmp (cons t tmp)) (unless kom-review-uses-cache (cache-del-text-stat (misc-info->comm-to (car misclist)))) (setq seen (cons (misc-info->comm-to (car misclist)) seen) tmp (cons (blocking-do 'get-text-stat (misc-info->comm-to (car misclist))) tmp)))) ((eq (misc-info->type (car misclist)) 'FOOTN-TO) (if (memq (misc-info->footn-to (car misclist)) seen) (setq tmp (cons t tmp)) (unless kom-review-uses-cache (cache-del-text-stat (misc-info->footn-to (car misclist)))) (setq seen (cons (misc-info->footn-to (car misclist)) seen) tmp (cons (blocking-do 'get-text-stat (misc-info->footn-to (car misclist))) tmp))))) (setq misclist (cdr misclist))) ;; ;; Remove unreadable texts ;; (setq tmp (delq nil tmp)) ;; ;; If no parents were found, this is is a top-level text ;; (when (null tmp) (setq result (cons head result)) (unless all (setq queue nil))) ;; ;; Remove "I visited this parent already" markers ;; (setq tmp (delq t tmp)) (setq queue (nconc tmp queue))) (if all (mapcar 'text-stat->text-no result) (text-stat->text-no (car result))))) (t nil))) (defun lyskom-review-tree (text) "Takes a TEXT as an arg, shows the text and the tree of all comments. Does a lyskom-end-of-command. Text is a text-no." (cond ((integerp text) (unless kom-review-uses-cache (cache-del-text-stat text)) (lyskom-view-text text nil t nil (lyskom-review-get-priority) t)) (t (signal 'lyskom-internal-error (list 'lyskom-review-tree "Called with incorrect argument." text))))) ;;; ================================================================ ;;; ]terse n{sta - review next ;;; Author: Linus Tolke (def-kom-command kom-review-next () "Resumes an interupted review by moving all suspended review entries to the front. This command may be less-than-useful depending on how review priorities are set, and the setting of `kom-higher-priority-breaks'. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive) (lyskom-tell-internat 'kom-tell-review) (let ((len (read-list-length lyskom-reading-list)) (finished nil)) (while (and (not finished) (> len 1)) (let ((type (read-info->type (read-list->first lyskom-reading-list)))) (if (and (not (eq type 'REVIEW)) (not (eq type 'REVIEW-TREE)) (not (eq type 'REVIEW-MARK))) (read-list-rotate lyskom-reading-list) (setq finished t))) (setq len (1- len))))) ;;; ================================================================ ;;; ]terse stacken - Review stack ;;; Author: Linus (def-kom-command kom-review-stack () "Displays a list of suspended review commands, and possibly regular read commands that have been suspended by reviewing. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive) (if (read-list->all-entries lyskom-reading-list) (mapcar (function (lambda (info) (let ((un (text-list->length (read-info->text-list info))) (type (read-info->type info)) (cto (read-info->comm-to info)) (conf (read-info->conf-stat info))) (cond ((eq type 'COMM-IN) (lyskom-format-insert 'view-many-comments cto un)) ((eq type 'CONF) (lyskom-format-insert 'view-texts-in-conf un conf)) ((eq type 'REVIEW) (lyskom-format-insert 'review-n-texts un)) ((eq type 'REVIEW-TREE) (lyskom-format-insert 'review-many-comments cto un)) ((eq type 'REVIEW-MARK) (lyskom-format-insert 'review-marked un)))))) (read-list->all-entries lyskom-reading-list)) (cond (lyskom-current-conf (lyskom-format-insert 'you-have-no-unreads lyskom-current-conf)) (t (lyskom-insert 'not-reading-anywhere))))) ;;; ================================================================ ;;; ]terse hoppa - review clear ;;; Author: Linus Tolke (def-kom-command kom-review-clear () "Cancel all active and suspended review commands. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive) (let ((found nil)) (if (not (read-list-isempty lyskom-reading-list)) (while (memq (read-info->type (read-list->first lyskom-reading-list)) lyskom-review-types-list) (set-read-list-del-first lyskom-reading-list) (setq found t))) (if (not (read-list-isempty lyskom-to-do-list)) (while (memq (read-info->type (read-list->first lyskom-to-do-list)) lyskom-review-types-list) (set-read-list-del-first lyskom-to-do-list) (setq found t))) (unless found (lyskom-insert 'not-reviewing)))) ;;; ================================================================ ;;; ]terse det kommenterade - View commented text ;;; Author: Inge Wallin (def-kom-command kom-review-comments (text-no) "Review all comments to the selected text. This command only reviews one level of comments. To see the entire comment tree, use `kom-review-tree' instead. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-text-no-prefix-arg 'review-comments-q))) (lyskom-tell-internat 'kom-tell-review) (cond (text-no (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-review-comments (blocking-do 'get-text-stat text-no))) (t (lyskom-insert-string 'read-text-first)))) (defun lyskom-review-comments (text-stat) "Handles the return from the initiate-get-text-stat, displays and builds list." (let* ((misc-info-list (and text-stat (text-stat->misc-info-list text-stat))) (misc-infos (and misc-info-list (append (lyskom-misc-infos-from-list 'FOOTN-IN misc-info-list) (lyskom-misc-infos-from-list 'COMM-IN misc-info-list)))) (all-text-nos (and misc-infos (mapcar (function (lambda (misc-info) (if (equal (misc-info->type misc-info) 'COMM-IN) (misc-info->comm-in misc-info) (misc-info->footn-in misc-info)))) misc-infos))) text-nos) ;; Only try to review texts that we can read. (while all-text-nos (unless kom-review-uses-cache (cache-del-text-stat (car all-text-nos))) (if (blocking-do 'get-text-stat (car all-text-nos)) (setq text-nos (cons (car all-text-nos) text-nos))) (setq all-text-nos (cdr all-text-nos))) (setq text-nos (nreverse text-nos)) (if text-nos (progn (lyskom-format-insert 'review-text-no (car text-nos)) (if (cdr text-nos) (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list (cdr text-nos)) lyskom-current-text) t)) ;; Don't check the no-cache thing here since we already ;; did earlier. We may end up slightly out of sync with ;; the server, but not so anyone will really notice. (lyskom-view-text (car text-nos))) (lyskom-insert-string 'no-such-text)))) (def-kom-command kom-review-cross-references (text-no) "Review all texts cross-referenced from the selected text. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg'). See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-text-no-prefix-arg 'review-xrefs-q))) (lyskom-tell-internat 'kom-tell-review) (cond (text-no (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-review-cross-references (blocking-do 'get-text-stat text-no))) (t (lyskom-insert-string 'read-text-first)))) (defun lyskom-cross-referenced-text (aux-item-xref) (and (string-match "^T\\([0-9]+\\)" (aux-item->data aux-item-xref)) (string-to-int (match-string 1 (aux-item->data aux-item-xref))))) (defun lyskom-review-cross-references (text-stat) "Handles the return from the initiate-get-text-stat, displays and builds list." (let* ((all-xrefs (lyskom-get-aux-item (text-stat->aux-items text-stat) 3)) (only-txts (mapcar 'lyskom-cross-referenced-text all-xrefs)) (to-review '())) ;; Only try to review texts that we can read. (while only-txts (when (car only-txts) (unless kom-review-uses-cache (cache-del-text-stat (car only-txts))) (when (blocking-do 'get-text-stat (car only-txts)) (setq to-review (cons (car only-txts) to-review)))) (setq only-txts (cdr only-txts))) (setq to-review (nreverse to-review)) (if to-review (progn (lyskom-format-insert 'review-text-no (car to-review)) (when (cdr to-review) (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list (cdr to-review)) lyskom-current-text) t)) ;; Don't check the no-cache thing here since we already ;; did earlier. We may end up slightly out of sync with ;; the server, but not so anyone will really notice. (lyskom-view-text (car to-review))) (lyskom-insert-string 'no-such-text)))) (def-kom-command kom-unread-comments (text-no) "Mark all comments to the selected text text as unread. This command only marks one level of comments as unread. To mark the entire comment tree unread, use `kom-unread-tree' instead. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-comments-q))) (cond (text-no (lyskom-unread-comments (blocking-do 'get-text-stat text-no))) (t (lyskom-insert-string 'read-text-first)))) (defun lyskom-unread-comments (text-stat) "Handles the return from the initiate-get-text-stat, displays and builds list." (let* ((misc-info-list (and text-stat (text-stat->misc-info-list text-stat))) (misc-infos (and misc-info-list (append (lyskom-misc-infos-from-list 'FOOTN-IN misc-info-list) (lyskom-misc-infos-from-list 'COMM-IN misc-info-list)))) (all-text-nos (and misc-infos (mapcar (lambda (misc-info) (if (equal (misc-info->type misc-info) 'COMM-IN) (misc-info->comm-in misc-info) (misc-info->footn-in misc-info))) misc-infos))) text-nos) ;; Only try to review texts that we can read. (while all-text-nos (if (blocking-do 'get-text-stat (car all-text-nos)) (setq text-nos (cons (car all-text-nos) text-nos))) (setq all-text-nos (cdr all-text-nos))) (setq text-nos (nreverse text-nos)) (if text-nos (lyskom-traverse text-no text-nos (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no))) (lyskom-insert-string 'no-such-text)))) ;;; ================================================================ ;;; ]terse igen - kom-review-last-normally-read ;;; ;;; Author: Linus Tolke (def-kom-command kom-review-last-normally-read (no) "Reviews the N texts most recently read using normal commands. After reviewing a number of texts, this will show the N texts read prior to that. See `kom-review-uses-cache', `kom-review-priority' and `kom-review-marks-texts-as-read' for information on settings that affect all review-related functions." (interactive (list (lyskom-read-number (lyskom-get-string 'read-normally-read) 1))) (lyskom-tell-internat 'kom-tell-review) (let* ((text-nos (nreverse (nfirst no lyskom-normally-read-texts)))) (if text-nos (progn (lyskom-format-insert 'review-text-no (car text-nos)) (if (cdr text-nos) (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW nil (lyskom-review-get-priority) (lyskom-create-text-list (cdr text-nos)) lyskom-current-text) t)) (unless kom-review-uses-cache (cache-del-text-stat (car text-nos))) (lyskom-view-text (car text-nos))) (lyskom-format-insert 'no-such-text)))) (def-kom-command kom-unread-last-normally-read (no) "Marks the N texts most recently read using normal commands unread. After marking a number of texts unread, this will mark the N texts read prior to that." (interactive (list (lyskom-read-number (lyskom-get-string 'read-normally-read) 1))) (let* ((text-nos (nreverse (nfirst no lyskom-normally-read-texts)))) (if text-nos (lyskom-traverse text-no text-nos (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no))) (lyskom-format-insert 'no-such-text)))) ;;; ============================================================ ;;; Återse omodifierat - Review a non-converted text ;;; Author: Linus Tolke ;;; Modified by: Johan Sundström (def-kom-command kom-review-noconversion (text-no) "Displays the selected text without any conversions or filtering \(i.e. no conversion of HTML, no automatic line breaks, all header lines etc). This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'review-noconversion-q))) (if text-no (let ((lyskom-format-special nil) (kom-smileys nil) (kom-show-footnotes-immediately nil) (kom-autowrap nil)) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-view-text text-no)) (lyskom-insert 'confusion-what-to-view))) ;;; ============================================================ ;;; Återse konverterat - Review a text converted (def-kom-command kom-review-converted (text-no) "Displays the selected text with all conversions enabled, even if some or all of them have are disabled by current settings. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'review-converted-q))) (if text-no (let ((kom-smileys t) (kom-autowrap t) (kom-format-html-authors '((t . t)))) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-view-text text-no)) (lyskom-insert 'confusion-what-to-view))) ;;; ============================================================ ;;; Återse rot13 - Review a text rot13:ed (def-kom-command kom-review-rot13 (text-no) "Displays the selected text rot13:ed. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'review-rot13-q))) (if text-no (let ((kom-view-text-hook kom-view-text-hook)) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (add-hook 'kom-view-text-hook 'lyskom-filter-rot13 nil t) (lyskom-view-text text-no) ) (lyskom-insert 'confusion-what-to-view))) (defun lyskom-review-get-priority () "Get the priority to use for reviewing texts." (or kom-review-priority (lyskom-get-current-priority))) (defun lyskom-review-enter-read-info (read-info before) "Enter READ-INFO into lyskom-reading-list and lyskom-to-do-list." (read-list-enter-read-info read-info lyskom-reading-list before) (read-list-enter-read-info read-info lyskom-to-do-list before)) ;;; ============================================================ ;;; Återse senaste dagarnas inlägg ;;; ;;; Author: Up for grabs ;;; ;;; Algorithm: ;;; ;;; Binärsökning i mappen efter inlägg med rätt datum. ;;; ;;; Utilityfunktioner: Beräkna diff i dagar mellan två datum. ;;; Subtrahera n dagar från ett datum. ;;; ;;; Användarkommandot: Återse N inlägg av person X till Y från DATE ;;; ;;; Hitta index i X och Y där det sökta datumet börjar ;;; Låt de vanliga återsefunktionerna accepter cmin och pmin som ;;; parametrar så de kan söka igenom en del av en map. ;;; ;;; Problem med binärsökning i mapparna är hålen. Det finns risk att ;;; man försöker binärsöka bland en massa nollor, och det lär ta tid. ;;; I de fallen får man nog göra get-next-text eller get-previous-text ;;; för att få ett riktigt textnummer att titta på. Risk: att man ;;; tittar på samma text två gånger och går i loop. ;;; ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: edit-text.el,v 44.119 2005/01/09 01:16:01 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: edit-text.el ;;;; ;;;; This file contains functions which lets the LysKOM user edit ;;;; a text in a window. It also defines a new mode - lyskom-edit-mode. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: edit-text.el,v 44.119 2005/01/09 01:16:01 byers Exp $\n")) ;;;; ================================================================ ;;; Set variables to make lyskom-edit-mode a minor mode. This ;;; simplifies some stuff a lot (defvar lyskom-edit-mode nil "Mode variable for lyskom-edit-mode") (make-variable-buffer-local 'lyskom-edit-mode) (defvar lyskom-edit-sending-mode nil "Mode variable for lyskom-edit-sending-mode") (make-variable-buffer-local 'lyskom-edit-sending-mode) (defvar lyskom-edit-sent-mode nil "Mode variable for lyskom-edit-sent-mode") (make-variable-buffer-local 'lyskom-edit-sent-mode) (put 'lyskom-edit-mode 'permanent-local t) (or (assq 'lyskom-edit-mode minor-mode-alist) (setq minor-mode-alist (cons '(lyskom-edit-mode " LysKOM Edit") minor-mode-alist))) (or (assq 'lyskom-edit-sending-mode minor-mode-alist) (setq minor-mode-alist (cons '(lyskom-edit-sending-mode " LysKOM Sending") minor-mode-alist))) (or (assq 'lyskom-edit-sent-mode minor-mode-alist) (setq minor-mode-alist (cons '(lyskom-edit-sent-mode " LysKOM Sent") minor-mode-alist))) (or (assq 'lyskom-edit-mode minor-mode-map-alist) (setq minor-mode-map-alist (cons (cons 'lyskom-edit-mode lyskom-edit-mode-map) minor-mode-map-alist))) (or (assq 'lyskom-edit-sending-mode minor-mode-map-alist) (setq minor-mode-map-alist (cons (cons 'lyskom-edit-sending-mode lyskom-edit-mode-map) minor-mode-map-alist))) (or (assq 'lyskom-edit-sent-mode minor-mode-map-alist) (setq minor-mode-map-alist (cons (cons 'lyskom-edit-sending-mode lyskom-edit-mode-map) minor-mode-map-alist))) (defvar lyskom-edit-mode-name "LysKOM edit" "Name of the mode.") (defvar lyskom-edit-text-sent nil "Non-nil when a text has been sent") (defvar lyskom-is-dedicated-edit-window nil "Status variable for an edit-window.") (defvar lyskom-edit-handler nil "Status variable for an edit-buffer. See lyskom-edit-handler-data.") (defvar lyskom-edit-handler-data nil "Status variable for an edit-buffer. See lyskom-edit-handler.") (defvar lyskom-edit-return-to-configuration nil "Status variable for an edit-buffer.") ;;; Error signaled by lyskom-edit-parse-headers (put 'lyskom-edit-text-abort 'error-conditions '(error lyskom-error lyskom-edit-error lyskom-edit-text-abort)) (put 'lyskom-unknown-header 'error-conditions '(error lyskom-error lyskom-edit-error lyskom-unknown-header)) (put 'lyskom-no-subject 'error-conditions '(error lyskom-error lyskom-edit-error lyskom-no-subject)) (put 'lyskom-edit-error 'error-conditions '(error lyskom-error lyskom-edit-error)) (defun lyskom-edit-text (proc misc-list subject body &optional handler &rest data) "Edit a text in a new buffer. PROC is the associated process. MISC-LIST is the default misc-list. SUBJECT is subject (a string). BODY is the default text-body (a string, normally empty.) HANDLER is a function to call when the text has been created. DATA is extra data to send to the function. HANDLER is called with (apply HANDLER text-no DATA) where text-no is the number of the text. Does lyskom-end-of-command." (setq lyskom-is-writing t) (lyskom-dispatch-edit-text proc misc-list subject body handler data)) (defun lyskom-dispatch-edit-text (proc misc-list subject body &optional handler &rest data) "Same as lyskom-edit-text except that it doesn't set lyskom-is-writing." (let ((buffer (lyskom-get-buffer-create 'write-texts (concat (buffer-name (process-buffer proc)) "-edit"))) (config (current-window-configuration))) (lyskom-display-buffer buffer) (text-mode) (lyskom-ignore-errors (run-hooks 'lyskom-edit-mode-mode-hook)) (lyskom-edit-mode) (make-local-variable 'lyskom-edit-handler) (make-local-variable 'lyskom-edit-handler-data) (make-local-variable 'lyskom-edit-return-to-configuration) (setq lyskom-edit-handler handler) (setq lyskom-edit-handler-data data) (setq lyskom-edit-return-to-configuration config) (buffer-disable-undo) (lyskom-edit-insert-miscs misc-list subject body) (buffer-enable-undo) (goto-char (point-min)) (re-search-forward (regexp-quote (lyskom-get-string 'header-subject)) (point-max) 'end) (if (not (looking-at "\\s-*$")) (goto-char (point-max))) (lyskom-message "%s" (lyskom-get-string 'press-C-c-C-c))) (set-buffer lyskom-buffer) ) (defun lyskom-edit-find-separator (&optional move-point) "Return the end position of the separator line. If MOVE-POINT is non-nil, move point to the start of the separator." (prog1 (save-excursion (goto-char (point-min)) (and (re-search-forward (concat "^" (regexp-quote (substitute-command-keys (lyskom-get-string 'header-separator))) "$") nil t))) (when (and move-point (match-beginning 0)) (goto-char (match-beginning 0))))) (defun lyskom-edit-insert-miscs (misc-list subject body &optional aux-list) "Insert MISC-LIST into header of text. RECPT -> Mottagare: <%d> %s. CC-RECPT -> Extra kopia: <%d> %s. BCC-RECPT -> Blind kopia: <%d> %s. COMM-TO -> Kommentar till text %d. FOOTN-TO -> Fotnot till text %d. nil -> Ingenting." (let ((edit-buffer (current-buffer)) (where-put-misc (point-min-marker)) (main-buffer lyskom-buffer)) (set-buffer main-buffer) (setq misc-list (cdr misc-list)) (while (not (null misc-list)) (let ((key (car (car misc-list))) (data (cdr (car misc-list)))) (cond ((eq key 'RECPT) (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data) (lyskom-get-string 'recipient) where-put-misc data)) ((eq key 'CC-RECPT) (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data) (lyskom-get-string 'carbon-copy) where-put-misc data)) ((eq key 'BCC-RECPT) (lyskom-edit-insert-misc-conf (blocking-do 'get-conf-stat data) (lyskom-get-string 'blank-carbon-copy) where-put-misc data)) ((eq key 'COMM-TO) (lyskom-edit-get-commented-author (blocking-do 'get-text-stat data) (lyskom-get-string 'comment) where-put-misc data)) ((eq key 'FOOTN-TO) (lyskom-edit-get-commented-author (blocking-do 'get-text-stat data) (lyskom-get-string 'footnote) where-put-misc data))) (setq misc-list (cdr misc-list)))) (mapcar (function (lambda (item) (let ((data (lyskom-aux-item-call item '(edit-insert print) item lyskom-pers-no))) (when data (lyskom-princ (lyskom-format "%#1@%[%#3s%] %#2s\n" (lyskom-default-button 'aux-edit-menu (cons edit-buffer (copy-marker where-put-misc))) data (lyskom-get-string 'aux-item-prefix)) where-put-misc))))) aux-list) (unless kom-edit-hide-add-button (lyskom-princ (lyskom-format "%[%#1@%#2s%]\n" (lyskom-default-button 'add-recipient-or-xref edit-buffer) (lyskom-get-string 'add-recpt-button-text)) where-put-misc)) (lyskom-princ (lyskom-format 'text-mass subject (substitute-command-keys (lyskom-get-string 'header-separator)) body (lyskom-get-string 'header-subject) '(read-only t) '(read-only t front-sticky nil start-open t rear-nonsticky nil end-open nil) '(read-only t rear-nonsticky t end-open t front-sticky t start-open nil) ) where-put-misc) (set-buffer edit-buffer) (goto-char where-put-misc) )) (defun lyskom-edit-insert-misc-conf (conf-stat string stream number) "Insert Recipient:, Carbon copy: or Blind Carbon copy: in edit-buffer. CONF-STAT is the conf-stat of the conference that is about to be put in, STRING is the string that is inserted. STREAM is the buffer or a marker telling the position. NUMBER is the number of the person. Used if the conf-stat is nil." (lyskom-princ (lyskom-format "%[%#1@%#2s%]: <%#3m> %#4M\n" (lyskom-default-button 'recpt-type (list (or (conf-stat->conf-no conf-stat) number) (marker-buffer stream)) (list (lyskom-get-string 'recpt-type-popup-title) string)) string (or conf-stat number) (or conf-stat "")) stream)) (defun lyskom-edit-get-commented-author (text-stat string stream number) (if text-stat (let ((mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16)))) (lyskom-edit-insert-commented-author (if (or mx-from mx-author) (lyskom-format-mx-author mx-from mx-author) (blocking-do 'get-conf-stat (text-stat->author text-stat))) string stream number)) (lyskom-edit-insert-commented-author nil string stream number))) (defun lyskom-edit-insert-commented-author (conf-stat string stream number) (lyskom-princ (lyskom-format 'comment-to-by string number (if conf-stat (lyskom-format 'by conf-stat) "")) stream)) (defun lyskom-create-misc-list (&rest misc-pairs) "Create a misc-list. Note that a misc-list is very different from a misc-info-list. A misc-list is used when creating a new text, and sent to the server. A misc-info-list is what is received from the server. Although the server has the same format for the two things, this client uses two quite different formats. The arguments to this function is any number of pairs of data. The first item in each pair should be one of RECPT, CC-RECPT, COMM-TO or FOOTN-TO. The second item should be the corresponding conf- or text-no. The result is a list of dotted pairs: ('RECPT . conf-no) ('CC-RECPT . conf-no) ('BCC-RECPT . conf-no) ('COMM-TO . text-no) ('FOOTN-TO . text-no). First element is a type-tag." (let ((result (cons 'MISC-LIST nil))) (while (not (null misc-pairs)) (nconc result (cons (cons (car misc-pairs) (car (cdr misc-pairs))) nil)) (setq misc-pairs (cdr (cdr misc-pairs)))) result)) ;;; ================================================================ ;;; lyskom-edit-mode (defvar lyskom-edit-mode-hook nil "*List of functions to be called when entering lyskom-edit-mode. Watch out! None of these functions are allowed to do kill-all-local-variables because kom-edit-send and other functions depend on some variables to be able to enter the text in the correct lyskom-process.") (defvar lyskom-edit-mode-mode-hook nil "*List of functions to be called when entering lyskom-edit-mode. Watch out! None of these functions are allowed to do kill-all-local-variables because kom-edit-send and other functions depend on some variables to be able to enter the text in the correct lyskom-process. This one differs from lyskom-edit-mode-hook in that it is called before the lyskom-special key bindings are added.") (defun lyskom-edit-mode (&optional arg) "\\Mode for editing texts for LysKOM. Commands: \\[kom-edit-send] sends the text when you are ready. The buffer will be deleted if (and only if) the server accepts the text. \\[kom-edit-quit] aborts the editing. You will get back to the LysKOM buffer. \\[kom-edit-show-commented] shows the commented text in a temporary buffer. \\[kom-edit-add-recipient] asks for another recipient and adds him to the header. \\[kom-edit-add-copy] as \\[kom-edit-add-recipient] but adds him as copy-recipient. \\[kom-edit-add-cross-reference] asks for what to refer to and adds a cross reference to it. \\[kom-edit-insert-commented] inserts the commented or footnoted text. \\[kom-edit-insert-text] inserts the shown text, you tell the number. \\[kom-edit-insert-link] asks for what to link to and inserts a link to it. Even though this is a minor mode, it's not intended to be turned on and off, so it's not as clean as it ought to be." (interactive "P") (setq lyskom-edit-mode (if (null arg) (not lyskom-edit-mode) (> (prefix-numeric-value arg) 0))) (lyskom-set-menus 'lyskom-edit-mode lyskom-edit-mode-map) (when lyskom-edit-mode (lyskom-edit-sending-mode 0) (lyskom-edit-sent-mode 0) (auto-fill-mode 1) (auto-save-mode 1) (when (not (local-variable-p 'lyskom-edit-text-sent (current-buffer))) (make-local-variable 'lyskom-edit-text-sent) (setq lyskom-edit-text-sent nil)) (make-local-variable 'paragraph-start) (make-local-variable 'paragraph-separate) (setq paragraph-start (concat "^" (regexp-quote (substitute-command-keys (lyskom-get-string 'header-separator))) "$\\|" paragraph-start)) (setq paragraph-separate (concat "^" (regexp-quote (substitute-command-keys (lyskom-get-string 'header-separator))) "$\\|" paragraph-separate)) (make-local-variable 'comment-start) (make-local-variable 'comment-end) (setq comment-start kom-cite-string comment-end "") (run-hooks 'lyskom-edit-mode-hook))) (defun lyskom-edit-sending-mode (arg) (interactive "P") (setq lyskom-edit-sending-mode (if (null arg) (not lyskom-edit-sending-mode) (> (prefix-numeric-value arg) 0))) (when lyskom-edit-sending-mode (lyskom-edit-mode 0) (lyskom-edit-sent-mode 0))) (defun lyskom-edit-sent-mode (arg) (interactive "P") (setq lyskom-edit-sent-mode (if (null arg) (not lyskom-edit-sent-mode) (> (prefix-numeric-value arg) 0))) (when lyskom-edit-sent-mode (lyskom-edit-sending-mode 0) (lyskom-edit-mode 0))) ;;; ================================================================ ;;; Functions bound to keyboard seqences in lyskom-edit-mode ;;; (defun kom-edit-send-anonymous () "Send the text anonymously to the server. Be aware that although the text will be truly anonymous, it is easy to slip up in such a way that the author is evident anyway." (interactive) (lyskom-edit-send 'initiate-create-anonymous-text t)) (defun kom-edit-send () "Send the text to the server. This command will attempt to send the text to the server. If something goes wrong, a prompt will be shown allowing you to edit the message and try to send it again." (interactive) (if (and (lyskom-default-value 'lyskom-is-anonymous) (lyskom-j-or-n-p 'do-send-anonymous)) (lyskom-edit-send 'initiate-create-anonymous-text t) (lyskom-edit-send 'initiate-create-text nil))) (defun lyskom-edit-send (send-function &optional is-anonymous) "Send the text to the server by calling SEND-FUNCTION. If optional IS-ANONYMOUS is non-nil, assume that the text is being submitted anonymously and take actions to avoid revealing the sender." (condition-case err (if (or (not lyskom-edit-text-sent) (j-or-n-p (lyskom-get-string 'already-sent))) (progn (let ((buffer (current-buffer)) (headers nil) (misc-list nil) (subject nil) (message nil) (aux-list nil)) ;; ;; Run user hooks ;; ####: ++++: FIXME: We should quit more graciously. (if (and (not (run-hook-with-args-until-failure 'kom-send-text-hook)) (not (run-hook-with-args-until-failure 'lyskom-send-text-hook))) (signal 'lyskom-edit-text-abort nil)) (save-excursion (setq headers (lyskom-edit-parse-headers) misc-list (apply 'lyskom-create-misc-list (elt headers 1)) aux-list (elt headers 2) subject (car headers))) ;; ;; Check that there is a subject ;; (if (or (null subject) (string= subject "")) (let ((old (point))) (goto-char (point-min)) (re-search-forward (lyskom-get-string 'header-subject) nil t) (end-of-line) (if (/= (point) old) (signal 'lyskom-no-subject '(enter-subject-idi))))) ;; ;; Check the recipients ;; (let ((extra-headers (lyskom-edit-send-check-recipients misc-list subject))) (if extra-headers (setq misc-list (apply 'lyskom-create-misc-list (nconc (elt headers 1) extra-headers))))) ;; ;; Check that we don't add ourselves to an anon text ;; (when (and is-anonymous (rassq lyskom-pers-no (cdr misc-list)) (lyskom-j-or-n-p (lyskom-get-string 'remove-self-sending-anonymous))) (rplacd misc-list (delq (rassq lyskom-pers-no (cdr misc-list)) (cdr misc-list)))) ;; ;; Transform the message text ;; (setq message (if (fboundp lyskom-send-text-transform-function) (funcall lyskom-send-text-transform-function (lyskom-edit-extract-text)) (lyskom-edit-extract-text))) (save-excursion (let* ((full-message (cond ((and lyskom-allow-missing-subject (or (null subject) (string= subject "")) (not (string-match ".*\n" message))) message) (t (concat (or subject "") "\n" message)))) (content-type (lyskom-get-aux-item aux-list 1)) (charset (and content-type (lyskom-mime-content-type-get (lyskom-mime-decode-content-type (aux-item->data (car content-type))) 'charset))) (mime-charset (lyskom-mime-string-charset full-message))) ;; If the charset isn't already set, encode the string (if (and mime-charset (null charset)) (setq full-message (lyskom-mime-encode-string full-message)) (when (lyskom-j-or-n-p 'too-many-languages) (keyboard-quit))) ;; Add the charset data to the content type (cond ((> (length content-type) 1) (lyskom-error (lyskom-get-string 'too-many-content-types))) ((null content-type) (setq aux-list (cons (lyskom-create-aux-item 0 1 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (format "text/x-kom-basic;charset=%S" mime-charset)) aux-list))) ((null charset) (set-aux-item->data (car content-type) (format "%s;charset=%S" (aux-item->data (car content-type)) mime-charset)))) ;; Send the text (lyskom-edit-sending-mode 1) (set-buffer lyskom-buffer) ;; Don't change the prompt if we won't see our own text (if (and kom-created-texts-are-read (not is-anonymous)) (setq lyskom-dont-change-prompt t)) (setq lyskom-is-writing nil) (lyskom-tell-internat 'kom-tell-send) (run-hook-with-args 'lyskom-create-text-hook full-message misc-list (if (not is-anonymous) (cons (lyskom-create-aux-item 0 15 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (concat "lyskom.el " lyskom-clientversion)) aux-list) aux-list) buffer is-anonymous) (run-hook-with-args 'kom-create-text-hook full-message misc-list (if (not is-anonymous) (cons (lyskom-create-aux-item 0 15 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (concat "lyskom.el " lyskom-clientversion)) aux-list) aux-list) buffer is-anonymous) (funcall send-function 'sending 'lyskom-create-text-handler full-message misc-list (if (not is-anonymous) (cons (lyskom-create-aux-item 0 15 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (concat "lyskom.el " lyskom-clientversion)) aux-list) aux-list) buffer is-anonymous)))) (lyskom-undisplay-buffer) (goto-char (point-max)))) ;; ;; Catch no-subject and other things ;; (lyskom-edit-text-abort (apply 'lyskom-message (cdr-safe err))) (lyskom-no-subject (lyskom-beep kom-ding-on-no-subject) (if (cdr-safe (cdr-safe err)) (goto-char (car-safe (cdr-safe (cdr-safe err))))) (lyskom-message "%s" (lyskom-get-string (car (cdr err)))) (condition-case nil (let ((text "")) (save-excursion (set-buffer lyskom-buffer) (if (and (string= "kom.lysator.liu.se" lyskom-server-name) (eq lyskom-pers-no 698)) (setq text "Ärende, IDI!"))) (save-excursion (insert text))) (error nil))) (lyskom-unknown-header (lyskom-message "%s" (lyskom-get-string (car (cdr err))))))) (eval-when-compile (defvar ispell-dictionary nil)) (eval-when-compile (defvar ispell-message-text-end nil)) (eval-when-compile (defvar ispell-message-start-skip nil)) (eval-when-compile (defvar ispell-message-end-skip nil)) ;;USER-HOOK: lyskom-ispell-text (defun lyskom-ispell-text () "Check spelling of the text body. Put this in kom-send-text-hook" (kom-edit-ispell-message) t) (eval-when-compile (defvar ispell-dictionary nil) (defvar ispell-message-text-end nil) (defvar ispell-message-start-skip nil) (defvar ispell-message-end-skip nil)) (defalias 'kom-ispell-message 'kom-edit-ispell-message) (defun kom-edit-ispell-message () "Check spelling of the text. Spelling is checked using ispell and the dictionary indicated by `kom-ispell-dictionary'. If you want to check the spelling of every message before sending it, read the documentation for `lyskom-ispell-text' and `kom-send-text-hook'" (interactive) (require 'ispell) (let ((ispell-dictionary (or kom-ispell-dictionary ispell-dictionary)) (kill-ispell (or (not (boundp 'ispell-dictionary)) (not (lyskom-string= kom-ispell-dictionary ispell-dictionary)))) (result nil)) (when kill-ispell (ispell-kill-ispell t)) ;; Checking code (save-excursion (goto-char (point-min)) (let* ((internal-messagep (lyskom-edit-find-separator t)) (limit (copy-marker (cond ((not ispell-message-text-end) (point-max)) ((char-or-string-p ispell-message-text-end) (if (re-search-forward ispell-message-text-end nil t) (match-beginning 0) (point-max))) (t (min (point-max) (funcall ispell-message-text-end)))))) (cite-regexp (regexp-quote (lyskom-default-value 'kom-cite-string))) (cite-regexp-start (concat "^[ \t]*$\\|" cite-regexp)) (cite-regexp-end (concat "^\\(" cite-regexp "\\)")) (old-case-fold-search case-fold-search) (case-fold-search t) (ispell-checking-message t) (subject-string (concat "^" (regexp-quote (lyskom-get-string 'subject))))) (lyskom-ignore ispell-checking-message) (goto-char (point-min)) (while (if internal-messagep (< (point) internal-messagep) (not (eobp))) (if (lyskom-looking-at subject-string) (progn (goto-char (match-end 0)) (let ((case-fold-search old-case-fold-search)) (ispell-region (point) (progn (end-of-line) (point))))) (forward-line 1))) (while (< (point) limit) (while (and (lyskom-looking-at cite-regexp-start) (< (point) limit) (zerop (forward-line 1)))) (if (< (point) limit) (let* ((start (point)) (end-c (and (re-search-forward cite-regexp-end limit 'end) (match-beginning 0))) (end-fwd (and (goto-char start) (boundp 'ispell-message-start-skip) (stringp ispell-message-start-skip) (re-search-forward ispell-message-start-skip limit 'end))) (end (or (and end-c end-fwd (min end-c end-fwd)) end-c end-fwd (marker-position limit)))) (goto-char start) (setq result (ispell-region start end)) (if (and end-fwd (= end end-fwd)) (progn (goto-char end) (re-search-forward ispell-message-end-skip limit 'end)) (goto-char end))))) (set-marker limit nil) result)) (when kill-ispell (ispell-kill-ispell t)) result)) (defun lyskom-is-permitted-author (conf-stat) (and conf-stat (or (eq 0 (conf-stat->permitted-submitters conf-stat)) (lyskom-is-supervisor (conf-stat->conf-no conf-stat) lyskom-pers-no)))) (defun lyskom-edit-send-check-recipients (misc-list subject) "Check that the recipients of this text are OK. Ask the user to confirm multiple recipients; check that the author of the commented text is a member of some recipient of this text. Cannot be called from a callback." (let* ((comm-to-list nil) (recipient-list nil) (text-stat nil) (collector (make-collector)) (extra-headers nil) (buffer (current-buffer)) (me (save-excursion (set-buffer lyskom-buffer) lyskom-pers-no)) (num-me 0) (num-real-recpt 0)) (lyskom-ignore text-stat) ; Have no idea if its ever used... ;; ;; List all texts this text is a comment to ;; List all recipients of the text ;; (lyskom-traverse misc (cdr misc-list) (cond ((eq (car misc) 'COMM-TO) (setq comm-to-list (cons (cdr misc) comm-to-list))) ((memq (car misc) lyskom-recpt-types-list) (when (eq (car misc) 'RECPT) (setq num-real-recpt (1+ num-real-recpt)) (when (eq (cdr misc) me) (setq num-me (1+ num-me)))) (setq recipient-list (cons (cdr misc) recipient-list))))) ;; ;; Check that there are recipients ;; (when (null recipient-list) (lyskom-error "%s" (lyskom-format 'no-recipients))) ;; ;; Check for duplicate recipients ;; (let ((tmp recipient-list)) (while tmp (when (memq (car tmp) (cdr tmp)) (lyskom-error "%s" (lyskom-format 'duplicate-recipients (car tmp)))) (setq tmp (cdr tmp)))) ;; ;; Check for new comments ;; (when (save-excursion (set-buffer lyskom-buffer) (cond ((null kom-check-for-new-comments) nil) ((functionp kom-check-for-new-comments) (funcall kom-check-for-new-comments buffer misc-list subject)) (t t))) (lyskom-message "%s" (lyskom-format 'checking-comments)) (save-excursion (set-buffer lyskom-buffer) (set-collector->value collector nil) (mapcar (function (lambda (text-stat) (cache-del-text-stat text-stat) (initiate-get-text-stat 'sending 'collector-push text-stat collector))) comm-to-list) (lyskom-wait-queue 'sending) (lyskom-traverse text-stat (collector->value collector) (when text-stat (when (catch 'unread (lyskom-traverse misc-item (text-stat->misc-info-list text-stat) (when (and (eq (misc-info->type misc-item) 'COMM-IN) (not (lyskom-text-read-at-least-once-p (blocking-do 'get-text-stat (misc-info->comm-in misc-item))))) (throw 'unread t)))) (unless (lyskom-j-or-n-p (lyskom-format 'have-unread-comment text-stat)) (signal 'lyskom-edit-text-abort (list "%s" (lyskom-get-string 'please-check-commented-texts)))))))) (lyskom-message "%s" (lyskom-format 'checking-comments-done))) ;; ;; Confirm multiple recipients ;; (if (and (lyskom-default-value 'kom-confirm-multiple-recipients) (not (eq (lyskom-default-value 'kom-confirm-multiple-recipients) 'before)) (> (- num-real-recpt num-me) 1)) (save-excursion (goto-char (point-min)) (if (not (lyskom-j-or-n-p (lyskom-format 'comment-all-relevant-p))) (signal 'lyskom-edit-text-abort (list "%s" (lyskom-get-string 'please-edit-recipients)))))) ;; ;; Check that the authors of all commented texts get to see the new text ;; (when (and (lyskom-default-value 'kom-check-commented-author-membership) (assq 'COMM-TO (cdr misc-list))) (lyskom-message "%s" (lyskom-get-string 'checking-rcpt)) (let ((raw-author-list (make-collector)) (author-list nil) (authors-to-ask-about nil) (recipient-list (let ((result nil)) (lyskom-traverse misc (cdr misc-list) (when (memq (car misc) lyskom-recpt-types-list) (setq result (cons (cdr misc) result)))) (nreverse result)))) ;; ;; Collect conf-stats of all authors to check. Since there ;; could be several, do it in a non-blocking way. ;; (lyskom-traverse text-no comm-to-list (initiate-get-text-stat 'sending (lambda (text-stat collector) (when text-stat (initiate-get-conf-stat 'sending 'collector-push (text-stat->author text-stat) collector))) text-no raw-author-list)) (lyskom-wait-queue 'sending) (setq raw-author-list (lyskom-delete-duplicates (collector->value raw-author-list) 'conf-stat->conf-no)) ;; ;; Filter the list. Remove all authors that are direct recipients ;; or whose send-comments-to is a direct recipient or who are ;; listed in kom-dont-check-commented-authors ;; (lyskom-traverse author raw-author-list (let ((send-comments-to (lyskom-get-send-comments-to author t))) (cond ;; Author is in kom-dont-check-commented-authors ((memq (conf-stat->conf-no author) kom-dont-check-commented-authors)) ;; Author is direct recipient to text ((memq (conf-stat->conf-no author) recipient-list)) ;; Author has a zero send-comments-to ((and send-comments-to (zerop (car send-comments-to)))) ;; We don't have permission to send stuff to the author's ;; send-comments-to or to the author if there is no ;; send-comments-to ((or (and send-comments-to (not (lyskom-is-permitted-author (blocking-do 'get-conf-stat (car send-comments-to))))) (and (not send-comments-to) (not (lyskom-is-permitted-author author))))) ;; We can't filter the author straight off, so we add it ;; to the list that we want to check completely. (t (setq author-list (cons author author-list)))))) ;; ;; Now author-list contains a list of authors that we need to ;; check memberships of. Traverse all authors and get their ;; memberships in all recipients. (lyskom-traverse author author-list (let ((memberships (make-collector))) (lyskom-traverse recipient recipient-list (initiate-query-read-texts 'sending (lambda (x y) (collector-push x y)) (conf-stat->conf-no author) recipient nil 0 memberships)) (lyskom-wait-queue 'sending) (setq memberships (collector->value memberships)) ;; ;; Now memberships contains the memberships of author ;; in all recipients of the text. Traverse all memberships ;; in the collector and see if there is one that is not ;; an active membership. If there is not, then we need to ;; ask the user whether they want to add the author. ;; (unless (lyskom-traverse membership memberships (when (and membership (not (membership-type->passive (membership->type membership)))) (lyskom-traverse-break t))) (setq authors-to-ask-about (cons author authors-to-ask-about))))) ;; ;; Now authors-to-ask-about contains all authors that we ;; want to ask about. So do that. ;; (lyskom-traverse author authors-to-ask-about (let ((send-comments-to (car (lyskom-get-aux-item (conf-stat->aux-items author) 33)))) (when send-comments-to (cond ((string-match "^\\([0-9]+\\)\\s-+\\([0-9]+\\)" (aux-item->data send-comments-to)) (setq send-comments-to (cons (string-to-number (match-string 1 (aux-item->data send-comments-to))) (string-to-number (match-string 2 (aux-item->data send-comments-to)))))) ((string-match "^\\([0-9]+\\)" (aux-item->data send-comments-to)) (setq send-comments-to (cons (string-to-number (match-string 1 (aux-item->data send-comments-to))) 0))) (t (setq send-comments-to nil)))) (when (lyskom-j-or-n-p (lyskom-format 'add-recipient-p author (car send-comments-to))) (setq extra-headers (nconc (list (cond ((and send-comments-to (eq (cdr send-comments-to) 0)) 'RECPT) ((and send-comments-to (eq (cdr send-comments-to) 1)) 'CC-RECPT) ((and send-comments-to (eq (cdr send-comments-to) 15)) 'BCC-RECPT) (t (if (lyskom-j-or-n-p (lyskom-format 'really-add-as-recpt-q author)) 'RECPT 'CC-RECPT))) (conf-stat->conf-no author)) extra-headers))))))) extra-headers)) ;;UNUSED: lyskom-send-enriched (defun lyskom-send-enriched (message) (condition-case err (let ((buf (lyskom-get-buffer-create 'lyskom-enriched "lyskom-enriched" t))) (unwind-protect (save-excursion (set-buffer buf) (insert message) (goto-char (point-min)) (format-encode-buffer 'text/enriched) (goto-char (point-min)) (search-forward "\n\n") (if (and (not (lyskom-string= (buffer-substring (point) (point-max)) message)) (save-excursion (set-buffer lyskom-buffer) (lyskom-j-or-n-p (lyskom-get-string 'send-formatted)))) (concat "enriched:\n" (buffer-string)) message)) (kill-buffer buf))) (error (if (lyskom-j-or-n-p (lyskom-format (lyskom-get-string 'transform-error) (error-message-string err))) message (signal 'lyskom-edit-text-abort nil))))) (defun kom-edit-quit () "Cancel editing the text being written and return to reading LysKOM." (interactive) (let ((edit-buffer (current-buffer))) (goto-char (point-max)) (setq lyskom-is-writing nil) (lyskom-tell-internat 'kom-tell-regret) (lyskom-save-excursion (set-buffer edit-buffer) (delete-auto-save-file-if-necessary)) (lyskom-undisplay-buffer edit-buffer) (kill-buffer edit-buffer)) (garbage-collect)) ;Take care of the garbage. (defun kom-edit-show-commented () "Show the commented text in another window." (interactive) (lyskom-edit-get-commented 'lyskom-edit-show-commented)) (defun kom-edit-insert-commented (arg) "Insert the commented text, prepending each line with the text in `kom-cite-string' (defaults to \"> \"). Note that citing the commented text is not common practise in LysKOM (unlike e-mail and news) since there is a strong link to the commented text anyway. Use this command sparingly." (interactive "P") (lyskom-edit-get-commented 'lyskom-edit-insert-commented (list (cond ((and arg (listp arg)) "") (t nil))))) (defun kom-edit-insert-buglist () "Insert the commented buglist, Roxen Internet Software style. Excluded from manual." (interactive) (lyskom-edit-get-commented 'lyskom-edit-insert-buglist)) (defun kom-edit-insert-digit-text () "Prompt for a text to insert. Excluded from manual." (interactive) (setq unread-command-events (cons last-command-event unread-command-events)) (call-interactively 'kom-edit-insert-text nil)) (defun kom-edit-insert-text (no) "Prompt for a text to insert, prefixing each line with the contents of `kom-cite-string' (defaults to \"> \"). Note that citing texts is not commonplace in LysKOM (unlike e-mail and news) since it is easy to refer to specific texts (see `kom-edit-insert-link' and `kom-edit-add-cross-reference'). Use this command sparingly." (interactive (list (cond ((null current-prefix-arg) (lyskom-read-number 'which-text-include)) ((prefix-numeric-value current-prefix-arg))))) (let ((buffer (current-buffer)) (window (selected-window))) (set-buffer lyskom-buffer) (lyskom-collect 'edit) (initiate-get-text 'edit nil no) (initiate-get-text-stat 'edit nil no) (lyskom-use 'edit 'lyskom-edit-insert-commented buffer window) (set-buffer buffer) (sit-for 0))) (defun lyskom-edit-get-commented (thendo &optional arg-list) "Get the commented text and text stat and then do THENDO with it. This function is called with an argument list TEXT TEXT-STAT BUFFER WINDOW plus any optional arguments given in ARG-LIST." (let ((p (point))) (save-excursion (let* ((buffer (current-buffer)) (window (selected-window)) (headers (condition-case nil (elt (lyskom-edit-parse-headers) 1) (lyskom-edit-error nil))) ; Ignore these errors (no nil)) (while headers (if (memq (car headers) '(COMM-TO FOOTN-TO)) (setq no (car (cdr headers)) headers nil) (setq headers (cdr (cdr headers))))) (cond (no (goto-char p) (set-buffer lyskom-buffer) (blocking-do-multiple ((text (get-text no)) (text-stat (get-text-stat no))) (set-buffer buffer) (apply thendo text text-stat buffer window arg-list))) (t (lyskom-message "%s" (lyskom-get-string 'no-such-text-m)))))) (sit-for 0))) ;;; ============================================================ ;;; Info node stuff (defvar Info-current-node) (defvar Info-current-file) ;; NOTUSED: kom-yank-info-nodename (defalias 'kom-yank-info-nodename 'kom-edit-yank-info-nodename) (defun kom-edit-yank-info-nodename () "When browsing info files, this command will place a reference to the current info node in the kill ring, from where it can be pasted into another buffer. This command is useful when you want to refer to an info node in a LysKOM text." (interactive) (kill-new (format "*Note %s: (%s)%s," Info-current-node (file-name-nondirectory Info-current-file) Info-current-node))) ;; NOTUSED: kom-insert-last-info-nodename (defalias 'kom-insert-last-info-nodename 'kom-edit-insert-last-info-nodename) (defun kom-edit-insert-last-info-nodename () "Insert a reference to the most recently visited info node." (interactive) (condition-case nil (let ((link nil)) (save-excursion (set-buffer (get-buffer "*info*")) (setq link (format "*Note %s: (%s)%s," Info-current-node (file-name-nondirectory Info-current-file) Info-current-node))) (insert link)) (error (lyskom-message "%s" (lyskom-get-string 'cant-find-info-node))))) ;;; ================================================================ ;;; Add recipient, copy-recipient - Addera mottagare ;;; ;;; Author: Anders Gertz ;;; Changed by: Linus Tolke (defun kom-edit-add-comment () "Makes this text a comment to another text. Using this command it is possible to make the text a comment to multiple texts. To remove a comment link, simply remove the corresponding line from the headers in the edit buffer." (interactive) (let* ((edit-buffer (current-buffer)) (insert-at (point-min-marker)) (text-no (lyskom-read-number (lyskom-get-string 'text-to-comment-q))) (text-stat (blocking-do 'get-text-stat text-no))) (lyskom-ignore edit-buffer) (lyskom-save-excursion (if text-stat (lyskom-edit-get-commented-author (blocking-do 'get-text-stat text-no) (lyskom-get-string 'comment) insert-at text-no) (lyskom-error "%s" (lyskom-get-string 'no-such-text-m)))))) (defun kom-edit-add-recipient () "Adds a regular recipient to the text or converts an existing recipient to a regular recipient. Using this command it is possible to add any number of regular recipients. To remove a recipient, simply delete the corresponding header line in the edit buffer." (interactive) (lyskom-edit-add-recipient/copy 'added-recipient nil 'RECPT)) (defun kom-edit-add-bcc () "Adds a blind carbon copy recipient to the text, or converts an existing recipient to blind carbon copy. Using this command it is possible to add any number of regular recipients. To remove a recipient, simply delete the corresponding header line in the edit buffer." (interactive) (lyskom-edit-add-recipient/copy 'added-blank-carbon-copy nil 'BCC-RECPT)) (defun kom-edit-add-copy () "Adds a carbon copy recipient to the text, or converts an existing recipient to blind carbon copy. Using this command it is possible to add any number of regular recipients. To remove a recipient, simply delete the corresponding header line in the edit buffer." (interactive) (lyskom-edit-add-recipient/copy 'added-carbon-copy nil 'CC-RECPT)) (defun kom-edit-move-text () "Adds a regular recipient to the text, or converts an existing recipient to blind carbon copy, and converts all other recipients to carbonn copy recipients. This command is intended for situations where a commend is being sent to a different recipient than the commented text was." (interactive) (lyskom-edit-add-recipient/copy 'who-to-move-to-q 'lyskom-edit-move-recipients)) (defun lyskom-edit-move-recipients (conf-stat insert-at edit-buffer) (save-excursion (set-buffer edit-buffer) (let* ((tmp (lyskom-edit-parse-headers)) (subject (car tmp)) (miscs (mapcar (lambda (x) (if (eq (car x) 'RECPT) (cons 'CC-RECPT (cdr x)) x)) (cdr (lyskom-edit-translate-headers (elt tmp 1))))) (aux-list (elt tmp 2)) (elem nil)) ;; If the new target is already a recipient, convert it to the right ;; kind. Otherwise insert the new target after the last comm-to (setq elem (lyskom-edit-find-misc miscs lyskom-recpt-types-list (conf-stat->conf-no conf-stat))) (if elem (setcar elem 'RECPT) (lyskom-insert-in-list (cons 'RECPT (conf-stat->conf-no conf-stat)) miscs (car (cdr (memq (lyskom-edit-find-misc miscs '(FOOTN-TO COMM-TO) nil t) miscs))))) (lyskom-edit-replace-headers subject (cons 'MISC-LIST miscs) aux-list)))) (defun lyskom-edit-do-add-recipient/copy (recpt-type recpt-no edit-buffer) (save-excursion (set-buffer edit-buffer) (let* ((headers (lyskom-edit-parse-headers)) (miscs (lyskom-edit-translate-headers (elt headers 1))) (elem (lyskom-edit-find-misc miscs lyskom-recpt-types-list recpt-no))) (cond (elem (setcar elem recpt-type)) (t (setq miscs (append miscs (list (cons recpt-type recpt-no)))))) (lyskom-edit-replace-headers (elt headers 0) miscs (elt headers 2))))) (defun lyskom-edit-add-recipient/copy (prompt &optional what-to-do recpt-type) "Adds a new recipient or a cc-recipient to the text which is being edited. PROMPT is the prompt to use to ask the user for a recipient. WHAT-TO-DO is a function to call to do the insertion. RECPT-TYPE is the type of recipient to add." (let ((edit-buffer (current-buffer)) (insert-at (point-min-marker)) (conf-stat (lyskom-read-conf-stat prompt '(all) nil nil t))) (lyskom-save-excursion (save-excursion (set-buffer lyskom-buffer) ;; +++ The information about msg-of-day might be old. We should ;; make sure it is up-to-date. (let ((text-no (conf-stat->msg-of-day conf-stat)) (win-config nil) (text nil) (text-stat nil) (collector (make-collector))) (unless (zerop text-no) (initiate-get-text 'edit 'collector-push text-no collector) (initiate-get-text-stat 'edit 'collector-push text-no collector) (lyskom-wait-queue 'edit) (setq text-stat (elt (collector->value collector) 0)) (setq text (elt (collector->value collector) 1))) (when (or (null text) (null text-stat) (null (get-buffer-window edit-buffer)) (progn (setq win-config (current-window-configuration)) (with-output-to-temp-buffer "*Motd*" (lyskom-princ (lyskom-format 'conf-has-motd-no (text->text-no text) (text->decoded-text-mass text text-stat)))) (j-or-n-p (lyskom-get-string 'still-want-to-add)))) (when (and kom-confirm-add-recipients (eq recpt-type 'RECPT) (not (lyskom-j-or-n-p (lyskom-format 'really-add-as-recpt-q conf-stat)))) (setq recpt-type 'CC-RECPT)) (if what-to-do (funcall what-to-do conf-stat insert-at edit-buffer) (lyskom-edit-do-add-recipient/copy recpt-type (conf-stat->conf-no conf-stat) edit-buffer))) (when win-config (set-window-configuration win-config))))))) (defun lyskom-edit-sub-recipient/copy (recpt-no edit-buffer) "Remove the recipient having RECPT-NO from EDIT-BUFFER" (save-excursion (set-buffer edit-buffer) (let* ((headers (lyskom-edit-parse-headers)) (miscs (lyskom-edit-translate-headers (elt headers 1))) (elem (lyskom-edit-find-misc miscs lyskom-recpt-types-list recpt-no))) (when elem (setcar elem nil)) (lyskom-edit-replace-headers (elt headers 0) miscs (elt headers 2))))) (defun kom-edit-add-cross-reference () "Add a cross reference to this text. This command prompts for the type and target of the cross reference. Cross references are used to systematically refer from a text to another text, conference or person without altering the contents of the text." (interactive) (let ((item (lyskom-read-cross-reference-and-get-aux-item))) (when item (lyskom-edit-insert-aux-item item)))) (defun kom-edit-add-read-confirm-request () "Request that others confirm reading this text. Conforming clients will ask each reader of this text to confirm reading the text. Note that not all clients understand this request, and that confirmation is neither automatic nor mandatory. Use very sparingly as this interrupts the normal flow of reading for many users." (interactive) (lyskom-edit-insert-aux-item (lyskom-create-aux-item 0 6 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 ""))) (defun kom-edit-add-no-comments () "Request that nobody comments this text. Conforming clients will either prevent users from commenting the text or ask for confirmation before commenting the text. Note that not all clients understand this request and that it is advisory only." (interactive) (lyskom-edit-insert-aux-item (lyskom-create-aux-item 0 4 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 ""))) (defun kom-edit-add-personal-comments () "Request that all replies to this text are in the form of personal replies. Conforming clients will treat a request to comment this text as a request to answer privately. Note that not all clients understand this request and that it is advisory only." (interactive) (lyskom-edit-insert-aux-item (lyskom-create-aux-item 0 5 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 ""))) (defun kom-edit-add-world-readable () "Make this text readable to all users, even if they are not logged in. World readable texts can be read by anyone, regardless of what recipients the text has. World readable texts can even be read without logging in to LysKOM." (interactive) (lyskom-edit-insert-aux-item (lyskom-create-aux-item 0 34 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 ""))) (defun kom-edit-insert-link () "Insert an in-line link to another text, a conference or a person. This command prompts for the target of the link and inserts text that most clients will interpret as a link." (interactive) (let ((item (lyskom-read-link))) (when item (insert item)))) (defun lyskom-read-link () "Query user about link type and value, and return the corresponding link as a string." (let* ((type (lyskom-a-or-b-or-c-p 'link-type '(abc-conference abc-person abc-text) nil)) (obj nil)) (cond ((eq type 'abc-text) (let ((prompt 'which-text-to-link)) (while (null obj) (setq obj (blocking-do 'get-text-stat (lyskom-read-number prompt))) (setq prompt 'which-text-to-link-err ))) (let* ((text-no (text-stat->text-no obj)) (text (blocking-do 'get-text text-no)) (txt (text->decoded-text-mass text obj)) (eos (string-match (regexp-quote "\n") txt)) (subject (substring txt 0 eos))) (format "" text-no subject))) ((eq type 'abc-conference) (while (null obj) (setq obj (lyskom-read-conf-stat 'which-conf-to-link '(conf) nil nil t))) (format "" (conf-stat->conf-no obj) (conf-stat->name obj))) ((eq type 'abc-person) (while (null obj) (setq obj (lyskom-read-conf-stat 'which-pers-to-link '(pers) nil nil t))) (format "" (conf-stat->conf-no obj) (conf-stat->name obj)))))) (defun lyskom-edit-insert-aux-item (item) "Insert the aux item ITEM in the current buffer" (save-excursion (lyskom-edit-find-separator t) (forward-line (if kom-edit-hide-add-button -1 -2)) (insert (concat (lyskom-format (format "%%#1@%%[%s%%] %%#2s" (lyskom-get-string 'aux-item-prefix)) (lyskom-default-button 'aux-edit-menu (cons (current-buffer) (point-marker))) (lyskom-aux-item-call item '(edit-insert print) item lyskom-pers-no)) "\n"))) ) (defun lyskom-edit-toggle-secret-aux (buf arg text) (interactive) (lyskom-save-excursion (set-buffer (car arg)) (goto-char (cdr arg)) (lyskom-edit-toggle-aux-item-flag buf arg text 'secret))) (defun lyskom-edit-toggle-anonymous-aux (buf arg text) (interactive) (save-excursion (set-buffer (car arg)) (goto-char (cdr arg)) (lyskom-edit-toggle-aux-item-flag buf arg text 'anonymous))) (defun lyskom-edit-toggle-inherit-aux (buf arg text) (interactive) (save-excursion (set-buffer (car arg)) (goto-char (cdr arg)) (lyskom-edit-toggle-aux-item-flag buf arg text 'inherit))) (defun lyskom-edit-delete-aux (buf arg text) (interactive) (save-excursion (set-buffer (car arg)) (goto-char (cdr arg)) (beginning-of-line) (delete-region (point) (save-excursion (forward-line 1) (point))))) (defun lyskom-edit-generate-aux-item-flags (flags) (save-excursion (let ((str (mapconcat 'identity (delq nil (list (and (aux-item-flags->secret flags) (lyskom-get-string 'secret-aux-flag)) (and (aux-item-flags->anonymous flags) (lyskom-get-string 'anonymous-aux-flag)) (and (aux-item-flags->inherit flags) (lyskom-get-string 'inherit-aux-flag)))) ", "))) (when (not (string= str "")) (format " [%s]" str))))) (defun lyskom-edit-insert-aux-item-flags (flags) (end-of-line) (insert (lyskom-edit-generate-aux-item-flags flags))) (defun lyskom-edit-toggle-aux-item-flag (buf arg text flag) (beginning-of-line) (let ((flags (lyskom-edit-extract-aux-item-flags))) (when (re-search-forward "\\s-?\\[[^]]*\\]\\s-*$" (save-excursion (end-of-line) (point)) t) (delete-region (match-beginning 0) (match-end 0))) (funcall (intern (format "set-aux-item-flags->%s" flag)) flags (not (funcall (intern (format "aux-item-flags->%s" flag)) flags))) (lyskom-edit-insert-aux-item-flags flags))) ;;; ================================================================ ;;; Help functions for the functions bound to keyboard sequences ;;; in lyskom-edit-mode. (defun lyskom-edit-find-misc (misc-list type data &optional last) "Return the first misc-info pair in MISC-LIST of type TYPE containing DATA. If TYPE is a list, then any type in TYPE is considered to match. If DATA is nil, then any DATA is considered to match. If optional LAST is non-nil, then return the last match instead of the first." (when (eq (car misc-list) 'MISC-LIST) (setq misc-list (cdr misc-list))) (let ((result nil) (elem nil)) (while (and misc-list (or last (null result))) (setq elem (car misc-list)) (setq misc-list (cdr misc-list)) (when (cond ((listp type) (and (memq (car elem) type) (or (null data) (eq data (cdr elem))))) ((symbolp type) (and (eq type (car elem)) (or (null data) (eq data (cdr elem))))) (t (or (null data) (eq data (cdr elem))))) (setq result elem))) result)) (defun lyskom-edit-translate-headers (misc-list) "Translate result of lyskom-edit-parse-header to something we can send to lyskom-edit-replace-headers" (let ((result nil)) (while misc-list (setq result (cons (cons (car misc-list) (car (cdr misc-list))) result)) (setq misc-list (cdr (cdr misc-list)))) (cons 'MISC-LIST (nreverse result)))) (defun lyskom-edit-replace-headers (subject misc-list aux-list) "Replace all headers with SUBJECT and MISC-LIST" (save-excursion (let ((start nil) (inhibit-read-only t) (end nil)) (goto-char (point-min)) (setq start (point-marker)) (set-marker-insertion-type start t) (lyskom-edit-find-separator t) (end-of-line) (setq end (point-marker)) (goto-char (point-min)) (lyskom-edit-insert-miscs misc-list subject "" aux-list) (delete-region start end) (goto-char end) (delete-char 1)))) (defun lyskom-looking-at-header (header match-number) "Check if point is at the beginning of a header of type HEADER. Return the corresponding number (conf no etc.) if MATCH-NUMBER is non-nil. If MATCH-NUMBER is 'angled, only match a number inside <>." (if (lyskom-looking-at (concat (lyskom-get-string header) (cond ((eq match-number 'angled) "[^0-9\n\r]*<\\([0-9]+\\)>") ((eq match-number 'empty) "[^:]*:\\(\\s-*\\)$") (match-number "[^0-9]*\\([0-9]+\\)") (nil "")))) (if match-number (string-to-int (buffer-substring (match-beginning 2) (match-end 2))) t) nil)) (defun lyskom-edit-parse-headers () "Parse the headers of an article. They are returned as a list where the first element is the subject, and the rest is a list (HEADER DATA HEADER DATA ...), where HEADER is either 'RECPT, 'CC-RECPT, 'COMM-TO or 'FOOTN-TO. This is to make it easy to use the result in a call to `lyskom-create-misc-list'." (goto-char (point-min)) (let ((misc nil) (subject nil) (aux nil)) (save-restriction ;; Narrow to headers (lyskom-edit-find-separator t) (narrow-to-region (point-min) (point)) (goto-char (point-min)) (while (< (point) (point-max)) (let ((case-fold-search t) (n nil)) (cond ((setq n (lyskom-looking-at-header 'recipient-prefix 'angled)) (setq misc (nconc misc (list 'RECPT n)))) ((setq n (lyskom-looking-at-header 'carbon-copy-prefix 'angled)) (setq misc (nconc misc (list 'CC-RECPT n)))) ((setq n (lyskom-looking-at-header 'blank-carbon-copy-prefix 'angled)) (setq misc (nconc misc (list 'BCC-RECPT n)))) ((setq n (lyskom-looking-at-header 'comment-prefix t)) (setq misc (nconc misc (list 'COMM-TO n)))) ((setq n (lyskom-looking-at-header 'footnote-prefix t)) (setq misc (nconc misc (list 'FOOTN-TO n)))) ((lyskom-looking-at-header 'header-subject nil) (setq subject (lyskom-edit-extract-subject))) ((lyskom-looking-at (lyskom-get-string 'aux-item-prefix-regexp)) (goto-char (match-end 0)) (let ((item (lyskom-edit-parse-aux-item))) (if item (setq aux (cons item aux)) (signal 'lyskom-unknown-header (list 'unknown-header (point)))))) ((lyskom-looking-at (lyskom-get-string 'comment-item-prefix)) nil) ((or (lyskom-looking-at-header 'blank-carbon-copy-prefix 'empty) (lyskom-looking-at-header 'carbon-copy-prefix 'empty) (lyskom-looking-at-header 'recipient-prefix 'empty)) nil) ((lyskom-looking-at-header 'add-recpt-button-text-regex nil) nil) (t (signal 'lyskom-unknown-header (list 'unknown-header (point)))))) (forward-line 1))) (list subject misc aux))) (defun lyskom-edit-parse-aux-item () (let ((definitions lyskom-aux-item-definitions) (data nil)) (while (and (null data) definitions) (setq data (lyskom-aux-item-call (car definitions) 'parse)) (unless data (setq definitions (cdr definitions)))) (when data (lyskom-create-aux-item 0 (lyskom-aux-item-definition->number (car definitions)) 0 0 (lyskom-edit-extract-aux-item-flags) 0 data)))) (defun lyskom-edit-extract-aux-item-flags () (if (lyskom-looking-at ".*\\[\\([^]]*\\)\\]\\s-*$") (let ((flag-strings (match-string 1)) (start 0) (flag nil) (flags (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil)) (case-fold-search t)) (while (string-match "\\s-*\\(\\w+\\)\\s-*" flag-strings start) (setq flag (match-string 1 flag-strings)) (setq start (match-end 0)) (cond ((string-match (lyskom-get-string 'secret-aux-flag) flag) (set-aux-item-flags->secret flags t)) ((string-match (lyskom-get-string 'anonymous-aux-flag) flag) (set-aux-item-flags->anonymous flags t)) ((string-match (lyskom-get-string 'inherit-aux-flag) flag) (set-aux-item-flags->inherit flags t)) (t nil))) flags) (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil))) (defun lyskom-edit-extract-subject () "Find the subject. Point must be located on the line where the subject is." (re-search-forward ": \\(.*\\)") (buffer-substring (match-beginning 1) (match-end 1))) (defun lyskom-edit-extract-text () "Get text as a string." (save-excursion (if (not (lyskom-edit-find-separator t)) (signal 'lyskom-internal-error "Altered lyskom-header-separator line.") (end-of-line) (buffer-substring (1+ (point)) (progn (goto-char (1- (point-max))) (while (lyskom-looking-at "\\s-") ; remove trailing (backward-char 1)) ; whitespace (forward-char 1) (point)))))) (defun lyskom-create-text-handler (text-no edit-buffer &optional is-anonymous) "Handle an attempt to write a text." (lyskom-tell-internat 'kom-tell-silence) (message "") (cond ((null text-no) (lyskom-insert-before-prompt (lyskom-format 'could-not-create-text lyskom-errno (lyskom-get-error-text lyskom-errno))) (beep) (lyskom-message "%s" (lyskom-format 'could-not-create-text lyskom-errno (lyskom-get-error-text lyskom-errno))) (set-buffer lyskom-buffer) (read-list-enter-first (lyskom-create-read-info 'RE-EDIT-TEXT nil 256 nil nil nil edit-buffer) lyskom-reading-list) (lyskom-update-prompt) (set-buffer edit-buffer) (lyskom-edit-mode 1) (sit-for 0)) (t (if is-anonymous (lyskom-format-insert-before-prompt 'text-created-anonymous text-no) (lyskom-insert-before-prompt (lyskom-format 'text-created text-no))) ;; Save the text (when kom-created-texts-are-saved (when (buffer-live-p edit-buffer) (initiate-get-conf-stat 'background 'lyskom-edit-fcc-text lyskom-pers-no (save-excursion (set-buffer edit-buffer) (buffer-string)) text-no is-anonymous))) ;; Immediately mark the text as read if kom-created-texts-are-read is set ;; and we are not sending the text anonymously. (cond ((and kom-created-texts-are-read (not is-anonymous)) (lyskom-is-read text-no) (initiate-get-text-stat 'background 'lyskom-mark-as-read text-no) (lyskom-run 'background 'set 'lyskom-dont-change-prompt nil) (lyskom-run 'background 'lyskom-set-mode-line)) (t ; Probably not necessary (setq lyskom-dont-change-prompt nil))) (set-buffer edit-buffer) ;Need local variables. (lyskom-edit-sent-mode 1) ;; Record the text number (unless is-anonymous (lyskom-setq-default lyskom-last-written text-no) (lyskom-setq-default lyskom-last-seen-written text-no)) ;; Select the old configuration. (let ((hnd lyskom-edit-handler) (dta lyskom-edit-handler-data)) (cond ((get-buffer-window edit-buffer) (set-window-configuration lyskom-edit-return-to-configuration) (set-buffer (window-buffer (selected-window))) (goto-char (point-max)))) ;; Apply handler. (set-buffer lyskom-buffer) (if hnd (apply hnd text-no dta))) ;; Kill the edit-buffer. (lyskom-save-excursion (set-buffer edit-buffer) (delete-auto-save-file-if-necessary)) (kill-buffer edit-buffer) ))) (defun lyskom-edit-fcc-text (conf-stat text text-no is-anonymous) (condition-case arg (let ((start 1) (end 0) (inhibit-read-only t)) (save-excursion (set-buffer (lyskom-get-buffer-create 'fcc "*kom*-fcc" t)) (erase-buffer) (insert text) (goto-char (point-min)) (when (lyskom-edit-find-separator t) (delete-region (match-beginning 0) (match-end 0)) (unless kom-edit-hide-add-button (save-excursion (beginning-of-line) (forward-line -2) (delete-region (progn (beginning-of-line) (point)) (progn (forward-line 1) (point))))) (insert (make-string kom-text-header-dash-length ?-)) (forward-line 1) (beginning-of-line) (setq start (point))) (goto-char (point-min)) (when (re-search-forward "\\(\\s-\\|[\n\r]\\)+\\'" nil t) (delete-region (match-beginning 0) (match-end 0))) (goto-char (point-max)) (setq end (point)) (insert (lyskom-format "\n(%#1n) %#2s\n\n" text-no (make-string (- kom-text-footer-dash-length (lyskom-string-width (int-to-string text-no)) 3) ?-))) (goto-char (point-min)) (lyskom-format-insert-at-point 'text-no-comment text-no (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time)) (count-lines start end) conf-stat is-anonymous) (append-to-file (point-min) (point-max) (expand-file-name kom-created-texts-are-saved)))) (file-error (message "%S" arg)(lyskom-format-insert-before-prompt 'cant-fcc-text-file-error text-no kom-created-texts-are-saved (elt arg 1) (elt arg 2) )) (error (lyskom-format-insert-before-prompt 'cant-fcc-text text-no kom-created-texts-are-saved (error-message-string arg))))) (defun lyskom-edit-show-commented (text text-stat editing-buffer window) "Handles the TEXT and TEXT-STAT from the return of the call of the text. The EDITING-BUFFER is the buffer the editing is done in. If this buffer is not displayed nothing is done. If displayed then this buffer is chosen then the with-output-to-temp-buffer command is issued to make them both apear." (and text (get-buffer-window editing-buffer) (progn (set-buffer editing-buffer) (select-window window) (let ((buf (lyskom-get-buffer-create 'view-commented "*Commented*")) (kom-deferred-printing nil)) (save-selected-window (lyskom-display-buffer buf) (unless kom-review-uses-cache (cache-del-text-stat (text->text-no text))) (save-excursion (set-buffer buf) (erase-buffer) (lyskom-view-text (text->text-no text)) (set-buffer-modified-p nil) (lyskom-view-mode))))))) (defun lyskom-edit-insert-commented (text text-stat editing-buffer window &optional prefix) "Handles the TEXT and TEXT-STAT from the return of the call of the text. When given a PREFIX string, that is prepended to each inserted line. If PREFIX is nil, use the default prefix (kom-cite-string or \">\"." (if (and text text-stat) (let ((str (text->decoded-text-mass text text-stat)) (prefix (or prefix (lyskom-default-value 'kom-cite-string) ">"))) (set-buffer editing-buffer) (and (not (bolp)) (insert "\n")) (and (not (eolp)) (open-line 1)) (let* ((pb (point)) (as (string-match "\n" str)) (te (substring str (1+ as)))) (insert te) (while (<= pb (point)) (beginning-of-line) (when prefix (insert prefix)) (forward-line -1)))) (lyskom-message "%s" (lyskom-get-string 'no-get-text)))) ;;; ======================================================================== ;;; Treat the commented text as a Roxen Internet Software-style buglist, ;;; handling the removal of closed subjects, last-message changes et c ;;; Author: Johan Sundström (defun lyskom-edit-insert-buglist (text text-stat editing-buffer window) "Handles the TEXT and TEXT-STAT from the return of the call of the text. The commented text is inserted in the buffer in the Roxen Internet Software buglist style, automating the removal of closed subjects and change-marks." (if (and text text-stat) (let ((str (text->decoded-text-mass text text-stat))) (set-buffer editing-buffer) (and (not (bolp)) (insert "\n")) (and (not (eolp)) (open-line 1)) (let* ((pb (point)) (as (string-match "\n" str)) (te (substring str (1+ as)))) ;; insert the body of the commented text at point (pb) (insert te) ;; traverse the inserted text, replacing a leading ! ;; with a space wherever some form of "[ ]" follows ;; (and X:s, since some morons were too inept to ;; handle these highly advanced syntactic rules) (while (re-search-backward "^\\s-*[!X][ \t(]*\\[" nil t) (replace-regexp "^\\(\\s-*\\)[!X]\\([ \t(]*\\[\\)" "\\1 \\2")) (goto-char pb) ;; new pass; leave all [ ], [/] and [\] subjects untouched, ;; but remove the rest, except for category headers, who remain. (while ;; Find a closed subject (that does not match any of the above) (re-search-forward "^[ \t*([]*\\[[^\\/ ]\\]" nil t) (beginning-of-line) ;; Delete from here to the next open subject or the ;; next category header, whichever comes first. (let* ((delete-from (point)) (delete-to ;; First part matches an open subject, second part finds ;; new headline. A headline is here defined as something ;; with no more than two leading ws characters followed by ;; a non-whitespace, non-[(*! character. The advantage of ;; this over matching against ^\s-*$ is that long subjects ;; may be split into separate paragraphs and still work here. (re-search-forward "^[ \t*(]*\\[[\\/ ]\\]\\|^\\s-\\{0,2\\}[^ \t(*![]" nil t))) (if delete-to ;; There was at least one more subject later on (progn (goto-char delete-to) (beginning-of-line) ;; Are we looking at a headline? (if (lyskom-thing-at-point-looking-at "^\\s-\\{0,2\\}[^ \t(*![]") ;; yes -- hence we need to move point somewhat (progn (beginning-of-line) ;; leave the newline before the headline intact (forward-char -1)))) ;; This was the last subject; kill the rest of the buffer (goto-char (point-max))) ;; Drain the closed subject. (delete-region delete-from (point)))))) (lyskom-message "%s" (lyskom-get-string 'no-get-text)))) ;;; ================================================================ ;;; Tab between buttons in the header (defun kom-edit-next-button-or-self-insert (num) "Move to the next link or insert a TAB, depending on context. Excluded from manual." (interactive "p") (let ((header-end (lyskom-edit-find-separator)) (start (point)) (next-pos nil)) (if (> (point) header-end) (unless (lyskom-traverse keymap (current-minor-mode-maps) (let ((binding (lookup-key keymap (this-command-keys)))) (when (and (commandp binding) (not (eq binding 'kom-edit-next-button-or-self-insert))) (call-interactively binding) (lyskom-traverse-break t)))) (let ((binding (lookup-key (current-local-map) (this-command-keys) t))) (if (and (commandp binding) (not (eq binding 'kom-edit-next-button-or-self-insert))) (call-interactively binding) (call-interactively 'self-insert-command)))) (while (> num 0) (lyskom-next-area 1 'lyskom-button) (if (eq start (point)) (setq next-pos nil) (setq next-pos (point))) (cond ((or (null next-pos) (> next-pos header-end)) (goto-char start) (unless (re-search-forward (regexp-quote (lyskom-get-string 'header-subject)) header-end t) (goto-char (point-max)) (setq num 0))) (t (goto-char next-pos))) (setq num (1- num) start (point)))))) (defun kom-edit-prev-button (num) "Move to the previous link. Excluded from manual." (interactive "p") (let ((header-end (lyskom-edit-find-separator))) (while (> num 0) (cond ((and (> (point) header-end) (progn (goto-char (point-min)) (re-search-forward (regexp-quote (lyskom-get-string 'header-subject)) header-end t))) (setq num (1- num))) (t (lyskom-prev-area num 'lyskom-button) (setq num 0)))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: filter.el,v 44.29 2003/08/17 13:21:33 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: filter.el ;;;; ;;;; Contains the support functions for text filtering. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: filter.el,v 44.29 2003/08/17 13:21:33 byers Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) ;;;============================================================ ;;; ;;; Filter pattern accessors ;;; ;;; Filters are lists with the following structure ;;; ;;; (filter [ PATTERNS ATTRIBUTES FUNCTION]) ;;; ;;; Where PATTERNS is a list of filter patterns and ATTRIBUTES is ;;; an association list. FUNCTION is a lisp function implementing ;;; the filter. ;;; ;;; The following attributes are reserved ;;; ;;; action -- What action to take when the pattern matches. Currently ;;; one of dontshow, skip or skip-comments. ;;; expire -- When the filter expires. Not used. ;;; (defun make-filter (&optional p a) "Creates and returns a filter structure. Optional P and A initialize pattern and attributes, respectively." (lyskom-create-filter p a (lyskom-create-compile-filter-function p))) (defun lyskom-create-filter (pattern attribute-list function) (list 'filter (vector pattern attribute-list function))) (defun lyskom-recompile-filter (filter) "Re-compile the filter FILTER" (set-filter->function filter (lyskom-create-compile-filter-function (filter->pattern filter)))) (defun copy-filter (f) "Create a copy of the filter F" (make-filter (copy-tree (filter->pattern f)) (copy-tree (filter->attribute-list f)))) (defun filter-p (f) "Returns T if f looks like a filter" (and (listp f) (eq 'filter (car f)))) (defun filter->pattern (f) "Extract the patterns part of a filter F" (elt (elt f 1) 0)) (defun filter->attribute-list (f) "Extract the attribute list of F." (elt (elt f 1) 1)) (defun filter->attribute (f a) "From filter F, extract the value of attribute A. Returns nil if no such attribute is present." (cdr (assq a (filter->attribute-list f)))) (defun set-filter->pattern (f p) "Set the patterns part of F to P." (aset (elt f 1) 0 p)) (defun set-filter->attribute-list (f l) "Set the attribute list of filter F to L" (aset (elt f 1) 1 l)) (defun set-filter->attribute (f a v) "Set the value in filter F of attribute A to V." (let ((x (assq a (filter->attribute-list f)))) (if x (setcdr x v) (set-filter->attribute-list f (cons (cons a v) (filter->attribute-list f)))))) (defun filter->function (f) "Get the function for filter F" (elt (elt f 1) 2)) (defun set-filter->function (f fn) "Set the function for filter F to FN" (aset (elt f 1) 2 fn)) ;;;============================================================ ;;; ;;; (defvar lyskom-filter-hack nil "Variable to busy-wait on to get the filter action. Set to invalid-value until a filter action has been selected.") (defun lyskom-filter-text-p (text-no) (if (null lyskom-filter-list) nil (progn (setq lyskom-filter-hack 'invalid-value) (initiate-get-text-stat 'filter 'lyskom-filter-text-p-2 text-no) ;; ;; Block until done ;; (while (eq lyskom-filter-hack 'invalid-value) (lyskom-accept-process-output)) lyskom-filter-hack))) (defun lyskom-filter-text-p-2 (text-stat) (if (null text-stat) (setq lyskom-filter-hack nil) (progn ;; ;; Collect information from the server ;; (lyskom-collect 'filter) ;; ;; Get the conf-stat of the author of the text ;; Get the text body ;; (initiate-get-conf-stat 'filter nil (text-stat->author text-stat)) (initiate-get-text 'filter nil (text-stat->text-no text-stat)) ;; ;; Get the conf-stat of the recipients ;; (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (if (memq type lyskom-recpt-types-list) (initiate-get-conf-stat 'filter nil (misc-info->recipient-no misc))))) ;; ;; Use the results ;; (lyskom-use 'filter 'lyskom-filter-text-p-3 text-stat)))) (defun lyskom-filter-text-p-3 (author text &rest data) (if (null text) (setq lyskom-filter-hack nil) (let (subject text-stat) ;; ;; Extract the text-stat which is the last element of data ;; Next shorten the list in data to exclude the text-stat. ;; (setq text-stat (elt data (- (length data) 1))) (if (= (length data) 1) (setq data nil) (rplacd (nthcdr (- (length data) 2) data) nil)) ;; ;; Extract the subject ;; (let ((str (text->decoded-text-mass text text-stat))) (cond ((string-match "\n" str) (setq subject (substring str 0 (match-beginning 0)))) (t (setq subject "")))) ;; ;; Do the checking ;; (setq lyskom-filter-hack (lyskom-check-filter-list text-stat author data subject (text->decoded-text-mass text text-stat) lyskom-filter-list))))) (defun lyskom-check-filter-list (text-stat author recipient-list subject text filter-list) (let (tmp) (while filter-list (condition-case nil (if (functionp (filter->function (car filter-list))) (setq tmp (funcall (filter->function (car filter-list)) (car filter-list) author recipient-list subject text-stat text))) (error nil)) (if tmp (setq filter-list nil) (setq filter-list (cdr filter-list)))) tmp)) ;;;======================================== ;;; The filter compiler. ;;; (defmacro lyskom-filter-is-member (testfn arg list selector) (` (let (found (objlist (, list))) (while (and objlist (not found)) (and ((, testfn) (, arg) ((, selector) (car objlist))) (setq found t)) (setq objlist (cdr objlist))) found))) (defun lyskom-create-compile-filter-function (pattern) (if (null pattern) (byte-compile '(lambda (filter author recipient-list subject text-stat text) nil)) (byte-compile (lyskom-create-filter-function pattern)))) (defun lyskom-create-filter-function (pattern) (` (lambda (filter author recipient-list subject text-stat text) (, (cons 'and (lyskom-create-filter-function-body pattern)))))) (defun lyskom-create-filter-function-body (pattern) (let (inverse) (cond ;; ;; End of pattern ;; ((null pattern) '((filter->attribute filter 'action))) ;; ;; Bad pattern ;; ((or (not (listp pattern)) (not (listp (car pattern)))) (lyskom-error "%s" (lyskom-get-string 'filter-error-specification))) ;; ;; Assume valid pattern ;; (t (let ((key (car (car pattern))) (args (cdr (car pattern))) (form nil)) (if (eq key 'not) (if (not (listp args)) (lyskom-error "%s" (lyskom-get-string 'filter-error-bad-not)) (setq key (car args) args (cdr args) inverse t))) (setq form (cond ((eq key 'author) (lyskom-filter-check-args 'stringp args) (` (and author (string-match (, (regexp-quote args)) (conf-stat->name author))))) ((eq key 'author-re) (lyskom-filter-check-args 'regexpp args) (` (and author (string-match (, args) (conf-stat->name author))))) ((eq key 'author-no) (lyskom-filter-check-args 'integerp args) (` (and author (= (, args) (conf-stat->conf-no author))))) ((eq key 'recipient) (lyskom-filter-check-args 'stringp args) (` (lyskom-filter-is-member string-match (, (regexp-quote args)) recipient-list conf-stat->name))) ((eq key 'recipient-re) (lyskom-filter-check-args 'regexpp args) (` (lyskom-filter-is-member string-match (, args) recipient-list conf-stat->name))) ((eq key 'recipient-no) (lyskom-filter-check-args 'integerp args) (` (lyskom-filter-is-member = (, args) recipient-list conf-stat->conf-no))) ((eq key 'subject) (lyskom-filter-check-args 'stringp args) (` (string-match (, (regexp-quote args)) subject))) ((eq key 'subject-re) (lyskom-filter-check-args 'regexpp args) (` (string-match (, args) subject))) ((eq key 'text) (lyskom-filter-check-args 'stringp args) (` (string-match (, (regexp-quote args)) text))) ((eq key 'text-re) (lyskom-filter-check-args 'regexpp args) (` (string-match (, args) text))) (t (lyskom-error (lyskom-get-string 'filter-error-unknown-key) key )))) (if inverse (setq form (list 'not form))) (cons form (lyskom-create-filter-function-body (cdr pattern)))))))) (defun lyskom-filter-check-args (fn arg) (if (not (funcall fn arg)) (lyskom-error (lyskom-get-string 'filter-error-key-arg) fn arg))) ;;; ============================================================ ;;; lyskom-filter-prompt ;;; ;;; Print a notice that a text has been filtered. ;;; (defun lyskom-filter-prompt (text-no prompt) (setq lyskom-filter-hack t) (let ((text-stat (blocking-do 'get-text-stat text-no)) (subject nil)) (if text-stat (blocking-do-multiple ((text (get-text text-no)) (conf-stat (get-conf-stat (text-stat->author text-stat)))) (if text (let ((str (text->decoded-text-mass text text-stat))) (setq subject (if (string-match "\n" str) (substring str 0 (match-beginning 0)) str)) (lyskom-format-insert prompt text-stat subject (or conf-stat (text-stat->author text-stat))) (lyskom-scroll)))))) (setq lyskom-filter-hack nil)) ;;;======================================== ;;; User functions and support functions ;;; (defun lyskom-add-filter (filter) "Add the filter FILTER to the LysKOM filtering mechanism." (if (filter->attribute filter 'expire) (setq kom-session-filter-list (cons filter kom-session-filter-list)) (progn (setq kom-permanent-filter-list (cons filter kom-permanent-filter-list)) (lyskom-save-options (current-buffer) (lyskom-get-string 'filter-edit-saving) (lyskom-get-string 'filter-edit-saving-done) (lyskom-get-string 'filter-edit-saving-error)))) (setq lyskom-filter-list (cons filter lyskom-filter-list))) (defun lyskom-filter-read-action () "Read a filter action from the minibuffer, returning its symbol" (let ((completion-ignore-case t)) (car (rassoc (lyskom-completing-read (lyskom-get-string 'filter-action) (lyskom-maybe-frob-completion-table (lyskom-reverse-pairs lyskom-filter-actions)) nil nil (cdr (car lyskom-filter-actions)) t) lyskom-filter-actions)))) (defun lyskom-filter-read-permanent () "Ask the user is a filter is permanent and return t in this case. Otherwise return nil." (lyskom-j-or-n-p (lyskom-get-string 'filter-permanent))) ;;;======================================== ;;; Filtrera ärende --- Filter subject ;;; (def-kom-command kom-filter-subject (&optional subject) "Interactively filter a subject. This creates a permanent or temporary filter for a single subject in one conference or all conferences. An alternative to this is `kom-super-jump'. To change existing filters, use `kom-filter-edit'." (interactive) (when (not (eq 0 lyskom-current-conf)) (let* (conf perm filter action) (setq subject (lyskom-read-from-minibuffer (lyskom-get-string 'filter-subject) (or subject lyskom-current-subject))) (setq filter (cons (cons 'subject subject) filter)) (setq conf (lyskom-read-conf-no 'filter-in-conf '(all) t nil t)) (if (not (eq conf 0)) (setq filter (cons (cons 'recipient-no conf) filter))) (setq action (lyskom-filter-read-action)) (setq perm (lyskom-filter-read-permanent)) (lyskom-add-filter (make-filter filter (list (cons 'action action) (cons 'expire (not perm)))))))) ;;;======================================== ;;; Filtrera författare --- Filter author ;;; (def-kom-command kom-filter-author () "Interactively filter an author. This creates a permanent or temporary filter on a single author in one conference or all conferences. To change existing filters, use `kom-filter-edit'." (interactive) (let (author conf filter action permanent) (setq author (lyskom-read-conf-no 'filter-author '(pers) t nil t)) (if (not (eq author 0)) (setq filter (cons (cons 'author-no author) filter))) (setq conf (lyskom-read-conf-no 'filter-in-conf '(all) t nil t)) (if (not (eq conf 0)) (setq filter (cons (cons 'recipient-no conf) filter))) (setq action (lyskom-filter-read-action)) (setq permanent (lyskom-filter-read-permanent)) (lyskom-add-filter (make-filter filter (list (cons 'action action) (cons 'expire (not permanent))))))) (def-kom-command kom-filter-recipient () "Interactively filter a recipient. This creates a permanent or temporary filter on a particular recipient. To change existing filters, use `kom-filter-edit'." (interactive) (let ((conf-no (lyskom-read-conf-no 'filter-recipient '(all) nil nil t)) (action (lyskom-filter-read-action)) (permanent (lyskom-filter-read-permanent))) (cond ((and conf-no (not (zerop conf-no))) (lyskom-add-filter (make-filter (list (cons 'recipient-no conf-no)) (list (cons 'action action) (cons 'expire (not permanent))))) )))) ;;;============================================================ ;;; ;;; Superhoppa ;;; (def-kom-command kom-super-jump (text-no) "Skip all texts and comments that share the subject and recipient of the selected text. This creates a temporary filter on the subject of the selected text in one of its recipients. The recipient is selected automatically: if the current conference is a recipient, then filter in that conference. Otherwise filter in the first recipient that the user is a member of. To change existing filters, use `kom-filter-edit'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'super-jump-q))) (if (or (null lyskom-current-text) (zerop lyskom-current-text)) (lyskom-insert-string 'have-to-read) (let ((text-stat (blocking-do 'get-text-stat lyskom-current-text)) (all-recipients nil) (recipients-member nil) (cc-recipients-member nil) (bcc-recipients-member nil) (recipients-nonmember nil) (cc-recipients-nonmember nil) (bcc-recipients-nonmember nil) (filter-recipient nil)) ;; Extract recipients into different lists (lyskom-traverse misc (text-stat->misc-info-list text-stat) (when (memq (misc-info->type misc) lyskom-recpt-types-list) (let* ((conf-no (misc-info->recipient-no misc)) (symbol (if (lyskom-get-membership conf-no) (cond ((eq (misc-info->type misc) 'RECPT) 'recipients-member) ((eq (misc-info->type misc) 'CC-RECPT) 'cc-recipients-member) ((eq (misc-info->type misc) 'BCC-RECPT) 'bcc-recipients-member)) (cond ((eq (misc-info->type misc) 'RECPT) 'recipients-nonmember) ((eq (misc-info->type misc) 'CC-RECPT) 'cc-recipients-nonmember) ((eq (misc-info->type misc) 'BCC-RECPT) 'bcc-recipients-nonmember))))) (set symbol (cons conf-no (symbol-value symbol))) (setq all-recipients (cons conf-no all-recipients))))) ;; Get the recipient to filter in (setq filter-recipient (or (and (memq lyskom-current-conf all-recipients) lyskom-current-conf) (car (nreverse recipients-member)) (car (nreverse cc-recipients-member)) (car (nreverse bcc-recipients-member)) (car (nreverse recipients-nonmember)) (car (nreverse cc-recipients-nonmember)) (car (nreverse bcc-recipients-nonmember)))) (if (null filter-recipient) (lyskom-insert-string 'no-recipient) (let ((text lyskom-current-subject)) (when (string-match "^\\s-*$" lyskom-current-subject) (setq text "")) (lyskom-add-filter (make-filter (list (cons 'subject-re (concat (if (string-equal text "") "^" "") "\\([rR][eE]: *\\|[Ff][Ww][Dd]: *\\)*" (replace-in-string (regexp-quote text) "[ \t]+" "[ \t]+") (if (string-equal text "") "$" ""))) (cons 'recipient-no filter-recipient)) (list (cons 'action 'skip-tree) (cons 'expire t)))) (lyskom-format-insert 'super-jump (copy-sequence lyskom-current-subject) filter-recipient)))))) ;;;============================================================ ;;; ;;; Filtrera text ;;; (def-kom-command kom-filter-text (&optional text) "Interactively filter on text contents. This creates a permanent or temporary filter on the contents of texts in all conferences or in a single conference. To change existing filters, use `kom-filter-edit'." (interactive) (when (not (eq 0 lyskom-current-conf)) (let ((conf nil) (action nil) (perm nil) (filter nil)) (setq text (lyskom-read-from-minibuffer (lyskom-get-string 'filter-which-text) (or text ""))) (setq filter (cons (cons 'text text) filter)) (setq conf (lyskom-read-conf-no 'filter-in-conf '(all) t nil t)) (if (not (eq conf 0)) (setq filter (cons (cons 'recipient-no conf) filter))) (setq action (lyskom-filter-read-action)) (setq perm (lyskom-filter-read-permanent)) (lyskom-add-filter (make-filter filter (list (cons 'action action) (cons 'expire (not perm)))))))) ;;;============================================================ ;;; Lista filter (kom-list-filters) ;;; ;;; Author: David Byers ;;; Calls internal functions in filter-edit mode. This may or ;;; may not be a good idea, but it works... (def-kom-command kom-list-filters () "Display all filters. This lists all filters in the LysKOM buffer. To change existing filters, use `kom-filter-edit'." (interactive) (let ((filters lyskom-filter-list)) (goto-char (point-max)) (if (null filters) (lyskom-insert (lyskom-get-string 'no-filters)) (progn (lyskom-insert (lyskom-get-string 'view-filters-header)) (while filters (goto-char (point-max)) (lyskom-format-filter-pattern (car filters)) (setq filters (cdr filters))) (lyskom-insert (lyskom-get-string 'view-filters-footer)))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: filter-edit.el,v 44.16 2005/01/09 01:16:02 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;;============================================================ ;;;;============================================================ ;;;; ;;;; File: filter-edit.el ;;;; ;;;; This file contains the filter editor ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: filter-edit.el,v 44.16 2005/01/09 01:16:02 byers Exp $\n")) (defvar filter-edit-currently-edited-filter-entry-list nil "List of filters currently being edited in a filter editor") (defvar filter-edit-change-flag nil) (defvar filter-edit-filter-list nil) (defvar filter-edit-list-start nil) (defvar filter-edit-list-end nil) (defun copy-filter-list (l) "Copy the filter list L" (cond ((null l) nil) (t (cons (copy-filter (car l)) (copy-filter-list (cdr l)))))) (defun lyskom-reverse-pairs (l) "Reverse the pairs in the assoc list L" (mapcar (function (lambda (e) (cons (cdr e) (car e)))) l)) ;;;======================================== ;;; Data types ;;; ;;; filter-entry ;;; Entry in the filter-entry list ;;; ;;; A filter entry is a vector consisting of ;;; ;;; [START END LINES PATTERN] ;;; ;;; START is the starting position (mark) in the buffer ;;; END is the ending position (mark) in the buffer ;;; LINES is a list of starting positions (marks) of the lines ;;; PATTERN is the filter displayed (type filter) ;;; (def-komtype filter-entry ((start :read-only t) (end :read-only t) lines (filter :read-only t))) ;;;============================================================ ;;; Verification functions ;;; (defun lyskom-verify-filter-list (filter) "Return non-nil if FILTER is a valid filter list" (cond ((null filter) t) ((not (listp filter)) nil) ((not (filter-p (car filter))) nil) (t (and (lyskom-verify-filter-pattern (filter->pattern (car filter))) (lyskom-verify-filter-list (cdr filter)))))) (defun lyskom-verify-filter-pattern (filter) "Return non-nil if FILTER is a valid filter pattern" (cond ((null filter) nil) ((and (= (length filter) 1) (symbolp (car filter))) t) ((not (listp (car filter))) nil) ((eq 'not (car (car filter))) (lyskom-verify-filter-pattern (cons (cdr (car filter)) (cdr filter)))) ((memq (car (car filter)) '(author-re recipient-re subject-re text-re)) (and (lyskom-filter-verify-regexp (cdr (car filter))) (lyskom-verify-filter-pattern (cdr filter)))) ((memq (car (car filter)) '(author subject recipient text)) (and (stringp (cdr (car filter))) (lyskom-verify-filter-pattern (cdr filter)))) ((memq (car (car filter)) '(author-no recipient-no)) (and (integerp (cdr (car filter))) (lyskom-verify-filter-pattern (cdr filter)))) (t nil))) (defun lyskom-filter-verify-regexp (re) "Return t if RE is a valid regexp." (condition-case nil (progn (string-match re "teststring") t) (error nil))) ;;;======================================== ;;; Locator functions ;;; (defun lyskom-filter-edit-lineno (where entry) "Return the line number at WHERE in the entry ENTRY. -1 means the header. 0 is the first line. Any number higher than the number of lines means outside the pattern." (let* ((lines (append (filter-entry->lines entry) (cons (filter-entry->end entry) nil))) (line -1) (current-line (length lines))) (if (>= where (filter-entry->start entry)) (while lines (if (< where (car lines)) (progn (setq current-line line) (setq lines nil)) (progn (setq lines (cdr lines)) (setq line (1+ line)))))) current-line)) (defun lyskom-filter-edit-locate (where) "Locate the entry at character position WHERE. nil means WHERE is not in any entry." (let ((entry-no (lyskom-filter-edit-locate-no where))) (if (= -1 entry-no) nil (elt filter-edit-currently-edited-filter-entry-list entry-no)))) (defun lyskom-filter-edit-locate-no (where) "Find the filter-edit-currently-edited-filter-entry-list index of the entry covering the character position WHERE. -1 means WHERE is not covered y any entry." (let ((i 0) (entry-no -1) (l filter-edit-currently-edited-filter-entry-list)) (while l (if (and (>= where (filter-entry->start (car l))) (<= where (filter-entry->end (car l)))) (progn (setq entry-no i) (setq l nil)) (progn (setq i (1+ i)) (setq l (cdr l))))) entry-no)) ;;;======================================== ;;; Formatting functions ;;; (defun lyskom-format-filter-list (filters) "Format the filter list FILTERS and insert the result into the current buffer. The buffer variable FILTER-EDIT-CURRENTLY-EDITED-FILTER-ENTRY-LIST is also updated." (let ((inhibit-read-only t)) (setq filter-edit-currently-edited-filter-entry-list nil) (lyskom-format-filter-list-2 filters) (setq filter-edit-currently-edited-filter-entry-list (nreverse filter-edit-currently-edited-filter-entry-list)))) (defun lyskom-format-filter-list-2 (filters) "Format the filter list FILTERS and insert the result into the current buffer." (cond ((null filters) nil) (t (setq filter-edit-currently-edited-filter-entry-list (cons (lyskom-format-filter-pattern (car filters)) filter-edit-currently-edited-filter-entry-list)) (lyskom-format-filter-list-2 (cdr filters))))) (defun lyskom-format-filter-pattern (pat) "Format and insert the filter pattern PAT into the current buffer. Returns an filter-entry structure representing the entry." (let ((inhibit-read-only t) start end lines) ;; ;; Insert text representation ;; (setq start (point-marker)) (lyskom-filter-format-entry-header pat t) (setq lines (lyskom-format-filter-pattern-2 (filter->pattern pat) nil)) (setq end (point-marker)) (insert "\n") (lyskom-create-filter-entry start end lines pat))) (defun lyskom-format-filter-pattern-2 (pat lines &optional neg) "Format and insert the body of the filter pattern PAT into the current buffer. Accumulate line starts in LINES. If NEG is non-nil, the first line will be negated." (cond ((or (null pat)) (nreverse lines)) ((eq (car (car pat)) 'not) (lyskom-format-filter-pattern-2 (cons (cdr (car pat)) (cdr pat)) lines t)) (t (setq lines (cons (point-marker) lines)) (lyskom-format-filter-pattern-insert pat neg) (lyskom-format-filter-pattern-2 (cdr pat) lines)))) (defun lyskom-format-filter-pattern-insert (pat neg) "Format and insert the first pattern in PAT. If NEG is non-nil, format the negation." (let (tmp) (insert (format " %s %s %S" (cdr (assoc (car (car pat)) lyskom-filter-what)) (if neg " != " " = ") (cdr (car pat)))) (cond ((memq (car (car pat)) '(recipient-no author-no)) (save-excursion (if (boundp 'lyskom-buffer) (set-buffer lyskom-buffer)) (setq tmp (blocking-do 'get-conf-stat (cdr (car pat))))) (insert (format " <%s>" (conf-stat->name tmp))))) (insert "\n"))) (defun lyskom-filter-format-entry-header (filter &optional newline action) "Format the header of a filter entry. FILTER is the filter to format. If NEWLINE is non-nil, insert a newline after the header." (let (permanent) (setq action (filter->attribute filter 'action) permanent (null (filter->attribute filter 'expire))) (insert (format "--- %s %s" (cdr (assq action lyskom-filter-actions )) (lyskom-get-string (if permanent 'permanent 'temporary)))) (if newline (insert "\n")))) ;;;======================================== ;;; User commands ;;; (defun lyskom-filter-edit-next-pattern (arg) "Move to the ARGth next pattern line in the current buffer." (interactive "p") (if (null arg) (setq arg 1)) (if (< arg 0) (lyskom-filter-edit-prev-entry (- arg)) (while (/= arg 0) (let ((entry-no (lyskom-filter-edit-locate-no (point))) tmp) (if (= -1 entry-no) (if (car filter-edit-currently-edited-filter-entry-list) (goto-char (filter-entry->start (car filter-edit-currently-edited-filter-entry-list))) (lyskom-error (lyskom-get-string 'filter-edit-empty-list))) (let* ((entry (elt filter-edit-currently-edited-filter-entry-list entry-no)) (lineno (lyskom-filter-edit-lineno (point) entry))) (cond ((= lineno -1) (if (filter-entry->lines entry) (setq tmp (car (filter-entry->lines entry))) (progn (setq tmp (elt filter-edit-currently-edited-filter-entry-list (1+ entry-no))) (if tmp (setq tmp (filter-entry->start tmp)) (lyskom-error (lyskom-get-string 'filter-edit-end-of-list)))))) ((= lineno (1- (length (filter-entry->lines entry)))) (setq tmp (elt filter-edit-currently-edited-filter-entry-list (1+ entry-no))) (if tmp (setq tmp (filter-entry->start tmp)) (lyskom-error (lyskom-get-string 'filter-edit-end-of-list)))) (t (setq tmp (elt (filter-entry->lines entry) (1+ lineno))))) (goto-char tmp) (setq arg (1- arg)))))))) (defun lyskom-filter-edit-prev-pattern (arg) "Move to the ARGth previous pattern line in the current buffer." (interactive "p") (if (null arg) (setq arg 1)) (if (< arg 0) (lyskom-filter-edit-next-entry (- arg)) (while (/= arg 0) (let ((entry-no (lyskom-filter-edit-locate-no (point))) tmp) (if (= -1 entry-no) (if (car filter-edit-currently-edited-filter-entry-list) (goto-char (filter-entry->start (car filter-edit-currently-edited-filter-entry-list))) (lyskom-error (lyskom-get-string 'filter-edit-empty-list))) (let* ((entry (elt filter-edit-currently-edited-filter-entry-list entry-no)) (lineno (lyskom-filter-edit-lineno (point) entry))) (cond ((= lineno -1) (if (= 0 entry-no) (lyskom-error (lyskom-get-string 'filter-edit-start-of-list)) (progn (setq entry (elt filter-edit-currently-edited-filter-entry-list (1- entry-no))) (setq tmp (car (nthcdr (1- (length (filter-entry->lines entry))) (filter-entry->lines entry)))) (if (null tmp) (setq tmp (filter-entry->start entry)))))) ((= lineno 0) (setq tmp (filter-entry->start entry))) (t (setq tmp (elt (filter-entry->lines entry) (1- lineno))))) (goto-char tmp) (setq arg (1- arg)))))))) (defun lyskom-filter-edit-next-entry (arg) "Move to the ARGth next entry in the current buffer." (interactive "p") (if (null arg) (setq arg 1)) (if (< arg 0) (lyskom-filter-edit-prev-entry (- arg)) (while (/= 0 arg) (let ((entry-no (lyskom-filter-edit-locate-no (point)))) (if (= -1 entry-no) (if (car filter-edit-currently-edited-filter-entry-list) (goto-char (filter-entry->start (car filter-edit-currently-edited-filter-entry-list))) (lyskom-error (lyskom-get-string 'filter-edit-empty-list))) (let ((tmp (elt filter-edit-currently-edited-filter-entry-list (1+ entry-no)))) (if tmp (progn (goto-char (filter-entry->start tmp)) (setq arg (1- arg))) (lyskom-error (lyskom-get-string 'filter-edit-end-of-list))))))))) (defun lyskom-filter-edit-prev-entry (arg &optional noerror) "Move to the ARGth previous entry in the current buffer." (interactive "p") (not (catch 'fail (if (null arg) (setq arg 1)) (if (< arg 0) (lyskom-filter-edit-next-entry (- arg)) (while (/= 0 arg) (let ((entry-no (lyskom-filter-edit-locate-no (point)))) (if (= -1 entry-no) (if (car filter-edit-currently-edited-filter-entry-list) (goto-char (filter-entry->start (car filter-edit-currently-edited-filter-entry-list))) (if noerror (throw 'fail t) (lyskom-error (lyskom-get-string 'filter-edit-empty-list))))) (if (= 0 entry-no) (if noerror (throw 'fail t) (lyskom-error (lyskom-get-string 'filter-edit-start-of-list))) (let ((tmp (elt filter-edit-currently-edited-filter-entry-list (1- entry-no)))) (setq arg (1- arg)) (goto-char (filter-entry->start tmp)))))))))) (defun lyskom-filter-edit-beginning-of-list () "Move to the first entry in the list" (interactive) (if (null filter-edit-currently-edited-filter-entry-list) (lyskom-error (lyskom-get-string 'filter-edit-empty-list)) (progn (push-mark) (goto-char (filter-entry->start (car filter-edit-currently-edited-filter-entry-list)))))) (defun lyskom-filter-edit-end-of-list () "Move to the last entry in the list" (interactive) (if (null filter-edit-currently-edited-filter-entry-list) (lyskom-error (lyskom-get-string 'filter-edit-empty-list)) (let ((entry (elt filter-edit-currently-edited-filter-entry-list (1- (length filter-edit-currently-edited-filter-entry-list))))) (push-mark) (goto-char (or (elt (filter-entry->lines entry) (1- (length (filter-entry->lines entry)))) (filter-entry->start entry)))))) (defun lyskom-filter-edit-insert-entry () "Add an entry to the end of the list" (interactive) (let ((inhibit-read-only t) (completion-ignore-case t) (rev-actions (lyskom-reverse-pairs lyskom-filter-actions)) action permanent filter start end entry) (if filter-edit-currently-edited-filter-entry-list (progn (goto-char (filter-entry->end (elt filter-edit-currently-edited-filter-entry-list (1- (length filter-edit-currently-edited-filter-entry-list))))) (insert "\n")) (goto-char filter-edit-list-end)) (setq action (lyskom-completing-read (lyskom-get-string 'filter-edit-filter-how) (lyskom-maybe-frob-completion-table rev-actions) nil t)) (setq permanent (lyskom-j-or-n-p (lyskom-get-string 'filter-permanent))) (setq filter (make-filter nil (list (cons 'action (cdr (assoc action rev-actions))) (cons 'expire (not permanent))))) (setq start (point-marker)) (lyskom-filter-format-entry-header filter t) (setq end (point-marker)) (setq entry (lyskom-create-filter-entry start end nil filter)) (if filter-edit-currently-edited-filter-entry-list (setcdr (nthcdr (1- (length filter-edit-currently-edited-filter-entry-list)) filter-edit-currently-edited-filter-entry-list) (cons entry nil)) (setq filter-edit-currently-edited-filter-entry-list (cons entry nil))) (setq filter-edit-change-flag t) (goto-char start))) (defun lyskom-filter-edit-insert-pattern () "Add a pattern line to the current list entry." (interactive) (let ((entry-no (lyskom-filter-edit-locate-no (point)))) (if (= -1 entry-no) (lyskom-error (lyskom-get-string 'filter-edit-outside-entry)))) (let ((what nil) (pred nil) (arg nil) (argstring nil) (lineno nil) (entry nil) (filter nil) (pat nil) (inhibit-read-only t) (completion-ignore-case t) (rev-what (lyskom-reverse-pairs lyskom-filter-what))) (setq what (lyskom-completing-read (lyskom-get-string 'filter-edit-filter-what) (lyskom-maybe-frob-completion-table rev-what) nil t)) (setq pred (lyskom-completing-read (lyskom-format 'filter-edit-insert-pred what) (lyskom-maybe-frob-completion-table lyskom-filter-predicate-list t) nil t)) (setq argstring (lyskom-read-from-minibuffer (lyskom-format 'filter-edit-insert-arg what pred))) (setq what (cdr (assoc what rev-what))) (if (not (cond ((memq what '(author subject text recipient)) (setq arg argstring)) ((memq what '(author-no recipient-no)) (setq arg (string-to-int argstring))) ((memq what '(author-re subject-re text-re recipient-re)) (setq arg argstring) (lyskom-filter-verify-regexp arg)))) (lyskom-error (lyskom-get-string 'filter-edit-bad-argument) argstring)) ;; ;; Build pattern ;; (setq pat (cons what arg)) (if (cdr (assoc pred (lyskom-maybe-frob-completion-table lyskom-filter-predicate-list t))) (setq pat (cons 'not pat))) ;; ;; Locate current entry ;; Locate current line ;; (setq entry (lyskom-filter-edit-locate (point))) (setq lineno (lyskom-filter-edit-lineno (point) entry)) (setq filter (filter-entry->filter entry)) ;; ;; Splice the new pattern into the old pattern at the ;; proper position. If lineno is -1 (the cursor is not in ;; the pattern area, append the pattern. ;; (if (= -1 lineno) (setq lineno (length (filter->pattern filter)))) (cond ((= lineno 0) (set-filter->pattern filter (cons pat (filter->pattern filter)))) (t (if (filter->pattern filter) (setcdr (nthcdr (1- lineno) (filter->pattern filter)) (cons pat (nthcdr lineno (filter->pattern filter)))) (set-filter->pattern filter pat)))) ;; ;; Update display ;; (if (= lineno (length (filter-entry->lines entry))) (goto-char (filter-entry->end entry)) (goto-char (elt (filter-entry->lines entry) lineno))) ;; ;; OK, right now, POINT is on top os a marker that represents the ;; NEXT line. This marker must be puched forward to avoid duplicating ;; it. ;; (forward-line -1) (end-of-line) (insert "\n") (lyskom-format-filter-pattern-insert (cons (if (eq (car pat) 'not) (cdr pat) pat) nil) (eq (car pat) 'not)) (forward-char -1) (delete-char 1) (beginning-of-line) ;; ;; Update lines list in the entry ;; (cond ((= lineno 0) (set-filter-entry->lines entry (cons (point-marker) (filter-entry->lines entry)))) (t (setcdr (nthcdr (1- lineno) (filter-entry->lines entry)) (cons (point-marker) (nthcdr lineno (filter-entry->lines entry)))))) (setq filter-edit-change-flag t))) (defun lyskom-filter-edit-delete-pattern (arg) "Delete ARG pattern lines, starting with the one at point. Only lines in the current entry will be deleted." (interactive "p") (let* ((inhibit-read-only t) (entry (lyskom-filter-edit-locate (point))) (filter (filter-entry->filter entry))) (if (null entry) (lyskom-error (lyskom-get-string 'filter-edit-outside-list)) (progn (while (/= 0 arg) (let ((lineno (lyskom-filter-edit-lineno (point) entry))) (if (null arg) (setq arg 1)) (if (and (> lineno -1) (< lineno (length (filter-entry->lines entry)))) (progn (setq arg (1- arg)) (setq lineno (lyskom-filter-edit-lineno (point) entry)) (delete-region (save-excursion (beginning-of-line) (point)) (1+ (save-excursion (end-of-line) (point)))) (if (= lineno (1- (length (filter-entry->lines entry)))) (forward-line -1)) (if (= lineno 0) (progn (set-filter-entry->lines entry (cdr (filter-entry->lines entry))) (set-filter->pattern filter (cdr (filter->pattern filter))) (setq filter-edit-change-flag t)) (progn (setcdr (nthcdr (1- lineno) (filter-entry->lines entry)) (nthcdr (1+ lineno) (filter-entry->lines entry))) (setcdr (nthcdr (1- lineno) (filter->pattern (filter-entry->filter entry))) (nthcdr (1+ lineno) (filter->pattern (filter-entry->filter entry)))) (setq filter-edit-change-flag t)))) (lyskom-error (lyskom-get-string 'filter-edit-end-of-pattern))))))))) (defun lyskom-filter-edit-delete-entry (arg &optional which noerror) "Delete ARG entries, starting with the one covering point. If optional WHICH is non-nil, start with entry number WHICH. If NOERROR is non-nil, return nil instead of signaling an error." (interactive "p") (let ((inhibit-read-only t)) (not (catch 'fail (if (null arg) (setq arg 1)) (while (/= 0 arg) (let* ((entry-no (or which (lyskom-filter-edit-locate-no (point)))) (entry nil)) (if (= -1 entry-no) (if noerror (throw 'fail t) (lyskom-error (lyskom-get-string 'filter-edit-end-of-list)))) (setq entry (elt filter-edit-currently-edited-filter-entry-list entry-no)) (delete-region (filter-entry->start entry) (1+ (filter-entry->end entry))) (cond ((= 0 entry-no) (setq filter-edit-currently-edited-filter-entry-list (cdr filter-edit-currently-edited-filter-entry-list)) (setq filter-edit-change-flag t)) (t (setcdr (nthcdr (1- entry-no) filter-edit-currently-edited-filter-entry-list) (nthcdr (1+ entry-no) filter-edit-currently-edited-filter-entry-list)) (setq filter-edit-change-flag t))) (if (= entry-no (length filter-edit-currently-edited-filter-entry-list)) (progn (if (lyskom-filter-edit-prev-entry 1 t) (setq arg 0) (throw 'fail t))) (setq arg (1- arg))))))))) (defun lyskom-filter-edit-quit () "Quit filter edit mode and ask to save changes (if any)" (interactive) (let ((save nil)) (if filter-edit-change-flag (setq save (lyskom-j-or-n-p (lyskom-get-string 'filter-edit-save-p)))) (if save (lyskom-filter-edit-save)) (set-window-configuration lyskom-edit-return-to-configuration))) (defun lyskom-filter-edit-expunge () "Delete all entries that are completely empty" (interactive) (let ((e filter-edit-currently-edited-filter-entry-list) (index 0)) (while e (if (null (filter-entry->lines (car e))) (lyskom-filter-edit-delete-entry 1 index t) (setq index (1+ index))) (setq e (cdr e))))) (defun lyskom-filter-empty-patterns-p () "Return non-nil if the entry list contains empty entries." (let ((e filter-edit-currently-edited-filter-entry-list) (result nil)) (while e (if (null (filter-entry->lines (car e))) (progn (setq e nil) (setq result t)) (setq e (cdr e)))) result)) (defun lyskom-filter-edit-save () "Save changes in filter edit mode" (interactive) (if (and (lyskom-filter-empty-patterns-p) (lyskom-j-or-n-p (lyskom-get-string 'filter-edit-remove-empty))) (lyskom-filter-edit-expunge)) (let ((e filter-edit-currently-edited-filter-entry-list) (xpermanent-list nil) (xtemporary-list nil)) (while e (set-filter->function (filter-entry->filter (car e)) (lyskom-create-compile-filter-function (filter->pattern (filter-entry->filter (car e))))) (set (if (filter->attribute (filter-entry->filter (car e)) 'expire) 'xtemporary-list 'xpermanent-list) (cons (filter-entry->filter (car e)) (if (filter->attribute (filter-entry->filter (car e)) 'expire) xtemporary-list xpermanent-list))) (setq e (cdr e))) (save-excursion (set-buffer lyskom-buffer) (setq lyskom-filter-list (append (setq kom-permanent-filter-list (nreverse xpermanent-list)) (setq kom-session-filter-list (nreverse xtemporary-list)))) (setq filter-edit-change-flag nil) (lyskom-message "%s" (lyskom-get-string 'filter-edit-saving)) (lyskom-save-options lyskom-buffer (lyskom-get-string 'filter-edit-saving) (lyskom-get-string 'filter-edit-saving-done) (lyskom-get-string 'filter-edit-saving-error))))) (defun lyskom-filter-edit-revert () "Discard changes and restart editing" (interactive) (if (or (not filter-edit-change-flag) (and filter-edit-change-flag (lyskom-j-or-n-p (lyskom-get-string 'filter-edit-restart-p)))) (let ((inhibit-read-only t)) (setq filter-edit-currently-edited-filter-entry-list nil) (delete-region filter-edit-list-start filter-edit-list-end) (goto-char filter-edit-list-start) (insert "\n") (lyskom-format-filter-list (copy-filter-list lyskom-filter-list)) (setq filter-edit-change-flag nil) (lyskom-filter-edit-beginning-of-list)))) (defun lyskom-filter-edit-toggle-permanent () "Toggle the permanent flag of the current entry" (interactive) (let ((entry-no (lyskom-filter-edit-locate-no (point))) (inhibit-read-only t)) (if (= -1 entry-no) (lyskom-error (lyskom-get-string 'filter-edit-outside-entry))) (let ((entry (elt filter-edit-currently-edited-filter-entry-list entry-no))) (set-filter->attribute (filter-entry->filter entry) 'expire (not (filter->attribute (filter-entry->filter entry) 'expire))) (setq filter-edit-change-flag t) (save-excursion (goto-char (filter-entry->start entry)) (delete-region (point) (save-excursion (end-of-line) (point))) (lyskom-filter-format-entry-header (filter-entry->filter entry)))))) (defun lyskom-filter-edit-toggle-action () "Toggle the filter action of the current entry." (interactive) (let ((entry-no (lyskom-filter-edit-locate-no (point))) (inhibit-read-only t)) (if (= -1 entry-no) (lyskom-error (lyskom-get-string 'filter-edit-outside-entry))) (let* ((entry (elt filter-edit-currently-edited-filter-entry-list entry-no)) (action-list lyskom-filter-actions) (action (car (cdr (memq (assq (filter->attribute (filter-entry->filter entry) 'action) action-list) action-list)))) (new-action (or action (car action-list)))) (setq filter-edit-change-flag t) (set-filter->attribute (filter-entry->filter entry) 'action (car new-action)) (save-excursion (goto-char (filter-entry->start entry)) (delete-region (point) (save-excursion (end-of-line) (point))) (lyskom-filter-format-entry-header (filter-entry->filter entry)))))) (defun lyskom-filter-edit-brief-help () "Display a help message in the minibuffer." (interactive) (lyskom-message "%s" (lyskom-get-string 'filter-edit-help))) (defun lyskom-filter-edit-mode () "\\Mode for editing LysKOM filters. Entry to this mode runs lyskom-filter-edit-hook Commands: \\[lyskom-filter-edit-prev-pattern] Moves up in the pattern list. \\[lyskom-filter-edit-next-pattern] Moves down in the pattern list. \\[lyskom-filter-edit-prev-entry] Moves up one filter in the list. \\[lyskom-filter-edit-next-entry] Moves down one filter in the list. \\[lyskom-filter-edit-beginning-of-list] Moves to the beginning of the list. \\[lyskom-filter-edit-end-of-list] Moves to the end of the list. \\[lyskom-filter-edit-delete-pattern] Deletes the pattern line at point. \\[lyskom-filter-edit-delete-entry] Deletes the filter containing point. \\[lyskom-filter-edit-insert-pattern] Inserts a pattern line at point. \\[lyskom-filter-edit-insert-entry] Inserts a new filter into the list. \\[lyskom-filter-edit-expunge] Deletes all empty filters from the list. \\[lyskom-filter-edit-revert] Discards all changes to the list. \\[lyskom-filter-edit-toggle-action] Toggles the filter action of the filter containing point. \\[lyskom-filter-edit-toggle-permanent] Toggles between permanent and temporary. \\[lyskom-filter-edit-save] Saves the filters. \\[lyskom-filter-edit-quit] Quit and return to LysKOM. All key bindings: \\{lyskom-filter-edit-map} " (interactive) (kill-all-local-variables) (make-local-variable 'filter-edit-currently-edited-filter-entry-list) (make-local-variable 'filter-edit-change-flag) (make-local-variable 'filter-edit-filter-list) (make-local-variable 'filter-edit-list-start) (make-local-variable 'filter-edit-list-end) (make-local-variable 'lyskom-buffer) (make-local-variable 'lyskom-edit-return-to-configuration) (setq buffer-read-only t) (setq filter-edit-change-flag nil) (buffer-disable-undo (current-buffer)) (lyskom-use-local-map lyskom-filter-edit-map) (setq mode-name "LysKOM Filter Edit") (setq major-mode 'lyskom-filter-edit-mode) (setq local-abbrev-table 'lyskom-filter-edit-abbrev-table) (run-hooks 'lyskom-filter-edit-hook)) ;;;======================================== ;;; LysKOM command to start editing ;;; (defun kom-filter-edit () "Interactively edit text filters. This command starts a special mode in which it is possble to create and alter filters. Use this to remove undesired filters and to create complex filters." (interactive) (let ((buf (current-buffer)) (filters lyskom-filter-list) (server-name lyskom-server-name) (curwin (current-window-configuration))) (lyskom-display-buffer (lyskom-get-buffer-create 'edit-filters (concat (buffer-name buf) "-" (lyskom-get-string 'filter-edit-buffer-name)) t)) (let ((inhibit-read-only t)) (erase-buffer)) (lyskom-filter-edit-mode) (setq lyskom-buffer buf) (let ((inhibit-read-only t)) (setq filter-edit-filter-list filters) (insert (format (lyskom-get-string 'filter-edit-header) server-name)) (setq filter-edit-list-start (point-marker)) (insert "\n") (lyskom-format-filter-list (copy-filter-list filter-edit-filter-list)) (setq filter-edit-list-end (point-max-marker))) (setq lyskom-edit-return-to-configuration curwin) (lyskom-filter-edit-beginning-of-list))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;; $Id: lyskom-buttons.el,v 44.99 2005/01/11 15:00:13 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: lyskom-buttons.el ;;;; Author: David Byers ;;;; ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: lyskom-buttons.el,v 44.99 2005/01/11 15:00:13 _cvs_pont_lyskomelisp Exp $\n")) (lyskom-external-function glyph-property) (lyskom-external-function widget-at) (lyskom-external-function widget-get) (lyskom-external-function w3-widget-button-click) (lyskom-external-function w3-popup-menu) (lyskom-external-function Info-goto-node) (lyskom-external-function term-char-mode) (lyskom-external-function w3m) (defun lyskom-add-button-action (type text func) "Add a new action to the popup menu for a class of objects. Arguments are TYPE, the type of object to adjust, TEXT the menu text for the action and FUNC, the function to call when the action is selected. By default TYPE may be any one of text, conf, pers or url although users can add other types. FUNC must be a function with three arguments, BUFFER, ARGUMENT and TEXT. BUFFER is the LysKOM buffer that the command should use, TEXT is the text of the selected button and ARGUMENT is the data argument associated with the object. For button type text it is a text number. For types conf and pers it is the conference number for the object. For URLs it is the text of the URL (a string) or NIL. For other (user-defined) types, it is a string. For more information on button types and arguments, see the documentation for the variable lyskom-text-buttons." (nconc (nth 3 (assq type lyskom-button-actions)) (list (cons text func)))) (defun kom-previous-link (num) "Move the cursor to the previous active area in the LysKOM buffer." (interactive "p") (lyskom-prev-area num 'lyskom-button)) (defun kom-next-link (num) "Move the cursor to the next active area in the LysKOM buffer." (interactive "p") (lyskom-next-area num 'lyskom-button)) (defun kom-button-press-or-self-insert-command () "Simulate a mouse button press at point, if there is a button." (interactive) (if (get-text-property (point) 'lyskom-button) (call-interactively 'kom-button-press) (call-interactively 'self-insert-command))) (defun kom-button-press () "Simulate a mouse button press at point." (interactive) (let* ((type (get-text-property (point) 'lyskom-button-type)) (data (assq type lyskom-button-actions)) (hint (get-text-property (point) 'lyskom-button-hint)) (act (or (and kom-use-button-hints hint) (and data (elt data 2))))) (cond ((null data) (lyskom-button-press (point))) ((null act) (lyskom-button-menu (point) 'key)) (t (lyskom-button-press (point)))))) (defun kom-menu-button-press-or-self-insert-command () "Simulate a menu mouse button press at point, if there is a button." (interactive) (if (get-text-property (point) 'lyskom-button) (call-interactively 'kom-menu-button-press) (call-interactively 'self-insert-command))) (defun kom-menu-button-press () "Simulate a menu mouse button press at point." (interactive) (lyskom-button-menu (point) 'key)) (defun kom-button-click (event &optional do-default) "Execute the default action of the active area under the mouse. If optional argument do-default is non-nil, call the default binding of this-command-keys." (interactive "@e") (let* ((pos (lyskom-event-point event)) (glyph (lyskom-event-glyph event)) (widget (and pos (or (and glyph (glyph-property glyph 'widget)) (widget-at pos)))) (parent (and widget (widget-get widget ':parent))) (href (or (and widget (widget-get widget ':href)) (and parent (widget-get parent ':href)) (and widget (widget-get widget 'href)) (and parent (widget-get parent 'href)))) (w3m-url (and pos (get-text-property pos 'w3m-href-anchor))) (type (and pos (get-text-property pos 'lyskom-button-type))) (data (and type (assq type lyskom-button-actions))) (hint (and pos (get-text-property pos 'lyskom-button-hint))) (act (or (and kom-use-button-hints hint) (and data (elt data 2))))) (cond (href (require 'w3) (w3-widget-button-click event)) (w3m-url (require 'w3m) (w3m w3m-url)) ((and do-default (or (null pos) (null (get-text-property pos 'lyskom-button-type)))) (let ((fn (lookup-key global-map (this-command-keys)))) (when (commandp fn) (call-interactively fn)))) ((null act) (kom-popup-menu event)) (t (lyskom-button-press pos))))) (defun kom-button-click-or-yank (event) "Execute the default action of the active area under the mouse. If there is no active area, then do something else." (interactive "@e") (kom-button-click event t)) (defun kom-popup-menu (event) "Pop up a menu of actions to be taken at the active area under the mouse." (interactive "@e") (let* ((pos (lyskom-event-point event)) (glyph (lyskom-event-glyph event)) (widget (and pos (or (and glyph (glyph-property glyph 'widget)) (widget-at pos)))) (parent (and widget (widget-get widget ':parent))) (href (or (and widget (widget-get widget ':href)) (and parent (widget-get parent ':href)) (and widget (widget-get widget 'href)) (and parent (widget-get parent 'href))))) (cond (href (require 'w3) (w3-popup-menu event)) ((and pos (get-text-property pos 'lyskom-button-type)) (lyskom-button-menu pos event)) (t (lyskom-background-menu pos event))))) (defun kom-mouse-null (event) "Do nothing." (interactive "@e") ;; This is here to pervent unwanted events when clicking mouse-3 (identity 1)) (defun lyskom-make-button-menu (title entries buf arg text) "Create a menu keymap from a list of button actions." ;; Use the command as the event for simplicity. Note that the menu ;; function alters the menu, so we copy the entries to prevent it ;; from fiddling with lyskom-button-actions. (let* ((lyskom-language lyskom-global-language) (title (lyskom-maybe-recode-string title 'iso-8859-1 t))) (when (> (length title) 44) (setq title (concat (substring title 0 40) " ..."))) (cond ((string-match "XEmacs" (emacs-version)) (cons (lyskom-maybe-recode-string title 'iso-8859-1 t) (mapcar (function (lambda (entry) (vector (lyskom-maybe-recode-string (lyskom-get-string (car entry)) 'iso-8859-1 t) (list (cdr entry) buf (if (listp arg) (list 'quote arg) arg) text) ':active t))) entries))) (t (append (list 'keymap title) (mapcar (function (lambda (entry) (let ((tmp (copy-tree entry))) (setcar tmp (lyskom-maybe-recode-string (lyskom-get-string (car tmp)) 'iso-8859-1 t)) (cons (` ((, (cdr entry)) (, buf) (, arg) (, text))) tmp)))) entries)))))) (defun lyskom-button-menu (pos event) "Internal function used by kom-popup-menu" (let* ((type (get-text-property pos 'lyskom-button-type)) (arg (get-text-property pos 'lyskom-button-arg)) (text (get-text-property pos 'lyskom-button-text)) (buf (get-text-property pos 'lyskom-buffer)) (data (assq type lyskom-button-actions)) (title (cond ((get-text-property pos 'lyskom-button-menu-title) (apply 'lyskom-format (get-text-property pos 'lyskom-button-menu-title))) ((elt data 1) (lyskom-format (lyskom-get-string (elt data 1)) text)) (t (lyskom-format (lyskom-get-string 'generic-popup-title) text)))) (actl (or (and data (elt data 3)) nil))) (cond ((null data) (goto-char pos)) ((null actl) (goto-char pos)) ((null buf) (goto-char pos)) ((null (get-buffer buf)) (lyskom-message "%s" (lyskom-get-string 'no-such-buffer))) (t (if (symbolp title) (setq title (lyskom-get-string title))) (set-buffer buf) ;; There is a simple bug in x-popup-menu which causes menus ;; from simple keymaps to be title-less. A list consisting ;; of a single keymap works better. A patch is submittet to ;; the GNU folks. /davidk (if (eq event 'key) (lyskom-keyboard-menu title actl buf arg text) (let* ((menu (lyskom-make-button-menu title actl buf arg text))) (lyskom-do-popup-menu menu event))))))) (defun lyskom-keyboard-menu (title entries buf arg text) "Do a keyboard menu selection." (let* ((prompt nil) (maxlen 0) (entries (mapcar (lambda (el) (cons (if (stringp (car el)) (car el) (lyskom-get-string (car el))) (cdr el))) entries)) (title (if (stringp title) title (lyskom-get-string title))) (completion-ignore-case t)) (lyskom-traverse e entries (if (> (lyskom-string-width (car e)) maxlen) (setq maxlen (lyskom-string-width (car e))))) (setq prompt (substring title 0 (min (lyskom-string-width title) (- (window-width (minibuffer-window)) maxlen 3)))) (let ((choice (lyskom-read-from-menu prompt (lyskom-maybe-frob-completion-table entries t)))) (when choice (funcall (cdr choice) buf arg text))))) (defun lyskom-button-press (pos) "Execute the default action of the active area at POS if any." (when pos (let* ((type (get-text-property pos 'lyskom-button-type)) (arg (get-text-property pos 'lyskom-button-arg)) (text (get-text-property pos 'lyskom-button-text)) (buf (get-text-property pos 'lyskom-buffer)) (hint (get-text-property pos 'lyskom-button-hint)) (data (assq type lyskom-button-actions)) (act (or (and kom-use-button-hints hint) (and data (elt data 2))))) (cond ((null act) (goto-char pos)) ((null buf) (goto-char pos)) ((and buf (null (get-buffer buf))) (lyskom-message "%s" (lyskom-get-string 'no-such-buffer))) (t (and buf (set-buffer buf)) (funcall act buf arg text)))))) (defun lyskom-fix-pseudo-url (url) (save-match-data (if (not (string-match lyskom-url-protocol-regexp url)) (cond ((string-match "^www\\." url) (concat "http://" url)) ((string-match "^ftp\\." url) (concat "ftp://" url)) ((string-match "^gopher\\." url) (concat "gopher://" url)) ((string-match "^wais\\." url) (concat "wais://" url)) (t (concat "http://" url))) url))) (defun lyskom-button-add-links (text links) "Add links to TEXT according to LINKS. LINKS is a list of lyskom-text-link objects." (lyskom-traverse spec links (let ((case-fold-search (lyskom-text-link->ignore-case spec)) (start 0)) (while (string-match (lyskom-text-link->pattern spec) text start) ;; Need to do this here since replace-in-string fscks up match-data (setq start (match-end 0)) (add-text-properties (or (match-beginning (lyskom-text-link->highlight spec)) (match-beginning 0)) (or (match-end (lyskom-text-link->highlight spec)) (match-end 0)) (lyskom-generate-button 'url nil (replace-in-string (match-string 0 text) (lyskom-text-link->pattern spec) (lyskom-text-link->replacement spec)) kom-url-face) text))))) (defun lyskom-button-get-arg (el text) "Get the button argument for button type EL from TEXT according to the current match-data." (let ((no (or (elt el 3) 0))) (substring text (match-beginning no) (match-end no)))) (defun lyskom-button-get-text (el text) "Get the button text for button type EL from TEXT according to the current match-data." (let ((no (or (elt el 2) 0))) (substring text (match-beginning no) (match-end no)))) (defun lyskom-button-get-face (el) "Get the button face for button type EL from TEXT according to the current match-data." (let ((face (elt el 4))) (or (and (boundp face) (symbol-value face)) (and (facep face) face)))) (defsubst lyskom-button-get-pred (el) "Return the match predicate for bitton type EL." (elt el 5)) (defun lyskom-button-transform-text (text &optional text-stat) "Add text properties to the string TEXT according to the definition of lyskom-text-buttons. Returns the modified string." (let ((blist lyskom-text-buttons) (rcpts (reverse (and text-stat (lyskom-text-recipients text-stat)))) (start 0) (el nil)) ;; Do other text buttons (while blist (setq el (car blist)) (setq start 0) (while (string-match (elt el 0) text start) (if (or (null (lyskom-button-get-pred el)) (funcall (lyskom-button-get-pred el) (lyskom-button-get-text el text))) (progn (add-text-properties (match-beginning (or (elt el 2) 0)) (match-end (or (elt el 2) 0)) (cond ((and (eq (elt el 1) 'text) (not lyskom-transforming-external-text)) (lyskom-generate-button 'text (lyskom-button-get-arg el text) (lyskom-button-get-text el text) (lyskom-button-get-face el))) ((eq (elt el 1) 'conf) (lyskom-generate-button 'conf (lyskom-button-get-arg el text) (lyskom-button-get-text el text) (lyskom-button-get-face el))) ((eq (elt el 1) 'pers) (lyskom-generate-button 'pers (lyskom-button-get-arg el text) (lyskom-button-get-text el text) (lyskom-button-get-face el))) ((eq (elt el 1) 'url) (lyskom-generate-button 'url nil (lyskom-button-get-text el text) (lyskom-button-get-face el))) ((eq (elt el 1) 'pseudo-url) (let ((url (lyskom-fix-pseudo-url (lyskom-button-get-text el text)))) (lyskom-generate-button 'url nil url (lyskom-button-get-face el)))) ((eq (elt el 1) 'info-node) (lyskom-generate-button 'info-node (lyskom-button-get-arg el text) (lyskom-button-get-text el text) (lyskom-button-get-face el))) ((eq (elt el 1) 'email) (lyskom-generate-button 'email nil (lyskom-button-get-text el text) (lyskom-button-get-face el))) (t nil)) text) (setq start (match-end 0))) (setq start (1+ (match-beginning 0))))) (setq blist (cdr blist))) ;; Do links from kom-text-links last -- they have precedence ;; Do the first recipient last so links for that rcpt have prio (lyskom-traverse rcpt rcpts (lyskom-button-add-links text (cdr (assq rcpt kom-text-links)))) ;; Do global links from kom-text-links very last (lyskom-button-add-links text (cdr (assq t kom-text-links))) ) text) (defun lyskom-get-button-hint (hints) "Get the hint to be used right now (if any) from HINTS" (let ((result nil) (hint nil)) (while (and hints (null result)) (setq hint (car hints)) (setq hints (cdr hints)) (cond ((null (car hint)) (if (and (eq lyskom-current-function (elt hint 1)) (or (null (elt hint 2)) (eq lyskom-current-function-phase (elt hint 2)))) (setq result (elt hint 3)))) ((listp (car hint)) (if (and lyskom-executing-command (memq lyskom-current-command (car hint))) (setq result (cdr hint)))) ((symbolp (car hint)) (if (and lyskom-executing-command lyskom-current-command (eq lyskom-current-command (car hint))) (setq result (cdr hint)))))) result)) (defun lyskom-generate-button (type arg &optional text face menu-title subtle) "Generate the properties for a button of type TYPE with argument ARG. Optional argument TEXT is the button text to be saved as a property and FACE is the default text face for the button. Optional argument MENU-TITLE defines the title for the popup menu. See lyskom-default-button for more information. Optional argument SUBTLE means don't set the lyskom-button property if non-nil. that means kom-next- and -previous-link won't notice the button" (setq lyskom-dummy-variable-to-fool-the-byte-compiler (car menu-title)) ; produce error if menu-title not cons (let* ((numarg (cond ((numberp arg) arg) ((stringp arg) (string-to-number arg)) ((lyskom-conf-stat-p arg) (conf-stat->conf-no arg)) ((lyskom-uconf-stat-p arg) (uconf-stat->conf-no arg)) ((lyskom-pers-stat-p arg) (pers-stat->pers-no arg)) (t nil))) (data (assq type lyskom-button-actions)) (hints (and data (elt data 4))) (the-hint (lyskom-get-button-hint hints)) (props (cond ((and (memq type '(conf pers)) numarg) (list 'face (or face (or (lyskom-traverse el kom-highlight-conferences (cond ((and (symbolp (car el)) (boundp (car el)) (listp (symbol-value (car el))) (memq numarg (symbol-value (car el)))) (lyskom-traverse-break (cond ((facep (cdr el)) (cdr el)) ((and (symbolp (cdr el)) (boundp (cdr el))) (symbol-value (cdr el)))))) ((and (symbolp (car el)) (boundp (car el)) (eq numarg (symbol-value (car el)))) (lyskom-traverse-break (cond ((facep (cdr el)) (cdr el)) ((and (symbolp (cdr el)) (boundp (cdr el))) (symbol-value (cdr el)))))) ((and (functionp (car el)) (funcall (car el) arg)) (lyskom-traverse-break (cond ((facep (cdr el)) (cdr el)) ((and (symbolp (cdr el)) (boundp (cdr el))) (symbol-value (cdr el)))))) ((and (listp (car el)) (memq numarg (car el))) (lyskom-traverse-break (cond ((facep (cdr el)) (cdr el)) ((and (symbolp (cdr el)) (boundp (cdr el))) (symbol-value (cdr el))))))) nil) kom-active-face)) 'mouse-face kom-highlight-face 'lyskom-button-text text 'lyskom-button-type type 'lyskom-button-arg numarg 'lyskom-button-menu-title menu-title 'lyskom-buffer lyskom-buffer)) ((and (eq type 'text) numarg) (list 'face (or face kom-text-no-face) 'mouse-face kom-highlight-face 'lyskom-button-text text 'lyskom-button-type type 'lyskom-button-arg numarg 'lyskom-button-menu-title menu-title 'lyskom-buffer lyskom-buffer)) ((eq type 'url) (list 'face (or face kom-active-face) 'mouse-face kom-highlight-face 'lyskom-button-text text 'lyskom-button-type type 'lyskom-button-arg arg 'lyskom-button-menu-title menu-title 'lyskom-buffer lyskom-buffer)) (t (list 'face (or face kom-active-face) 'mouse-face kom-highlight-face 'lyskom-button-text text 'lyskom-button-type type 'lyskom-button-arg arg 'lyskom-button-menu-title menu-title 'lyskom-buffer lyskom-buffer))))) (append (list 'rear-nonsticky t) (if (not subtle) (list 'lyskom-button t)) (if the-hint (cons 'lyskom-button-hint (cons the-hint props)) props)))) (defun lyskom-default-button (type arg &optional menu-title) "Generate a button of type TYPE from data in ARG. ARG can be almost any type of data and is converted to the proper argument type for buttons of type TYPE before being sent to lyskom-generate-button. Optional argument MENU-TITLE is a list consisting of a format string or symbol and arguments for the format string. The arguments are not when the menu is popped up." (and kom-text-properties (let (xarg text face subtle) (cond ((eq type 'conf) (cond ((lyskom-conf-stat-p arg) (if (conf-type->letterbox (conf-stat->conf-type arg)) (setq type 'pers)) (setq xarg arg text (conf-stat->name arg))) ((lyskom-uconf-stat-p arg) (if (conf-type->letterbox (uconf-stat->conf-type arg)) (setq type 'pers)) (setq xarg (uconf-stat->conf-no arg) text (uconf-stat->name arg))) ((lyskom-conf-z-info-p arg) (if (conf-type->letterbox (conf-z-info->conf-type arg)) (setq type 'pers)) (setq xarg (conf-z-info->conf-no arg) text (conf-z-info->name arg))) ((numberp arg) (if (setq xarg (cache-get-uconf-stat arg)) (progn (if (conf-type->letterbox (uconf-stat->conf-type xarg)) (setq type 'pers)) (setq text (uconf-stat->name xarg)) (setq xarg arg)) (setq text "" xarg arg))) (t (setq text "" xarg 0)))) ((eq type 'pers) (cond ((lyskom-conf-stat-p arg) (setq xarg arg text (conf-stat->name arg))) ((lyskom-uconf-stat-p arg) (setq xarg arg text (uconf-stat->name arg))) ((lyskom-conf-z-info-p arg) (setq xarg arg text (conf-z-info->name arg))) ((lyskom-pers-stat-p arg) (setq xarg (pers-stat->pers-no arg) text (or (conf-stat->name (cache-get-conf-stat (pers-stat->pers-no arg))) ""))) ((numberp arg) (if (setq xarg (cache-get-uconf-stat arg)) (progn (if (conf-type->letterbox (uconf-stat->conf-type xarg)) (setq type 'pers)) (setq text (uconf-stat->name xarg)) (setq xarg arg)) (setq text "" xarg arg))) (t (setq text "" xarg 0)))) ((eq type 'text) (cond ((stringp arg) (setq xarg (string-to-number arg) text arg)) ((numberp arg) (setq xarg arg text (number-to-string arg))) ((lyskom-text-stat-p arg) (setq xarg (text-stat->text-no arg) text (number-to-string (text-stat->text-no arg)))) (t (setq xarg 0 text "")))) ((eq type 'url) (setq face kom-url-face) (cond ((stringp arg) (setq xarg nil text arg)) (t (setq xarg nil text "")))) ((eq type 'email) (setq face kom-url-face) (cond ((stringp arg) (setq xarg nil text arg)) (t (setq xarg nil text "")))) ((eq type 'timestamp) (setq face 'default subtle t) (cond ((null arg) (setq xarg (lyskom-current-client-time) ;text (format-time-string "%Y-%m-%d %H:%M") )) (t (setq xarg arg ;text (format-time-string "%Y-%m-%d %H:%M" arg) )))) (t (setq xarg arg text ""))) (lyskom-generate-button type xarg text face menu-title subtle)))) ;;;======================================== ;;; Button actions ;;; (defun lyskom-button-view-text (buf arg text) "In the LysKOM buffer BUF, view the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-view arg)))) (defun lyskom-button-unread-text (buf arg text) "In the LysKOM buffer BUF, unread the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-mark-unread arg)))) (defun lyskom-button-copy-text-no (but arg text) "In the LysKOM buffer BUF, ignore ARG and copy TEXT to the kill ring. This is a LysKOM button action." (kill-new text)) (defun lyskom-button-review-noconversion (buf arg text) "In the LysKOM buffer BUF, view the text ARG without conversion. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-review-noconversion arg)))) (defun lyskom-button-review-converted (buf arg text) "In the LysKOM buffer BUF, view the text ARG converted. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-review-converted arg)))) (defun lyskom-button-review-rot13 (buf arg text) "In the LysKOM buffer BUF, view the text ARG rot13:ed. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-review-rot13 arg)))) (defun lyskom-button-find-root-review (buf arg text) "In the LysKOM buffer BUF, view the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-find-root-review arg)))) (defun lyskom-button-find-root (buf arg text) "In the LysKOM buffer BUF, view the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-find-root arg)))) (defun lyskom-button-comment-text (buf arg text) "In the LysKOM buffer BUF, comment the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-write-comment arg)))) (defun lyskom-button-private-comment-text (buf arg text) "In the LysKOM buffer BUF, write a private comment the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-private-answer arg)))) (defun lyskom-button-mark-text (buf arg text) "In the LysKOM buffer BUF, mark the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (unwind-protect (progn (pop-to-buffer buf) (lyskom-start-of-command 'kom-mark-text) (lyskom-mark-text arg)) (lyskom-end-of-command))))) (defun lyskom-button-unmark-text (buf arg text) "In the LysKOM buffer BUF, unmark the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (unwind-protect (progn (pop-to-buffer buf) (lyskom-start-of-command 'kom-unmark-text) (lyskom-unmark-text arg)) (lyskom-end-of-command))))) (defun lyskom-button-save-text (buf arg text) "In the LysKOM buffer BUF, save the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (unwind-protect (progn (pop-to-buffer buf) (kom-save-text nil (list arg))))))) (defun lyskom-button-save-text-body (buf arg text) "In the LysKOM buffer BUF, save the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (unwind-protect (progn (pop-to-buffer buf) (kom-save-text-body arg)))))) (defun lyskom-button-review-comments (buf arg text) "In the LysKOM buffer BUF, review comments to the the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-review-comments arg)))) (defun lyskom-button-review-tree (buf arg text) "In the LysKOM buffer BUF, recursively review comments to the the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-review-tree arg)))) (defun lyskom-button-write-footnote (buf arg text) "In the LysKOM buffer BUF, write a footnote to the the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-write-footnote arg)))) (defun lyskom-button-fast-reply (buf arg text) "In the LysKOM buffer BUF, make a remark to the the text ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-fast-reply arg)))) (defun lyskom-button-view-conf-presentation (buf arg text) "In the LysKOM buffer BUF, view the presentation of ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-review-presentation arg)))) (defun lyskom-button-view-conf-status (buf arg text) "In the LysKOM buffer BUF, view the status of conference ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-status-conf arg)))) (defun lyskom-button-goto-conf (buf arg text) "In the LysKOM buffer BUF, go to the conference ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-go-to-conf arg)))) (defun lyskom-button-add-self (buf arg text) "In the LysKOM buffer buf, add self to conference ARG." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-add-self arg)))) (defun lyskom-button-sub-self (buf arg text) "In the LysKOM buffer buf, sub self from conference ARG." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-sub-self arg)))) (defun lyskom-button-view-pers-presentation (buf arg text) "In the LysKOM buffer BUF, view the presentation of person ARG. Last argument TEXT is ignored. This is a LysKOM button action." (lyskom-button-view-conf-presentation buf arg text)) (defun lyskom-button-view-pers-status (buf arg text) "In the LysKOM buffer BUF, view the status of person ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (goto-char (point-max)) (kom-status-person arg)))) (defun lyskom-button-mail (buf arg text) "In the LysKOM buffer BUF, send mail to the conference ARG. Last argument TEXT is ignored. This is a LysKOM button action." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-send-letter arg)))) (defun lyskom-button-send-message (buf arg text) "In the LysKOM buffer BUF, send a personal message to person ARG." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-send-message arg nil)))) (defun lyskom-button-view-session-status (buf arg text) "In the LysKOM buffer BUF, show session status for person ARG." (cond ((not (integerp arg)) nil) (t (pop-to-buffer buf) (kom-status-session (lyskom-session-from-conf arg))))) (defun lyskom-button-copy-email (but arg text) "In the LysKOM buffer BUF, ignore ARG and copy TEXT to the kill ring. This is a LysKOM button action." (kill-new text)) (lyskom-external-function compose-mail) (defun lyskom-button-open-email (but arg text) "In the LysKOM buffer BUF, ignore ARG and open TEXT as an e-mail address. This is a LysKOM button action." (if (fboundp 'compose-mail) (compose-mail text) (mail nil text))) (defun lyskom-button-copy-url (but arg text) "In the LysKOM buffer BUF, ignore ARG and copy TEXT to the kill ring. This is a LysKOM button action." (kill-new (replace-in-string text "\\s-+" ""))) (defun lyskom-transform-url (url) (let ((rules kom-url-transformation-rules)) (while rules (setq url (replace-in-string url (car (car rules)) (cdr (car rules))) rules (cdr rules)))) url) (defun lyskom-button-open-url (buf arg text) "In the LysKOM buffer BUF, ignore ARG and open TEXT as an URL. This is a LysKOM button action." (let* ((url (lyskom-fix-pseudo-url (replace-in-string text "\\s-+" ""))) protocol url-manager) (setq url (lyskom-transform-url url)) (string-match lyskom-url-protocol-regexp url) (setq protocol (match-string 1 url)) (setq url-manager (lyskom-get-url-manager protocol)) (if (null url-manager) (lyskom-error "Can't find URL viewer")) (funcall (elt url-manager 3) url url-manager))) ;;; ;;; Info node button ;;; (defun lyskom-button-goto-info-node (buf arg text) "In the LysKOM buffer BUF, open ARG as an Info node, and ignore TEXT. This is a LysKOM button action." (when (not (fboundp 'Info-goto-node)) (autoload 'Info-goto-node "info" "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME." t)) (setq arg (replace-in-string arg "\n" " " t)) (setq arg (replace-in-string arg " +" " " t)) (Info-goto-node arg)) ;;; ;;; Timestamp button ;;; (defun lyskom-button-copy-timestamp (buf arg text) "In the LysKOM buffer BUF, ignore TEXT and copy ARG to the kill ring after formating it as time. This is a LysKOM button action." (let ((kom-print-relative-dates nil)) (kill-new (lyskom-format-time 'date-and-time arg)))) ;;; ;;; LysKOM URL Management ;;; (defun lyskom-get-url-manager (protocol) "Get the URL manager for PROTOCOL (a string). Returns a function." (let ((managers kom-url-managers) (preferences kom-url-viewer-preferences) (result nil)) (while (and preferences (not result)) (setq managers kom-url-managers) (while (and managers (not result)) (if (and (string-match (car (car managers)) (car preferences)) (string-match (car (cdr (car managers))) protocol)) (setq result (car managers))) (setq managers (cdr managers))) (setq preferences (cdr preferences))) result)) (defun lyskom-url-manager-starting (manager) "Tell the user that the URL manager MANAGER is starting." (lyskom-message "%s" (lyskom-format (lyskom-get-string 'starting-program) (elt manager 2)))) (eval-when-compile (defvar browse-url-browser-function nil)) (defun lyskom-view-url-browse-url (url manager) (require 'browse-url) (funcall browse-url-browser-function url)) (lyskom-with-external-functions (w3-fetch) (defun lyskom-view-url-w3 (url manager) "View the URL using W3. Second argument MANAGER is ignored." (w3-fetch url))) (defun lyskom-view-url-dired (url manager) "View the URL URL using dired. Second argument MANAGER is ignored." (if (not (and (string-match "\\(file\\|ftp\\)://\\([^/:]*\\)\\(:[0-9]*\\)?\\(/\\|$\\)" url) (match-beginning 0) (match-beginning 1) (match-beginning 2))) (lyskom-error "Bad URL")) (let ((host (substring url (match-beginning 2) (match-end 2))) (path (substring url (match-end 0))) (user "anonymous")) (if (string-match ";type=.$" path) (setq path (substring path 0 (match-beginning 0)))) (if (and (string-match "\\([^@]*\\)@" host) (match-beginning 1)) (progn (setq user (substring host (match-beginning 1) (match-end 1))) (setq host (substring host (match-end 0))))) (cond ((string= host "localhost") (find-file path)) (t (find-file (concat "/" user "@" host ":/" path)))) ;; (message "%s %s %s" user host path) )) (defun lyskom-view-url-telnet (url manager) "View the URL URL using telnet. Second argument MANAGER is ignored." (if (not (and (string-match "telnet://\\([^@]*@\\)?\\([^/:]*\\)\\(:[0-9]*\\)?" url) (match-beginning 0) (match-beginning 2))) (lyskom-error "Bad URL")) (let ((host (substring url (match-beginning 2) (match-end 2))) (port (if (match-beginning 3) (substring url (1+ (match-beginning 3)) (match-end 3)) "")) (user (if (match-beginning 1) (substring url (match-beginning 1) (1- (match-end 1))) nil)) ;; (password nil) ) (if (and user (string-match "^\\([^:]*\\):\\(.*\\)" user)) (progn ;; (setq password (substring user ;; (match-beginning 2) ;; (match-end 2))) (setq user (substring user (match-beginning 1) (match-end 1))))) (telnet (concat host " " port)) ;; (message "u:%s p:%s h:%s #:%s" ;; (or user "") ;; (or password "

") ;; (or host "") ;; (or port "<#>")) )) (defun lyskom-view-url-mailmode (url manager) "View the URL URL using mail in Emacs. The second argument MANAGER is ignored." (if (not (and (string-match "mailto:\\([^@]+@.*\\)$" url) (match-beginning 1))) (lyskom-error "Bad URL")) (mail nil (substring url (match-beginning 1) (match-end 1)))) (defun lyskom-view-url-windows (url manager) "View the URL URL in Microsoft Windows. MANGER is the URL manager. Fall back on Netscape if not running in Microsoft Windows. In theory, opening an URL on Windows should be a matter of doing \(w32-shell-execute \"open\" URL\), but this sometimes fails, so we protect ourselves by also trying to start some common defaults using start-process." (cond ((memq window-system '(win32 mswindows w32)) (cond ((and (boundp 'kom-windows-browser-command) (and (not (null kom-windows-browser-command)) (not (eq (length kom-windows-browser-command) 0)))) ;; Explicit given file name of browser, so complain to user if ;; the value is bad. (if (not (file-executable-p kom-windows-browser-command)) (error (concat "Not an executable file: %s;" " kom-windows-browser-command has a bad value") kom-windows-browser-command)) (condition-case nil (progn (lyskom-url-manager-starting manager) (start-process "Browser" nil kom-windows-browser-command url)) (error (error (concat "Failed starting browser using" " kom-windows-browser-command" " (%s)") kom-windows-browser-command)))) ((and (not (memq 'w32-shell-execute lyskom-compatibility-definitions)) (condition-case nil (progn (w32-shell-execute "open" url) t) (error nil))) (lyskom-url-manager-starting manager)) ;;(lyskom-message "Webb via [%s \"%s\" \"%s\"] ..." ;; "w32-shell-execute" "open" url)) (t (let ((programs '("c:\\Program\\Internet Explorer\\iexplore.exe" "c:\\Programs\\Internet Explorer\\iexplore.exe" "c:\\Program Files\\Internet Explorer\\iexplore.exe" "start" "explorer" "C:\\Program Files\\Netscape\\Communicator\\Program\\netscape.exe" "C:\\Program Files\\Netscape\\Navigator\\Program\\netscape.exe" ))) (while programs (condition-case nil (progn (lyskom-url-manager-starting manager) (start-process (car programs) nil (car programs) url) (setq programs nil)) (error (setq programs (cdr programs))))))))) (t (lyskom-view-url-netscape url manager)))) (defun lyskom-view-url-netscape (url manager) "View the URL URL using Netscape Navigator. The second argument MANAGER is the URL manager that started Netscape. This function attempts to load the URL in a running Netscape, but failing that, starts a new one." (setq url (replace-in-string url "," "%2C")) (setq url (replace-in-string url "(" "%28")) (setq url (replace-in-string url ")" "%29")) (let* ((url-string (if (memq window-system '(win32 mswindows w32)) (list url) (list "-remote" (format (cond ((eq kom-netscape-variant 'new-window) "openUrl(%s, new-window)") ((eq kom-netscape-variant 'new-tab) "openUrl(%s, new-tab)") (t "openUrl(%s)")) url)))) (proc (apply 'start-process "netscape" nil (if (listp kom-netscape-command) (car kom-netscape-command) kom-netscape-command) (if (listp kom-netscape-command) (append (cdr kom-netscape-command) url-string) url-string))) (status 'run) (exit nil)) (lyskom-url-manager-starting manager) (while (eq status 'run) (lyskom-accept-process-output) (setq status (process-status proc))) (setq exit (process-exit-status proc)) (cond ((and (eq status 'exit) (eq exit 1)) (apply 'start-process "netscape" nil (if (listp kom-netscape-command) (car kom-netscape-command) kom-netscape-command) (if (listp kom-netscape-command) (append (cdr kom-netscape-command) (list url)) (list url)))) (t nil)))) (defun lyskom-view-url-mosaic (url manager) "View the URL URL using NCSA Mosaic. The attempts to open the URL in an existing Mosaic process. Failing that, it starts a new Mosaic." (let ((pid -1) tempbuffer (filename "/tmp/Mosaic.")) (if (file-exists-p (expand-file-name "~/.mosaicpid")) (save-excursion (set-buffer (setq tempbuffer (get-buffer-create " *kom*-mosaicpid"))) (insert-file-contents (expand-file-name "~/.mosaicpid")) (setq pid (read tempbuffer)) (delete-region (point-min) (point-max)) (insert "newwin\n") (insert url) (insert "\n") (setq filename (concat filename (number-to-string pid))) (write-region (point-min) (point-max) filename nil 'x) (kill-buffer tempbuffer) (if (= -1 (signal-process pid 30)) (apply 'start-process "mosaic" (current-buffer) (if (listp kom-mosaic-command) (car kom-mosaic-command) kom-mosaic-command ) (if (listp kom-mosaic-command) (append (cdr kom-mosaic-command) (list url)) (list url))) (lyskom-url-manager-starting manager))) (save-excursion (apply 'start-process "mosaic" (current-buffer) (if (listp kom-mosaic-command) (car kom-mosaic-command) kom-mosaic-command ) (if (listp kom-mosaic-command) (append (cdr kom-mosaic-command) (list url)) (list url))) (lyskom-url-manager-starting manager))))) (defun lyskom-view-url-galeon (url manager) "View the URL URL using Galeon. The second argument MANAGER is the URL manager that started Galeon. This function attempts to load the URL in a running Galeon, but failing that, starts a new one." (setq url (replace-in-string url "," "%2C")) (setq url (replace-in-string url "(" "%28")) (setq url (replace-in-string url ")" "%29")) (let* ((url-string (if (memq window-system '(win32 mswindows w32)) (list url) (list "-n" (format "%s" url))))) (lyskom-url-manager-starting manager) (apply 'start-process "galeon" nil (if (listp kom-galeon-command) (car kom-galeon-command) kom-galeon-command) (if (listp kom-galeon-command) (append (cdr kom-galeon-command) url-string) url-string)))) ;; Added by Peter Liljenberg (defun lyskom-view-url-lynx (url manager) "View the URL URL using Lynx. Lynx will be run either in an xterm or in Emacs terminal mode, depending on the value of `kom-lynx-terminal'." (cond ((eq kom-lynx-terminal 'xterm) (apply 'start-process "lynx" nil (car kom-lynx-xterm-command) (append (cdr kom-lynx-xterm-command) (list url))) (lyskom-url-manager-starting manager)) ((eq kom-lynx-terminal 'terminal) (let* ((lbuf (get-buffer "*Lynx*")) (lproc (and lbuf (get-buffer-process lbuf)))) (if lproc ;; Tell existing Lynx to fetch URL (process-send-string lproc (concat "g" url "\n")) ;; Create a new Lynx (switch-to-buffer (apply 'make-term "Lynx" (if (listp kom-lynx-terminal-command) (car kom-lynx-terminal-command) kom-lynx-terminal-command) nil (if (listp kom-lynx-terminal-command) (append (cdr kom-lynx-terminal-command) (list url)) (list url)))) (delete-other-windows) (term-char-mode) (set-process-sentinel (get-buffer-process (current-buffer)) (function (lambda (proc str) (kill-buffer (process-buffer proc)))))) (lyskom-url-manager-starting manager))) (t (lyskom-error "Bad Lynx terminal: %s" kom-lynx-terminal)) )) ;;; ;;; aux-item buttons ;;; (defun lyskom-button-delete-aux (buf arg text) (let ((aux nil)) (cond ((lyskom-aux-item-p arg)) ((listp arg) (let ((items (cond ((eq 'text (car arg)) (text-stat->aux-items (blocking-do 'get-text-stat (elt arg 1)))) ((eq 'conf (car arg)) (conf-stat->aux-items (blocking-do 'get-conf-stat (elt arg 1)))) ((eq 'server (car arg)) (server-info->aux-item-list (blocking-do 'get-server-info))) (t nil)))) (while items (when (eq (aux-item->aux-no (car items)) (elt arg 2)) (setq aux (car items)) (setq items nil)) (setq items (cdr items)))))) (when aux (lyskom-start-of-command nil) (unwind-protect (progn (unless (cond ((eq 'text (car arg)) (cache-del-text-stat (elt arg 1)) (blocking-do 'modify-text-info (elt arg 1) (list (aux-item->aux-no aux)) nil)) ((eq 'conf (car arg)) (cache-del-conf-stat (elt arg 1)) (blocking-do 'modify-conf-info (elt arg 1) (list (aux-item->aux-no aux)) nil)) ((eq 'server (car arg)) (prog1 (blocking-do 'modify-server-info (list (aux-item->aux-no aux)) nil) (lyskom-set-default 'lyskom-server-info (blocking-do 'get-server-info))))) (lyskom-report-command-answer nil))) (lyskom-end-of-command))))) (defun lyskom-button-info-aux (buf arg text) (pop-to-buffer buf) (goto-char (point-max)) (let ((aux nil)) (cond ((lyskom-aux-item-p arg)) ((listp arg) (let ((items (cond ((eq 'text (car arg)) (text-stat->aux-items (blocking-do 'get-text-stat (elt arg 1)))) ((eq 'conf (car arg)) (conf-stat->aux-items (blocking-do 'get-conf-stat (elt arg 1)))) ((eq 'server (car arg)) (server-info->aux-item-list (blocking-do 'get-server-info))) (t nil)))) (while items (when (eq (aux-item->aux-no (car items)) (elt arg 2)) (setq aux (car items)) (setq items nil)) (setq items (cdr items)))))) (if aux (let ((header (cond ((eq 'text (car arg)) (lyskom-format 'aux-item-for-text-no (elt arg 1))) ((eq 'conf (car arg)) (lyskom-format 'aux-item-for-conference-no (blocking-do 'get-conf-stat (elt arg 1)))) ((eq 'server (car arg)) (lyskom-format 'aux-item-for-server)) (t "????")))) (lyskom-start-of-command nil) (unwind-protect (lyskom-insert (or (lyskom-aux-item-call aux 'info aux header) (lyskom-aux-item-info aux header))) (lyskom-end-of-command))) (lyskom-format-insert-before-prompt 'cant-get-aux-item)))) (defun lyskom-button-apply (buf arg text) (apply (car arg) (cdr arg))) ;;; ================================================================ ;;; Functions to put in kom-highlight-conferences (defun lyskom-highlight-function-get-conf-stat (arg) "Try to translate ARG to a conf-stat without making server calls. ARG may be a conf-stat, pers-stat, uconf-stat, conf-z-info, integer or string." (if (lyskom-conf-stat-p arg) arg (let* ((conf-no (cond ((lyskom-pers-stat-p arg) (pers-stat->pers-no arg)) ((lyskom-uconf-stat-p arg) (uconf-stat->conf-no arg)) ((numberp arg) arg) ((lyskom-conf-z-info-p arg) (conf-z-info->conf-no arg)) ((stringp arg) (string-to-int arg))))) (when conf-no (cond ((cache-get-conf-stat conf-no)) (conf-no (initiate-get-conf-stat 'background nil conf-no) nil)))))) (defun lyskom-highlight-i-am-supervisor (arg) "Returns non-nil if lyskom-pers-no is the supervisor of ARG. ARG interpreted by `lyskom-highlight-function-get-conf-stat'. This function never makes server calls, so if the information required to answer accurately is not cached, this function will return an incorrect result (nil instead of t)." (let ((conf-stat (lyskom-highlight-function-get-conf-stat arg))) (lyskom-i-am-supervisor conf-stat nil))) (defun lyskom-highlight-has-no-presentation (arg) "Returns non-nil if lyskom-pers-no is the supervisor of CONF-STAT. ARG is interpreted by `lyskom-highlight-function-get-conf-stat'. This function never makes server calls, so if the information required to answer accurately is not cached, this function will return an incorrect result (nil instead of t)." (let ((conf-stat (lyskom-highlight-function-get-conf-stat arg))) (cond ((null conf-stat) nil) ((conf-type->secret (conf-stat->conf-type conf-stat)) nil) (t (eq 0 (conf-stat->presentation conf-stat)))))) ;;;;; -*-coding: raw-text;-*- ;;;;; ;;;;; $Id: view-text.el,v 44.82 2005/01/11 15:00:14 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;; ================================================================ ;;; ================================================================ ;;; ;;; File: view-text.el ;;; ;;; This file contains functions that have to do with putting ;;; a text into the lyskom buffer. ;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: view-text.el,v 44.82 2005/01/11 15:00:14 _cvs_pont_lyskomelisp Exp $\n")) (defvar lyskom-view-text-text) (defvar lyskom-view-text-text-stat) (defun lyskom-view-text (text-no &optional mark-as-read follow-comments conf-stat priority build-review-tree filter-active flat-review) "Display text number TEXT-NO. Args: TEXT-NO &optional MARK-AS-READ FOLLOW-COMMENTS CONF-STAT PRIORITY BUILD-REVIEW-TREE FLAT-REVIEW. If MARK-AS-READ (or `kom-review-marks-texts-as-read') is non-nil the text will be marked as read. If FOLLOW-COMMENTS is non-nil all comments and footnotes to this text will be read before the next text. CONF-STAT must be the conference status of the current conference, and PRIORITY the priority, if FOLLOW-COMMENTS is non-nil. If BUILD-REVIEW-TREE is non-nil then it fixes a new entry in the lyskom-reading-list to read the comments to this. If FLAT-REVIEW is non-nil this is a review caused by lyskom-view-commented or kom-view-text viewing REVIEW or REVIEW-MARK text. Note that this function must not be called asynchronously." (let ((inhibit-read-only t) (filter (and filter-active (lyskom-filter-text-p text-no))) (start nil) (todo nil) (lyskom-last-text-format-flags nil)) (cond ((eq filter 'obliterate) (setq todo 'next-text) (lyskom-mark-as-read (blocking-do 'get-text-stat text-no)) 'next-text) ((eq filter 'skip-text) (lyskom-filter-prompt text-no 'filter-text) (setq todo 'next-text) (lyskom-mark-as-read (blocking-do 'get-text-stat text-no)) 'next-text) ((eq filter 'skip-tree) (lyskom-filter-prompt text-no 'filter-tree) ;;(initiate-get-text-stat 'main 'lyskom-jump text-no t) ;; Let's try something else: (lyskom-jump (blocking-do 'get-text-stat text-no) t) (lyskom-wait-queue 'main) (setq todo 'next-text) 'next-text) (t (if (not (or (null filter) (eq filter 'read) (eq filter 'dontshow))) (lyskom-message "%s" (lyskom-get-string 'invalid-filter-list))) (if (eq filter 'dontshow) (setq todo 'next-text)) (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (setq lyskom-view-text-text text lyskom-view-text-text-stat text-stat) (if (and text-stat text) (progn (run-hooks 'lyskom-view-text-hook) (run-hooks 'kom-view-text-hook) ;; Use a marker, because the buffer may lose data ;; at the top if kom-max-buffer-size is set. (setq start (point-max-marker)) (let ((mx-date (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 21))) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (mx-to (lyskom-get-aux-item (text-stat->aux-items text-stat) 19)) (mx-cc (lyskom-get-aux-item (text-stat->aux-items text-stat) 20)) (mx-message-id (lyskom-get-aux-item (text-stat->aux-items text-stat) 22)) (mx-filename (lyskom-get-aux-item (text-stat->aux-items text-stat) 10104)) (mx-sender (lyskom-get-aux-item (text-stat->aux-items text-stat) 10103)) (mx-headers (lyskom-get-aux-item (text-stat->aux-items text-stat) 24)) (mx-reply-to (lyskom-get-aux-item (text-stat->aux-items text-stat) 18))) (lyskom-format-insert 'view-text-first-line text-stat (list 'lyskom-text-start (text-stat->text-no text-stat)) (if mx-date (let ((date (lyskom-mx-date-to-time mx-date))) (if date (concat (lyskom-format-time 'date-and-time date) (if (time->tzhr date) (lyskom-format " %#1s%#2s" (time->tzhr date) (time->tzmin date)) "")) (aux-item->data mx-date))) (lyskom-format-time 'date-and-time (text-stat->creation-time text-stat))) (text-stat->no-of-lines text-stat) (or (lyskom-format-mx-author mx-from mx-author) (lyskom-format "%#1P" (text-stat->author text-stat))) (when (eq filter 'dontshow) (lyskom-get-string 'filtered)) (when kom-highlight-first-line `(face ,kom-first-line-face))) (set-marker start nil) ;; Insert sender (when (and mx-sender kom-show-imported-envelope-sender) (lyskom-format-insert 'envelope-sender (aux-item->data (car mx-sender)))) (when mx-filename (lyskom-format-insert 'attachment-filename (aux-item->data (car mx-filename)))) (when (and mx-message-id kom-show-imported-message-id) (lyskom-format-insert 'message-id (aux-item->data (car mx-message-id)))) ;; Insert imported at (cond ((and (or mx-from mx-author mx-sender mx-headers) (text-stat->author text-stat) kom-show-imported-importer) (lyskom-format-insert 'text-imported-at-by (lyskom-format-time 'date-and-time (text-stat->creation-time text-stat)) (text-stat->author text-stat))) (mx-from (lyskom-format-insert 'text-imported-at (lyskom-format-time 'date-and-time (text-stat->creation-time text-stat)))) (mx-date (lyskom-format-insert 'text-created-at (lyskom-format-time 'date-and-time (text-stat->creation-time text-stat))))) (when kom-show-imported-external-recipients (mapcar (lambda (el) (lyskom-format-insert "%#1s: %#2s\n" (lyskom-get-string 'mx-Recipient) (aux-item->data el))) mx-to) (mapcar (lambda (el) (lyskom-format-insert "%#1s: %#2s\n" (lyskom-get-string 'mx-Extra-recipient) (aux-item->data el))) mx-cc) (mapcar (lambda (el) (lyskom-format-insert "%#1s: %#2s\n" (lyskom-get-string 'mx-Extern-reply-to) (aux-item->data el))) mx-reply-to) ) ;; Insert all recipients and other header lines. (if (eq filter 'dontshow) (lyskom-mark-as-read (blocking-do 'get-text-stat text-no)) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (cond ((memq type '(RECPT BCC-RECPT CC-RECPT)) (lyskom-print-header-recpt (misc-info->recipient-no misc) misc)) ((eq type 'COMM-IN) (if kom-reading-puts-comments-in-pointers-last nil (lyskom-print-header-comm (misc-info->comm-in misc) misc text-stat))) ((eq type 'FOOTN-IN) (if kom-reading-puts-comments-in-pointers-last nil (lyskom-print-header-comm (misc-info->footn-in misc) misc text-stat))) ((eq type 'COMM-TO) (lyskom-print-header-comm (misc-info->comm-to misc) misc text-stat)) ((eq type 'FOOTN-TO) (lyskom-print-header-comm (misc-info->footn-to misc) misc text-stat)) ))) ;; Insert aux-items that go in the header. (lyskom-traverse-aux aux (text-stat->aux-items text-stat) (let ((tpw (lyskom-aux-item-definition-field aux 'text-print-when))) (when (or (and (lyskom-viewing-noconversion) (not (eq tpw 'footer))) (eq tpw 'header) (and (eq tpw 'comment) (not kom-reading-puts-comments-in-pointers-last))) (if (lyskom-aux-item-has-call aux 'text-print) (let ((text (lyskom-aux-item-call aux 'text-print aux text-stat))) (when text (lyskom-insert text) (lyskom-insert "\n"))) (lyskom-format-insert 'text-header-aux-item (lyskom-get-string (or (car (lyskom-aux-item-definition-field aux 'text-name)) 'unknown-aux-item)) (aux-item->tag aux) (aux-item->data aux) (lyskom-aux-item-terminating-button aux text-stat)) (lyskom-insert "\n"))))) ;; If the text is marked, insert line saying so. (let ((num-marks (text-stat->no-of-marks text-stat)) (is-marked-by-me (cache-text-is-marked (text-stat->text-no text-stat)))) (when (> num-marks 0) (if is-marked-by-me (if (= num-marks 1) (lyskom-format-insert 'marked-by-you (mark->symbolic-mark-type is-marked-by-me)) (lyskom-format-insert 'marked-by-you-and-others (1- num-marks) (mark->symbolic-mark-type is-marked-by-me))) (lyskom-format-insert 'marked-by-several num-marks)))) ;; Insert the text body. (lyskom-print-text text-stat text (or mark-as-read kom-review-marks-texts-as-read) text-no flat-review) (if kom-review-marks-texts-as-read (lyskom-is-read text-no))) ;; Insert aux-items that go in the footer. (let ((text nil)) (lyskom-traverse-aux aux (text-stat->aux-items text-stat) (when (and (or (eq (lyskom-aux-item-definition-field aux 'text-print-when) 'footer) (and (eq (lyskom-aux-item-definition-field aux 'text-print-when) 'comment) kom-reading-puts-comments-in-pointers-last )) (setq text (lyskom-aux-item-call aux 'text-print aux text-stat))) (lyskom-insert text) (lyskom-insert "\n")))) ;; Insert fast replies. (let ((author-fast-replies nil) (other-fast-replies nil)) (lyskom-traverse-aux aux (text-stat->aux-items text-stat) (when (eq (aux-item->tag aux) 2) (if (or (lyskom-viewing-noconversion) (not (eq (text-stat->author text-stat) (aux-item->creator aux)))) (setq other-fast-replies (cons aux other-fast-replies)) (setq author-fast-replies (cons aux author-fast-replies))))) (when author-fast-replies (lyskom-insert (concat (lyskom-format 'author-fast-replies) "\n" (mapconcat (lambda (item) (concat (lyskom-format 'author-fast-reply-aux (aux-item->data item) (aux-item->creator item)) (lyskom-aux-item-terminating-button item text-stat) "\n")) (nreverse author-fast-replies) "")))) (when other-fast-replies (lyskom-insert (concat (lyskom-format 'other-fast-replies) "\n" (mapconcat (lambda (item) (concat (lyskom-format 'other-fast-reply-aux (aux-item->data item) (aux-item->creator item)) (lyskom-aux-item-terminating-button item text-stat) "\n")) (nreverse other-fast-replies) ""))))) ;; Insert footnote/comment references. (if kom-reading-puts-comments-in-pointers-last (lyskom-view-text-handle-saved-comments text-stat)) ; Show footnotes if we should do that directly (if kom-show-footnotes-immediately (lyskom-traverse misc (text-stat->misc-info-list text-stat) (if (eq (misc-info->type misc) 'FOOTN-IN) ;; Show the footnote (progn (lyskom-view-text (misc-info->footn-in misc) mark-as-read t conf-stat priority) ; Mark as read (internally) så follow-comments won't add ; it to the read list. (lyskom-is-read (misc-info->footn-in misc)))))) ;; Prefetch commented texts. (if (or follow-comments ;; Checking build-review-tree should not be ;; necessary, really /davidk build-review-tree) ;; This shows footnotes also. (progn ;; this is a bit silly, as it prefetches all ;; the texts many times. (unless (and build-review-tree kom-review-uses-cache) (lyskom-prefetch-texttree text-no)) (lyskom-follow-comments text-stat conf-stat (or mark-as-read kom-review-marks-texts-as-read) priority build-review-tree))) (if (lyskom-text-p (cache-get-text text-no)) (cache-del-text text-no)) )) (lyskom-format-insert 'no-such-text-no text-no)) (let ((aux-items (text-stat->aux-items text-stat))) (while aux-items (lyskom-aux-item-call (car aux-items) 'read-action text-stat) (setq aux-items (cdr aux-items)))) ))) todo)) (defun lyskom-text-is-mail-p (text-stat) "Ad-hoc test to determine whether a text is a mail by peeking at aux-items." (lyskom-match-aux-items (text-stat->aux-items text-stat) (lambda (aux-item) (let ((tag (aux-item->tag aux-item))) (or (and (> tag 15) ; 16:mx-author, 17:mx-from, 18:mx-reply-to, (< tag 22)) ; 19:mx-to, 20:mx-cc, 21:mx-date, (= 24 tag)))))) ; 24:mx-headers (defun lyskom-filter-signature-hook () "Filter out the signature of imported mail messages. Most useful when put in your `kom-view-text-hook'." (unless (lyskom-viewing-noconversion) (when (lyskom-text-is-mail-p lyskom-view-text-text-stat) (let* ((body (text->text-mass lyskom-view-text-text)) (sign (string-match "^-- $" body))) (when sign (set-text->text-mass lyskom-view-text-text (substring body 0 sign)) (lyskom-signal-reformatted-text 'reformat-signature)))))) ;(add-hook 'kom-view-text-hook 'lyskom-filter-signature-hook) ; review-rot13 (defun lyskom-rot13-string (s) (mapconcat (lambda (c) (cond ((and (>= c ?a) (<= c ?z)) (string (+ ?a (% (+ 13 (- c ?a)) 26)))) ((and (>= c ?A) (<= c ?Z)) (string (+ ?A (% (+ 13 (- c ?A)) 26)))) (t (string c)))) s "")) (defun lyskom-filter-rot13 () "Encrypts everything with rot-13. Least useless when put in your `kom-view-text-hook'." (set-text->text-mass lyskom-view-text-text (lyskom-rot13-string (text->text-mass lyskom-view-text-text))) (lyskom-signal-reformatted-text 'reformat-rot13)) (defun lyskom-view-text-convert-ISO-646-SE-to-ISO-8859-1 () "Display r{ksm|rg}s as räksmörgås unless the text is an imported mail or we are reviewing without conversion. In other words, the characters ][\\}{| are converted, however ^~@` are not. Yet another useful function to put in your `kom-view-text-hook'." ;; First the hard part - should we patch the text ;; in the text object? (unless (or (lyskom-viewing-noconversion) (lyskom-text-is-mail-p lyskom-view-text-text-stat)) ;; Yes, modify the text from the text-object (stored in mod) (let* ((mod (aref (cdr lyskom-view-text-text) 1)) (brk (string-match "\n" mod)) (sbj (if brk (substring mod 0 brk) mod)) (txt (if brk (substring mod (1+ brk)) "")) (tbl '((?\] . ?\305) ; Å (?\[ . ?\304) ; Ä (?\\ . ?\326) ; Ö (?\} . ?\345) ; å (?\{ . ?\344) ; ä (?\| . ?\366)))) ; ö (when (and (not (string-match "[\200-\377]" txt)) (or (string-match "[A-Za-z][][\\}{|]" txt) (string-match "[][\\}{|][A-Za-z]" txt) (string-match "[A-Za-z] +[][\\}{|]" txt))) (lyskom-signal-reformatted-text 'reformat-deswascii) (while (string-match "\\([][\\}{|]\\)" txt) (let ((old-char (aref (match-string 1 txt) 0))) (aset txt (match-beginning 1) (cdr (assoc old-char tbl))))) (aset (cdr lyskom-view-text-text) 1 (if brk (concat sbj "\n" txt) sbj)))))) ;(add-hook 'kom-view-text-hook 'lyskom-view-text-convert-ISO-646-SE-to-ISO-8859-1) (defun lyskom-follow-comments (text-stat conf-stat mark-as-read priority review-tree) "Arrange so that all comments and footnotes to this text will be read. This will essentially fix the reading list and issue calls for the cache to be filled. Arguments are: TEXT-STAT CONF-STAT MARK-AS-READ PRIORITY REVIEW-TREE TEXT-STAT is the current text. CONF-STAT the current conference If MARK-AS-READ is non-nil the texts will be marked as read. PRIORITY the priority of the reading. If REVIEW-TREE is non-nil then build an entry of type 'REVIEW-TREE in the lyskom-reading-list." ;; . Fix the reading-list ;; . Issue cache-filling initiate-calls for everything left comments. (let ((flist nil) (clist nil) (mx-attachments-in (lyskom-get-text-attachments text-stat))) (lyskom-traverse misc (text-stat->misc-info-list text-stat) (cond ((eq (misc-info->type misc) 'FOOTN-IN) (setq flist (cons (misc-info->footn-in misc) flist))) ((eq (misc-info->type misc) 'COMM-IN) (setq clist (cons (misc-info->comm-in misc) clist))))) (let (comments footnotes) ;; Find the comments that we should read and enter them into the ;; read-list. (lyskom-traverse no clist (cond ((or review-tree kom-follow-attachments (not (memq no mx-attachments-in))) (let ((text-stat (blocking-do 'get-text-stat no))) (if (and text-stat (or review-tree (not (lyskom-text-read-p text-stat)))) (setq comments (cons no comments))))) ((memq no mx-attachments-in) (lyskom-skip-attachments no mark-as-read)))) (if comments (if review-tree (lyskom-review-enter-read-info (lyskom-create-read-info 'REVIEW-TREE conf-stat priority (lyskom-create-text-list comments) (text-stat->text-no text-stat)) t) (read-list-enter-read-info (lyskom-create-read-info 'COMM-IN conf-stat priority (lyskom-create-text-list comments) (text-stat->text-no text-stat)) lyskom-reading-list t))) ;; Find the footnotes that we should read and enter them into ;; the read-list. A slight trick is to increase the priority so ;; that they will be read first. (lyskom-traverse no flist (let ((text-stat (blocking-do 'get-text-stat no))) (if (or review-tree (and text-stat (not (lyskom-text-read-p text-stat)))) (setq footnotes (cons no footnotes))))) (if footnotes (read-list-enter-read-info (lyskom-create-read-info (if review-tree 'REVIEW-TREE 'FOOTN-IN) conf-stat (1+ priority) (lyskom-create-text-list footnotes) (text-stat->text-no text-stat)) lyskom-reading-list t))))) (defun lyskom-get-text-attachments (text-stat) "Return a list of all attachments to TEXT-STAT." (mapcar (lambda (el) (string-to-number (aux-item->data el))) (lyskom-get-aux-item (text-stat->aux-items text-stat) 10101))) (defun lyskom-get-text-belongs-to (text-stat) "Return a list of all texts TEXT-STAT is an attachment to." (mapcar (lambda (el) (string-to-number (aux-item->data el))) (lyskom-get-aux-item (text-stat->aux-items text-stat) 10100))) (defun lyskom-skip-attachments (text-no mark-as-read) "Skip the hierarchy of attachments starting at text-no" (let ((queue (list text-no)) (done nil) (tmp (make-collector)) (result nil)) ;; Note: this does block the client, but explicitly checks that ;; it is not being called from under the parser (where it ;; really doesn't make a whole lot of sense anyway), so ;; we ought to be OK anyway. (unless lyskom-is-parsing (while queue (while queue (when (not (memq (car queue) done)) (initiate-get-text-stat 'background 'collector-push (car queue) tmp) (setq queue (cdr queue)) (setq done (cons (car queue) done)))) (lyskom-wait-queue 'background) (setq result (nconc result (collector->value tmp))) (lyskom-traverse text-stat (collector->value tmp) (setq queue (nconc queue (lyskom-get-text-attachments text-stat))))) (lyskom-traverse text-stat result (read-list-delete-text (text-stat->text-no text-stat) lyskom-reading-list) (read-list-delete-text (text-stat->text-no text-stat) lyskom-to-do-list) (when mark-as-read (lyskom-mark-as-read text-stat) (lyskom-is-read-handler text-stat)))))) (defun lyskom-text-read-p (text-stat) "Return t if TEXT-STAT has been marked as read in all recipients to it that the user is a member in." (let* ((misc-info-list (text-stat->misc-info-list text-stat)) (i (length misc-info-list)) (res 'not-member)) (while (and res (not (zerop i))) (setq i (1- i)) (let* ((misc-info (elt misc-info-list i)) (type (misc-info->type misc-info))) (cond ((memq type '(RECPT BCC-RECPT CC-RECPT)) ;; Is this function ever called asynchronously? If not, we ;; can use lyskom-get-membership istead. (let ((membership (lyskom-try-get-membership (misc-info->recipient-no misc-info) nil)) (loc-no (misc-info->local-no misc-info))) ;; Make a note that this text really is in a group we are ;; a member of. (if (and res membership) (setq res t)) (if (and membership (> loc-no (membership->last-text-read membership)) (not (lyskom-vmemq loc-no (membership->read-texts membership)))) (setq res nil))))))) (if (eq res 'not-member) (not kom-follow-comments-outside-membership) res))) (defun lyskom-text-read-at-least-once-p (text-stat &optional bg) "Return t if TEXT-STAT has been marked as read in any of the recipients the user is a member of. Uses blocking-do. Returns t if TEXT-STAT is nil. If BG is non-nil, this function is run in the background and must not use blocking-do." (if text-stat (let* ((misc-info-list (text-stat->misc-info-list text-stat)) (misc-item nil) (type nil) (membership nil) (is-member nil) (result nil)) (while misc-info-list (setq misc-item (car misc-info-list)) (setq type (misc-info->type misc-item)) (setq misc-info-list (cdr misc-info-list)) (cond ((memq type '(RECPT BCC-RECPT CC-RECPT)) (setq membership (if bg (lyskom-try-get-membership (misc-info->recipient-no misc-item) t) (lyskom-get-membership (misc-info->recipient-no misc-item) nil))) (when membership (setq is-member t) (when (or (<= (misc-info->local-no misc-item) (membership->last-text-read membership)) (lyskom-vmemq (misc-info->local-no misc-item) (membership->read-texts membership))) (setq result t) (setq misc-info-list nil)))))) (cond (result result) ((not is-member) (not kom-follow-comments-outside-membership)) (t nil))) t)) (defun lyskom-subtract-one-day (x) (let ((high-x (1- (car x))) (low-x (car (cdr x)))) (if (> 20864 low-x) (setq high-x (1- high-x) low-x (+ low-x 65536))) (setq low-x (- low-x 20864)) (list high-x low-x nil))) (defun lyskom-calculate-day-diff (time) (let* ((now (current-time)) (yesterday (lyskom-subtract-one-day now)) (decnow (decode-time now)) (decthen (decode-time yesterday))) (cond ((and (= (time->mday time) (elt decnow 3)) (= (time->mon time) (elt decnow 4)) (= (time->year time) (elt decnow 5))) 'today) ((and (= (time->mday time) (elt decthen 3)) (= (time->mon time) (elt decthen 4)) (= (time->year time) (elt decthen 5))) 'yesterday) (t nil)))) (defun lyskom-format-text-footer (text author author-name format format-flags) "Format the footer of a text." (let* ((result "") (start 0) (format-letter nil) (field-width nil) (kom-deferred-printing nil) (author-name-len nil) (have-author (and format (string-match "%=?[0-9]*P" format)))) (setq author-name-len (lyskom-string-width (or author-name (conf-stat->name author)))) ;; No user-specified format, so output dashes and stuff (if (null format) (let* ((format-flag-string (if (and format-flags (listp format-flags)) (let ((first-flag t)) (concat "(" (mapconcat (lambda (str) (let ((face nil)) ;; If it's a cons, the cdr is property list (when (consp str) (setq face (cdr str) str (car str))) ;; Get the string (setq str (lyskom-get-string str)) ;; Upcase the first in the list (when first-flag (setq first-flag nil str (upcase-initials str))) ;; If we have a plist, apply it (when face (add-text-properties 0 (length str) face str)) ;; Return the string str)) format-flags ", ") ")")) "")) (end-dash-chars (- kom-text-footer-dash-length (lyskom-string-width (int-to-string (text-stat->text-no text))) 3 ; Parens and space (if kom-show-author-at-end (+ author-name-len 2) 0) (lyskom-string-width format-flag-string))) (end-dash (if (> end-dash-chars 0) (make-string end-dash-chars ?-) ""))) (lyskom-format (cond ((and kom-dashed-lines kom-show-author-at-end) "(%#1n) /%#2P/%#3s%#4s") (kom-dashed-lines "(%#1n) %#3s%#4s") (kom-show-author-at-end "(%#1n) /%#2P/") (t "(%#1n)")) text (or author-name author) end-dash format-flag-string)) ;; User-specified format. Do all kinds of weird stuff (while (string-match "%\\(=?-?[0-9]+\\)?\\([-nPpf% ]\\)" format start) (setq result (concat result (substring format start (match-beginning 0)))) (setq format-letter (aref format (match-beginning 2))) (setq field-width (match-string 1 format)) (when (null field-width) (setq field-width "")) (setq start (match-end 0)) (setq result (concat result (cond ((eq format-letter ?p) (lyskom-format (format "%%%s#1p" field-width) (or author (text-stat->author text)))) ((eq format-letter ?P) (lyskom-format (format "%%%s#1P" field-width) (or author author-name))) ((eq format-letter ?n) (lyskom-format (format "%%%s#1n" field-width) (text-stat->text-no text))) ((eq format-letter ?f) (if format-flags (lyskom-format (format "%%%s#1s" field-width) (lyskom-get-string format-flags)) "")) ((eq format-letter ?-) (let ((width (cond ((null field-width) 42) ((string= "" field-width) 42) ((eq ?= (aref field-width 0)) (string-to-int (substring field-width 1))) (t (string-to-int field-width))))) (lyskom-format "%#1s" (if have-author (if (< author-name-len width) (make-string (- width author-name-len) ?-) "") (make-string width ?-))))) ((eq format-letter ?%) "%") (t (concat "%" field-width (make-string 1 format-letter)))))) ) (setq result (concat result (substring format start))) (if (string-match "[ \t]+\\'" result) (substring result 0 (match-beginning 0)) result)))) (defun lyskom-deferred-insert-footer (conf-stat defer-info) "Insert the name of a conference at a previously reserved place." (let* ((text-stat (elt (defer-info->data defer-info) 0)) (format-flags (elt (defer-info->data defer-info) 1)) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (name (cond (conf-stat nil) ((= (defer-info->call-par defer-info) 0) (lyskom-get-string 'person-is-anonymous)) (t (lyskom-format 'person-does-not-exist (text-stat->author text-stat)))))) (setq name (or (lyskom-format-mx-author mx-from mx-author) name)) (lyskom-replace-deferred defer-info (lyskom-format-text-footer text-stat conf-stat name kom-text-footer-format format-flags)))) (defun lyskom-print-text (text-stat text mark-as-read text-no flat-review) "Print a text. The header must already be printed. Print an error message if TEXT-STAT or TEXT is nil. Mark the text as read if (and only if) MARK-AS-READ is non-nil. Args: TEXT-STAT TEXT MARK-AS-READ TEXT-NO FLAT-REVIEW." (let* ((lyskom-current-function 'lyskom-print-text) (cti (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)) (content-type (and cti (aux-item->data (car cti))))) (cond ((or (null text) (null text-stat)) (lyskom-format-insert 'no-such-text-no text-no) (setq lyskom-previous-text lyskom-current-text) (setq lyskom-current-text text-no)) (t (when (eq (text-stat->author text-stat) lyskom-pers-no) (setq lyskom-last-seen-written (text-stat->text-no text-stat))) (let* ((str (text->decoded-text-mass text text-stat)) (truncated nil) ;; s1 s2 t1 t2 body) (cond ((and (string-match "\n" str) (not (equal "x-kom/user-area" content-type))) (setq lyskom-current-subject (substring str 0 (match-beginning 0))) (setq body (substring str (match-end 0))) (lyskom-insert-string 'head-Subject) (let ((lyskom-current-function-phase 'subject)) (lyskom-format-insert "%#1r\n" (cons text-stat (copy-sequence lyskom-current-subject)))) (lyskom-format-insert "%#2$%#1s\n" (if kom-dashed-lines (make-string kom-text-header-dash-length ?-) "") (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face)))) ;; (setq t1 (point-max)) ;; Truncate body if flat-review and long text (when (and flat-review (numberp kom-truncate-show-lines) (numberp kom-truncate-threshold)) (let* ((truncated-body (lyskom-truncate-to-lines body kom-truncate-threshold (min kom-truncate-show-lines kom-truncate-threshold)))) (unless (eq truncated-body body) (setq body truncated-body truncated t)))) (let ((lyskom-current-function-phase 'body)) (lyskom-format-insert "%#2$%#1t\n" (cons text-stat body) (and kom-highlight-text-body `(face ,(or kom-text-body-face lyskom-default-text-body-face)))) ) ;; Indicate that the text was truncated (if truncated (lyskom-signal-reformatted-text `(reformat-truncated . (face ,kom-warning-face)))) ;; (setq t2 (point-max)) ) (t ;No \n found. Don't print header. (lyskom-format-insert "%#2$%#1s\n" (if kom-dashed-lines (make-string kom-text-header-dash-length ?-) "") (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face)))) (lyskom-format-insert "%#2$%#1t\n" (cons text-stat str) (and kom-highlight-text-body `(face ,(or kom-text-body-face lyskom-default-text-body-face)))) (setq lyskom-current-subject ""))) (sit-for 0) (let* ((lyskom-current-function-phase 'footer) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (author-name (lyskom-format-mx-author mx-from mx-author))) (if (and kom-deferred-printing (or kom-text-footer-format kom-show-author-at-end)) (progn (lyskom-format-insert "%#2$%#1s\n" lyskom-defer-indicator (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face)))) (lyskom-defer-insertion (lyskom-create-defer-info 'get-conf-stat (text-stat->author text-stat) 'lyskom-deferred-insert-footer (set-marker (make-marker) (- (point-max) (length lyskom-defer-indicator) 1)) (length lyskom-defer-indicator) "%#1s" (list text-stat lyskom-last-text-format-flags)))) (let* ((conf-stat (and (or kom-text-footer-format kom-show-author-at-end) (not (eq 0 (text-stat->author text-stat))) (blocking-do 'get-conf-stat (text-stat->author text-stat))))) (lyskom-format-insert "%#2$%#1s\n" (lyskom-format-text-footer text-stat conf-stat (cond (author-name author-name) ((eq (text-stat->author text-stat) 0) (lyskom-get-string 'person-is-anonymous)) (conf-stat (conf-stat->name conf-stat)) (t (lyskom-format 'person-does-not-exist (text-stat->author text-stat)))) kom-text-footer-format lyskom-last-text-format-flags) (when kom-highlight-dashed-lines `(face ,(or kom-dashed-lines-face lyskom-default-dashed-lines-face))))))) (if mark-as-read (lyskom-mark-as-read text-stat)) (setq lyskom-previous-text lyskom-current-text) (setq lyskom-current-text (text-stat->text-no text-stat))))))) (defun lyskom-mark-as-read (text-stat) "Mark a text as read in all conferences that are recipients. Tell the server that it is read. Args: TEXT-STAT This function does not remove the text from the internal structures of the client. That is done by lyskom-is-read." (let ((misc-info-list (text-stat->misc-info-list text-stat))) (lyskom-traverse misc-info misc-info-list (if (and (memq (misc-info->type misc-info) lyskom-recpt-types-list) ;; The whole membership list might not be fetched ;; yet. So we better mark it as read in all conferences. ;; (lyskom-member-p (misc-info->recipient-no misc-info)) ) (initiate-mark-as-read 'background nil (misc-info->recipient-no misc-info) (list (misc-info->local-no misc-info)) text-stat (misc-info->recipient-no misc-info) (list (misc-info->local-no misc-info))))))) (defun lyskom-print-header-recpt (conf-no misc) "Print a line of info about a recipient (or cc-recipient) of a text." (lyskom-format-insert "%#1s: %#2M <%#3d>\n" (cond ((eq (misc-info->type misc) 'RECPT) (lyskom-get-string 'Recipient)) ((eq (misc-info->type misc) 'BCC-RECPT) (lyskom-get-string 'Hidden-recipient)) ((eq (misc-info->type misc) 'CC-RECPT) (lyskom-get-string 'Extra-recipient)) (t (lyskom-get-string 'Strange-recipient))) conf-no (misc-info->local-no misc)) (if (misc-info->sent-at misc) (lyskom-format-insert 'send-at (lyskom-format-time 'date-and-time (misc-info->sent-at misc)))) (if (misc-info->sender misc) (lyskom-format-insert 'sent-by (misc-info->sender misc))) (if (misc-info->rec-time misc) (lyskom-format-insert 'received-at (lyskom-format-time 'date-and-time (misc-info->rec-time misc))))) (defun lyskom-view-text-handle-saved-comments (text-stat) "Ask server for what is needed to print the references to commenting texts and prints the references. Used at the bottom of the text. Args: TEXT-STAT of the text being read." (lyskom-traverse misc (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc))) (cond ((eq type 'COMM-IN) (lyskom-print-header-comm (misc-info->comm-in misc) misc text-stat)) ((eq type 'FOOTN-IN) (lyskom-print-header-comm (misc-info->footn-in misc) misc text-stat)))))) (defun lyskom-print-header-comm (text misc read-text-stat) "Get author of TEXT-NO and print a header line." (let ((text-stat (if kom-deferred-printing (cache-get-text-stat text) (blocking-do 'get-text-stat text)))) ;; Print information about the link (cond (text-stat (lyskom-insert-header-comm text-stat misc read-text-stat)) ((not kom-deferred-printing) (lyskom-insert-header-comm text-stat misc read-text-stat)) (t (let ((defer-info (lyskom-create-defer-info 'get-text-stat text 'lyskom-insert-deferred-header-comm (point-max-marker) (length lyskom-defer-indicator) nil ; Filled in later (list misc read-text-stat)))) (lyskom-format-insert "%#1s\n" lyskom-defer-indicator) (lyskom-defer-insertion defer-info)))) ;; Print information about who added the link (if (misc-info->sent-at misc) (lyskom-format-insert 'send-at (lyskom-format-time 'date-and-time (misc-info->sent-at misc)))) (if (misc-info->sender misc) (lyskom-format-insert 'sent-by (misc-info->sender misc))))) (defun lyskom-insert-deferred-header-comm (text-stat defer-info) (let* ((author (if text-stat (text-stat->author text-stat) nil)) (misc (elt (defer-info->data defer-info) 0)) (read-text-stat (elt (defer-info->data defer-info) 1)) (type (misc-info->type misc)) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (read-mx-from (car (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (mx-attachments-in (lyskom-get-text-attachments read-text-stat)) (mx-belongs-to (mapcar (lambda (el) (string-to-number (aux-item->data el))) (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 10100))) (content-type "") (read-content-type "") fmt data) (setq author (or (lyskom-format-mx-author mx-from mx-author) author)) ;; Extract the content type (if (and mx-from (setq content-type (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data content-type)) (setq content-type (format "(%s) " (aux-item->data content-type)))) (setq content-type "")) (if (and read-mx-from (setq read-content-type (car (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data read-content-type)) (setq read-content-type (format "(%s) " (aux-item->data read-content-type)))) (setq read-content-type "")) (cond ((eq type 'COMM-TO) (setq fmt (cond ((memq (misc-info->comm-to misc) mx-belongs-to) 'attachment-to-text) (author 'comment-to-text-by) (t 'comment-to-text)) content-type read-content-type data (misc-info->comm-to misc))) ((eq type 'FOOTN-TO) (setq fmt (cond ((memq (misc-info->footn-to misc) mx-belongs-to) 'attachment-to-text) (author 'footnote-to-text-by) (t 'footnote-to-text)) content-type read-content-type data (misc-info->footn-to misc))) ((eq type 'COMM-IN) (setq fmt (cond ((memq (misc-info->comm-in misc) mx-attachments-in) 'attachment-in-text) (author 'comment-in-text-by) (t 'comment-in-text)) data (misc-info->comm-in misc))) ((eq type 'FOOTN-IN) (setq fmt (cond ((memq (misc-info->footn-in misc) mx-attachments-in) 'attachment-in-text) (author 'footnote-in-text-by) (t 'footnote-in-text)) data (misc-info->footn-in misc)))) (set-defer-info->format defer-info fmt) ; Note: author is ignored if fmt is not *-by (lyskom-replace-deferred defer-info data author content-type))) (defun lyskom-insert-header-comm (text-stat misc read-text-stat) "Get author of TEXT-NO and print a header line." ;;+++ error kommer att se annorlunda ut. (let ((author (if text-stat (text-stat->author text-stat) nil)) (mx-from (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 17))) (read-mx-from (car (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 17))) (mx-author (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 16))) (mx-attachments-in (lyskom-get-text-attachments read-text-stat)) (mx-belongs-to (mapcar (lambda (el) (string-to-number (aux-item->data el))) (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 10100))) (content-type "") (read-content-type "") (is-attachment nil) (type (misc-info->type misc))) (setq author (or (lyskom-format-mx-author mx-from mx-author) author)) ;; Extract the content type (if (and mx-from (setq content-type (car (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data content-type)) (setq content-type (format "(%s) " (aux-item->data content-type)))) (setq content-type "")) (if (and read-mx-from (setq read-content-type (car (lyskom-get-aux-item (text-stat->aux-items read-text-stat) 1)))) (progn (string-match "^\\(\\S-+\\)" (aux-item->data read-content-type)) (setq read-content-type (format "(%s) " (aux-item->data read-content-type)))) (setq read-content-type "")) (cond ((eq type 'COMM-TO) (lyskom-format-insert (if (and (memq (misc-info->comm-to misc) mx-belongs-to) (setq is-attachment t)) 'attachment-to-text 'comment-to-text) (misc-info->comm-to misc) nil read-content-type)) ((eq type 'FOOTN-TO) (lyskom-format-insert (if (and (memq (misc-info->footn-to misc) mx-belongs-to) (setq is-attachment t)) 'attachment-to-text 'footnote-to-text) (misc-info->footn-to misc) nil read-content-type)) ((eq type 'COMM-IN) (lyskom-format-insert (if (and (memq (misc-info->comm-in misc) mx-attachments-in) (setq is-attachment t)) 'attachment-in-text 'comment-in-text) (misc-info->comm-in misc) nil content-type)) ((eq type 'FOOTN-IN) (lyskom-format-insert (if (and (memq (misc-info->footn-in misc) mx-attachments-in) (setq is-attachment t)) 'attachment-in-text 'footnote-in-text) (misc-info->footn-in misc) nil content-type))) (if (and author (not is-attachment)) (lyskom-format-insert 'written-by author) (lyskom-insert "\n")))) (defun lyskom-format-mx-author (mx-from mx-author) (let ((author nil) (mx-author (if (and mx-author (equal (aux-item->data mx-author) "")) nil mx-author))) (when (or mx-from mx-author) (setq author (lyskom-get-string 'email-name-prefix)) (when mx-author (setq author (concat author (aux-item->data mx-author)))) (when (and mx-from mx-author) (setq author (concat author " "))) (when mx-from (setq author (concat author (lyskom-format "<%[%#1@%#2s%]>" (lyskom-default-button 'email (aux-item->data mx-from)) (aux-item->data mx-from))))) (setq author (concat (lyskom-get-string 'email-name-suffix) author)) ) author)) (lyskom-with-external-functions (calendar-iso-from-absolute calendar-absolute-from-gregorian) (defun lyskom-mx-date-to-time (mx-date) "Attempt to convert MX-DATE to a lyskom time structure. Returns the time structure if successful, otherwise nil." (if (and mx-date (condition-case nil (progn (require 'calendar) (require 'cal-iso) t) (error nil)) (string-match "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\) \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\) \\([-+][0-9][0-9]\\)?\\([0-9][0-9]\\)?" (aux-item->data mx-date))) (let* ((secs (string-to-number (match-string 6 (aux-item->data mx-date)))) (mins (string-to-number (match-string 5 (aux-item->data mx-date)))) (hour (string-to-number (match-string 4 (aux-item->data mx-date)))) (mday (string-to-number (match-string 3 (aux-item->data mx-date)))) (mon (string-to-number (match-string 2 (aux-item->data mx-date)))) (year (string-to-number (match-string 1 (aux-item->data mx-date)))) (tzhr (match-string 7 (aux-item->data mx-date))) (tzmin (or (match-string 8 (aux-item->data mx-date)) "")) (wday (abs (elt (calendar-iso-from-absolute (calendar-absolute-from-gregorian (list mon mday year))) 1)))) (lyskom-create-time secs mins hour mday mon year wday 0 nil tzhr tzmin))))) ;;; Local Variables: ;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2) ;;; end: ;;;;; ;;;;; $Id: async.el,v 44.65 2004/11/12 10:54:56 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: async.el ;;;; ;;;; These functions implement a nice service that give the user ;;;; continuous messages about what other users are doing and what ;;;; is happening inside the lyskom server. ;;;; ;;;; Author: Linus Tolke ;;;; Entry: Inge Wallin ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: async.el,v 44.65 2004/11/12 10:54:56 _cvs_pont_lyskomelisp Exp $\n")) (defun lyskom-is-ignoring-async (buffer message &rest args) (save-excursion (set-buffer buffer) (let ((tmp (assq message lyskom-ignoring-async-list))) (and tmp (equal args (cdr tmp)))))) (defun lyskom-parse-async (tokens buffer) "Parse an asynchronous message from the server. The message consists of TOKENS tokens. Unknown messages are skipped. Actions are taken to perform the various tasks that is required on reciept of an asynchronous message. If variable `kom-presence-messages-in-echo-area' is non-nil or some minibuffer editing is going on then nothing is printed on the message area. This function is called with the lyskom-unparsed-buffer as current-buffer. All calls using the lyskom-variables have to be made using the buffer BUFFER. Be careful when editing this. All parsing is done with the buffer this function is called with as the current-buffer, while all calls from this function shall be with current-buffer the BUFFER." (let ((msg-no (lyskom-parse-num))) (cond ((or (eq msg-no 0) (eq msg-no 15)) ; New text (let* ((text-no (lyskom-parse-num)) (text-stat (if (eq msg-no 0) (lyskom-parse-text-stat-old text-no) (lyskom-parse-text-stat text-no)))) (lyskom-save-excursion (set-buffer buffer) (lyskom-async-new-text text-stat)))) ; ((eq msg-no 1) ; Logout (obsolete) (lyskom-skip-tokens tokens)) ((eq msg-no 2) ; Login, obsolete. (lyskom-skip-tokens tokens)) ((eq msg-no 3) ; Conference deleted (lyskom-skip-tokens tokens)) ((eq msg-no 4) ; Conference created (lyskom-skip-tokens tokens)) ((eq msg-no 5) ; A person or conference has ; changed name. (let ((conf-no (lyskom-parse-num)) (old-name (lyskom-parse-string)) (new-name (lyskom-parse-string))) (lyskom-save-excursion (set-buffer buffer) (if (and lyskom-pers-no (= conf-no lyskom-pers-no)) (lyskom-format-insert-before-prompt 'you-changed-name-to new-name (lyskom-default-button 'conf conf-no))) (let ((cached-stat (cache-get-conf-stat conf-no)) (cached-ustat (cache-get-uconf-stat conf-no))) (when cached-stat (set-conf-stat->name cached-stat new-name)) (when cached-ustat (set-uconf-stat->name cached-ustat new-name))) (cond ((lyskom-is-in-minibuffer)) ((lyskom-show-presence conf-no kom-presence-messages-in-echo-area) (lyskom-message "%s" (lyskom-format 'name-has-changed-to-name old-name new-name)))) (cond ((lyskom-show-presence conf-no kom-presence-messages-in-buffer) (lyskom-format-insert-before-prompt 'name-has-changed-to-name-r old-name new-name (lyskom-default-button 'conf conf-no)))) ;; Update in the mship-edit buffer (lp--maybe-update-entry-for-conf conf-no)))) ((eq msg-no 6) ;i_am_on - something is moving (lyskom-parse-who-info)) ((eq msg-no 7) ; Database is syncing. (lyskom-save-excursion (set-buffer buffer) ;; I removed the test for kom-presence-messages /david (if (and (not (lyskom-is-in-minibuffer)) kom-show-sync-messages) (lyskom-message "%s" (lyskom-get-string 'database-sync))) (setq mode-line-process (lyskom-get-string 'mode-line-saving)) (setq lyskom-is-saving t) ;; I guess the following two lines could be replaced by ;; force-mode-line-update in a modern emacs. (set-buffer-modified-p (buffer-modified-p)) (sit-for 0) (if (not lyskom-pending-calls) (initiate-get-time 'async nil)))) ((eq msg-no 8) ; Forced leave conference (let ((conf-no (lyskom-parse-num))) (unless (lyskom-is-ignoring-async buffer 8 conf-no) (lyskom-save-excursion (set-buffer buffer) (initiate-get-conf-stat 'follow 'lyskom-async-forced-leave-conf conf-no conf-no))))) ((eq msg-no 9) ; A person has logged in (let ((pers-no (lyskom-parse-num)) ;;;(session-no (lyskom-parse-num)) ) (lyskom-parse-num) (lyskom-save-excursion (set-buffer buffer) (if (and lyskom-pers-no (not (zerop lyskom-pers-no)) (/= pers-no lyskom-pers-no)) ; Don't show myself. (initiate-get-conf-stat 'follow 'lyskom-show-logged-in-person pers-no)) ))) ;; msg-no 10 is the old broadcast message. No longer used. ((eq msg-no 11) (lyskom-save-excursion (set-buffer buffer) (lyskom-insert-before-prompt (lyskom-get-string-sol 'lyskom-is-full)) )) ((eq msg-no 12) ; Message to the user (or everybody) (let ((recipient (lyskom-parse-num)) (sender (lyskom-parse-num)) (message (lyskom-parse-string))) (lyskom-save-excursion (set-buffer buffer) (if (zerop recipient) (initiate-get-conf-stat 'async 'lyskom-handle-personal-message sender 0 message) (lyskom-collect 'async) (initiate-get-conf-stat 'async nil sender) (initiate-get-conf-stat 'async nil recipient) (lyskom-use 'async 'lyskom-handle-personal-message message))))) ((eq msg-no 13) ; New logout (let ((pers-no (lyskom-parse-num)) (session-no (lyskom-parse-num))) (lyskom-save-excursion (set-buffer buffer) (if (and lyskom-pers-no (not (zerop lyskom-pers-no)) (/= lyskom-pers-no pers-no) (or (lyskom-show-presence pers-no kom-presence-messages-in-echo-area) (lyskom-show-presence pers-no kom-presence-messages-in-buffer))) (initiate-get-conf-stat 'follow 'lyskom-show-logged-out-person pers-no session-no))))) ((eq msg-no 14) ; Deleted text (let* ((text-no (lyskom-parse-num)) (text-stat (lyskom-parse-text-stat text-no))) (lyskom-save-excursion (set-buffer buffer) (lyskom-async-deleted-text text-stat)))) ((eq msg-no 16) ; New recipient (let ((text-no (lyskom-parse-num)) (conf-no (lyskom-parse-num)) (misc-type (lyskom-parse-num))) (cond ((eq misc-type 0) (setq misc-type 'RECPT)) ((eq misc-type 1) (setq misc-type 'CC-RECPT)) ((eq misc-type 15) (setq misc-type 'BCC-RECPT))) (when (symbolp misc-type) (lyskom-save-excursion (set-buffer buffer) (cache-del-text-stat text-no) (cache-del-conf-stat conf-no) (initiate-get-text-stat 'follow 'lyskom-async-new-recipient text-no text-no conf-no misc-type) )))) ((eq msg-no 17) ; Deleted recipient (let ((text-no (lyskom-parse-num)) (conf-no (lyskom-parse-num)) (misc-type (lyskom-parse-num))) (lyskom-save-excursion (set-buffer buffer) (cache-del-conf-stat conf-no) (cache-del-text-stat text-no) ;; FIXME: Code here. ;; FIXME: This implementation sucks. There is no need to ;; FIXME: remove the text from the cache. Just modify it. ;; FIXME: If we cache maps somewhere, we'll want to remove ;; FIXME: the text from the appropriate map. ;; FIXME: If we want to get *really* picky, and the user is ;; FIXME: doing a review texts to conference, and this text ;; FIXME: has been found, remove this text from those ;; FIXME: lists too (probably not worth the effort). ;; FIXME: The text should be removed from the reading lists ;; FIXME: if it is there because we are reading the conf ;; FIXME: that is being removed. Take care not to lose ;; FIXME: any comments to it though... ;; FIXME: The unread counter for the conference should be ;; FIXME: decreased like it is in async-deleted-text (i hope). (lyskom-ignore misc-type) ))) ((eq msg-no 18) ; New membership (let ((pers-no (lyskom-parse-num)) (conf-no (lyskom-parse-num))) (unless (lyskom-is-ignoring-async buffer 18 pers-no conf-no) (lyskom-save-excursion (set-buffer buffer) (cache-del-pers-stat pers-no) (cache-del-conf-stat conf-no) (when (eq pers-no lyskom-pers-no) (lyskom-collect 'follow) (initiate-get-conf-stat 'follow nil conf-no) (initiate-query-read-texts 'follow nil pers-no conf-no t 0) (lyskom-use 'follow 'lyskom-async-new-membership pers-no conf-no)) )))) ((eq msg-no 19) ; async-new-user-area (let* ((pers-no (lyskom-parse-num)) (old-user-area (lyskom-parse-num)) (new-user-area (lyskom-parse-num))) (lyskom-save-excursion (set-buffer buffer) (when (and (eq pers-no lyskom-pers-no) (not (eq lyskom-current-user-area new-user-area))) (initiate-get-pers-stat 'follow 'lyskom-async-new-user-area pers-no old-user-area new-user-area))))) ((eq msg-no 20) ; async-new-presentation (let* ((conf-no (lyskom-parse-num)) (old-pres (lyskom-parse-num)) (new-pres (lyskom-parse-num))) (lyskom-ignore old-pres) (lyskom-save-excursion (set-buffer buffer) (when (cache-get-conf-stat conf-no) (set-conf-stat->presentation (cache-get-conf-stat conf-no) new-pres) (lp--maybe-update-entry-for-conf conf-no))))) ((eq msg-no 21) ; async-new-motd (let* ((conf-no (lyskom-parse-num)) (old-motd (lyskom-parse-num)) (new-motd (lyskom-parse-num))) (lyskom-save-excursion (set-buffer buffer) (lyskom-ignore old-motd) (when (cache-get-conf-stat conf-no) (set-conf-stat->msg-of-day (cache-get-conf-stat conf-no) new-motd))))) ((eq msg-no 22) ; async-text-aux-changes (let* ((text-no (lyskom-parse-num)) (deleted-aux (lyskom-parse-aux-item-list)) (added-aux (lyskom-parse-aux-item-list)) (text-stat nil)) (lyskom-save-excursion (set-buffer buffer) (setq text-stat (cache-get-text-stat text-no)) (when text-stat (set-text-stat->aux-items text-stat (lyskom-aux-item-modify-list (text-stat->aux-items text-stat) deleted-aux added-aux)))))) (t (lyskom-skip-tokens tokens))))) (defun lyskom-async-new-user-area (pers-stat old-user-area new-user-area) (when pers-stat (let ((need-reread (and (eq lyskom-pers-no (pers-stat->pers-no pers-stat)) (not (eq lyskom-current-user-area new-user-area))))) ;; Update the cache (set-pers-stat->user-area pers-stat new-user-area) ;; Re-read (when (and need-reread new-user-area (not (zerop new-user-area))) (initiate-get-text 'follow (lambda (text) (when text (lyskom-format-insert-before-prompt 'reading-settings-from-server) (setq lyskom-saved-unknown-variables (lyskom-read-options-eval text)))) new-user-area))))) (defun lyskom-async-forced-leave-conf (conf-stat conf-no) (if conf-stat (lyskom-format-insert-before-prompt 'no-longer-member conf-stat) (lyskom-format-insert-before-prompt 'no-longer-member-n conf-no)) (lyskom-remove-membership conf-no) (when (eq conf-no lyskom-current-conf) (lyskom-leave-current-conf)) (read-list-delete-read-info conf-no lyskom-to-do-list) (lyskom-update-prompt)) (defun lyskom-async-new-membership (conf-conf-stat membership pers-no conf-no) ;; Are we already members? (when membership (let ((cur-mship (lyskom-try-get-membership conf-no t)) (mship-type (membership->type membership))) (unless cur-mship (lyskom-format-insert-before-prompt (cond ((membership-type->invitation mship-type) 'have-become-invited-member) ((membership-type->passive mship-type) 'have-become-passive-member) (t 'have-become-member)) conf-conf-stat)) (cond ((membership-type->passive (membership->type membership)) (lyskom-replace-membership membership) (when (eq conf-no lyskom-current-conf) (lyskom-leave-current-conf)) (read-list-delete-read-info conf-no lyskom-to-do-list) (lyskom-update-prompt)) ;; Already a member. Perhaps the priority changed. ;; Update the cache. The reading list is probably also ;; not quite correct since the priority might have changed (cur-mship (lyskom-replace-membership membership) (lyskom-sort-to-do-list)) ;; Not a member. Completely new. Deal with it. (t (lyskom-add-membership membership conf-no)))))) (defun lyskom-show-presence (num flag) "Returns non-nil if presence messages for NUM should be displayed according to the value of FLAG." (cond ((null flag) nil) ((eq flag 'friends) (memq num kom-friends)) ((eq flag 'morons) (memq num kom-morons)) ((eq flag 'friends-and-morons) (or (memq num kom-friends) (memq num kom-morons))) ((listp flag) (memq num flag)) (t t))) (defun lyskom-show-logged-in-person (conf-stat) "Visa p} kommandoraden vem som loggat in." (let ((server (lyskom-session-nickname))) (cond ((lyskom-is-in-minibuffer)) ((lyskom-show-presence (conf-stat->conf-no conf-stat) kom-presence-messages-in-echo-area) (lyskom-message "%s" (lyskom-format 'has-entered (or conf-stat (lyskom-get-string 'unknown-person)) server )))) (cond ((lyskom-show-presence (conf-stat->conf-no conf-stat) kom-presence-messages-in-buffer) (if conf-stat (lyskom-format-insert-before-prompt 'has-entered-r conf-stat (and kom-text-properties `(face ,kom-presence-face)) server) (lyskom-format-insert-before-prompt 'has-entered-r (lyskom-get-string 'unknown-person) (and kom-text-properties `(face ,kom-presence-face)) server)))))) (defun lyskom-show-logged-out-person (conf-stat session-no) "Visa p} kommandoraden vem som loggat ut." (let ((server (lyskom-session-nickname))) (cond ((lyskom-is-in-minibuffer)) ((lyskom-show-presence (conf-stat->conf-no conf-stat) kom-presence-messages-in-echo-area) (lyskom-message "%s" (lyskom-format 'has-left (or conf-stat (lyskom-get-string 'unknown-person)) server)))) (cond ((lyskom-show-presence (conf-stat->conf-no conf-stat) kom-presence-messages-in-buffer) (if conf-stat (lyskom-format-insert-before-prompt 'has-left-r conf-stat (and kom-text-properties `(face ,kom-presence-face)) server) (lyskom-format-insert-before-prompt 'has-left-r (lyskom-get-string 'unknown-person) (and kom-text-properties `(face ,kom-presence-face)) server)))))) (defun lyskom-is-in-minibuffer () "Returns non-nil if I am using the minibuffer for some reading." (or lyskom-inhibit-minibuffer-messages cursor-in-echo-area (not (zerop (minibuffer-depth))))) (defun lyskom-show-personal-message (sender recipient message &optional when nobeep) "Insert a personal message into the lyskom buffer. Args: SENDER: conf-stat for the person sending the message. RECIPIENT: 0 if this message is for everybody, otherwise the conf-stat of the recipient. MESSAGE: A string containing the message. WHEN: Optional time of arrival. A lyskom time structure. NOBEEP: True means don't beep. No matter what." (lyskom-insert-personal-message sender recipient message when nobeep) (setq lyskom-last-personal-message-sender (if (stringp sender) sender (conf-stat->conf-no sender))) (setq lyskom-last-group-message-recipient (if (and recipient (not (eq 0 recipient)) (not (eq (conf-stat->conf-no recipient) lyskom-pers-no))) (conf-stat->conf-no recipient) nil)) (run-hooks 'lyskom-personal-message-hook) (run-hooks 'kom-personal-message-hook)) (defun lyskom-insert-personal-message (sender recipient message &optional when nobeep) "Insert a personal message in the current buffer. Arguments: SENDER RECIPIENT MESSAGE. SENDER is a conf-stat (possibly nil). RECIPIENT is 0 if the message is public, otherwise the conf-stat of the recipient. MESSAGE is a string containing the message. WHEN, if given, is the time when the message arrived. It must be a lyskom time structure. Non-nil NOBEEP means don't beep." (lyskom-handle-as-personal-message (lyskom-format-as-personal-message sender recipient message when nobeep) (conf-stat->conf-no sender) nil)) (defun lyskom-format-as-personal-message (sender recipient message &optional when nobeep) "Formats a personal message, returning it as a string. Arguments: SENDER RECIPIENT MESSAGE. SENDER is a conf-stat (possibly nil). RECIPIENT is 0 if the message is public, otherwise the conf-stat of the recipient. MESSAGE is a string containing the message. WHEN, if given, is the time when the message arrived. It must be a lyskom time structure. Non-nil NOBEEP means don't beep." (let ((lyskom-last-text-format-flags nil) (now (lyskom-current-client-time))) (when (null when) (setq when (lyskom-current-client-time))) (if (or kom-show-personal-message-date (not (eq (time->mday when) (time->mday now))) (not (eq (time->mon when) (time->mon now))) (not (eq (time->year when) (time->year now)))) (setq when (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time when))) (setq when (lyskom-format-time 'time when))) (setq nobeep (or nobeep (and kom-ansaphone-on kom-silent-ansaphone))) (cond ((or (null recipient) ; Have been seen to be nil when ; listing recorded ; messages. Should it be? ; /davidk (eq recipient 0)) ; Public message (if (not nobeep) (lyskom-beep kom-ding-on-common-messages sender)) (lyskom-format (lyskom-get-string-sol 'message-broadcast) (cond ((stringp sender) sender) (sender sender) (t (lyskom-get-string 'unknown))) message when (when kom-async-highlight-dashed-lines `(face ,(or kom-async-dashed-lines-face lyskom-default-async-dashed-lines-face))) (when kom-async-highlight-text-body `(face ,(or kom-async-text-body-face lyskom-default-async-text-body-face))))) ((= (conf-stat->conf-no recipient) lyskom-pers-no) ; Private (if (not nobeep) (lyskom-beep kom-ding-on-personal-messages sender)) (lyskom-format (lyskom-get-string-sol 'message-from) (cond ((stringp sender) sender) (sender sender) (t (lyskom-get-string 'unknown))) message when (when kom-async-highlight-dashed-lines `(face ,(or kom-async-dashed-lines-face lyskom-default-async-dashed-lines-face))) (when kom-async-highlight-text-body `(face ,(or kom-async-text-body-face lyskom-default-async-text-body-face))))) (t ; Group message (if (not nobeep) (lyskom-beep kom-ding-on-group-messages recipient)) (lyskom-format (lyskom-get-string-sol 'message-from-to) message (cond ((stringp sender) sender) (sender sender) (t (lyskom-get-string 'unknown))) (cond ((stringp recipient) recipient) (recipient recipient) (t (lyskom-get-string 'unknown))) when (when kom-async-highlight-dashed-lines `(face ,(or kom-async-dashed-lines-face lyskom-default-async-dashed-lines-face))) (when kom-async-highlight-text-body `(face ,(or kom-async-text-body-face lyskom-default-async-text-body-face)))))))) (defun lyskom-handle-as-personal-message (string from &optional filter) "Insert STRING as a personal message and beep if not from me and supposed to. The buffer, is chosen according to the kom-show-personal-messages-in-buffer variable value. The text is converted, before insertion." (if (and filter (or (eq 0 (string-match "^Remote-command: [0-9]+ [0-9]+\n" string)) (eq 0 (string-match "^Auto-reply:\n" string)))) nil (let ((pop kom-pop-personal-messages)) (lyskom-save-excursion (cond ((eq kom-show-personal-messages-in-buffer t) (lyskom-insert-before-prompt string) (if pop (display-buffer (current-buffer)))) ((null kom-show-personal-messages-in-buffer)) (t (let ((inhibit-read-only t)) (let ((message-buffer (car (lyskom-buffers-of-category 'personal-messages)))) (if message-buffer (set-buffer message-buffer) (set-buffer (lyskom-get-buffer-create 'personal-messages kom-show-personal-messages-in-buffer t)) (lyskom-view-mode) (setq buffer-read-only t))) (goto-char (point-max)) (lyskom-insert string ) (if pop (save-selected-window (select-window (lyskom-display-buffer (current-buffer) (not (eq pop t)))) (goto-char (point-max)) (recenter -1)))))))))) ;;; ================================================================ ;;; New recipient ;;; The text stat and might have been cached and thus invalid. Check ;;; for this. The conf-stat for the conf-no is almost certainly ;;; invalid. (defun lyskom-async-new-recipient (text-stat text-no conf-no misc-type) "Handle a new recipient message" ;; Check if we are added. A new letter! (when (and (eq conf-no lyskom-pers-no) (not (eq (text-stat->author text-stat) lyskom-pers-no))) (lyskom-beep kom-ding-on-new-letter)) ;; If the text is read in another conference, mark it as read here too ;; unless the new recipient is the mailbox (if (and kom-mark-read-texts-as-read-in-new-recipient (lyskom-text-read-at-least-once-p text-stat t) (not (eq conf-no lyskom-pers-no))) (lyskom-traverse misc-info (text-stat->misc-info-list text-stat) (when (and (memq (misc-info->type misc-info) lyskom-recpt-types-list) (eq conf-no (misc-info->recipient-no misc-info))) (initiate-mark-as-read 'follow nil conf-no (list (misc-info->local-no misc-info))))) ;; Text is previously unread or in the mailbox (let ((local-no nil)) (lyskom-traverse misc-info (text-stat->misc-info-list text-stat) (when (and (eq (misc-info->type misc-info) misc-type) (eq (misc-info->recipient-no misc-info) conf-no)) (setq local-no (misc-info->local-no misc-info)))) (when local-no (initiate-get-conf-stat 'async 'lyskom-add-new-text conf-no text-no local-no) (lyskom-prefetch-text-all text-no) (lyskom-run 'async 'lyskom-default-new-recipient-hook text-stat) (lyskom-run 'async 'lyskom-prefetch-and-print-prompt))))) (defun lyskom-default-new-recipient-hook (text-stat) (when (and (not lyskom-dont-change-prompt) ;We shall change it (not lyskom-executing-command)) ;We have time to do it. (lyskom-update-prompt)) (run-hooks 'lyskom-new-recipient-hook) (run-hooks 'kom-new-recipient-hook)) ;;; ================================================================ ;;; Functions for dealing with a new or deleted text (defun lyskom-default-new-text-hook (text-stat) "Print a message if the user was waiting. Change the prompt. run hooks." (if (and (not lyskom-dont-change-prompt) ;We shall change it (not lyskom-executing-command)) ;We have time to do it. (lyskom-update-prompt)) (let ((no-message nil)) (run-hooks 'lyskom-new-text-hook) (run-hooks 'kom-new-text-hook) (if (and (not no-message) lyskom-is-waiting (not (lyskom-is-in-minibuffer))) (lyskom-message "%s" (lyskom-format 'text-is-created (text-stat->text-no text-stat)))))) (defun lyskom-default-deleted-text-hook (text-stat) "Update the prompt. Run hooks" (if (and (not lyskom-dont-change-prompt) ;We shall change it (not lyskom-executing-command)) ;We have time to do it. (lyskom-update-prompt)) (run-hooks 'lyskom-deleted-text-hook) (run-hooks 'kom-deleted-text-hook)) (defun lyskom-async-new-text (text-stat) "Take care of a message that a new text has been created." (cache-del-pers-stat (text-stat->author text-stat)) ;+++Borde {ndra i cachen i st{llet. (lyskom-traverse misc-info (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc-info))) (cond ((memq type lyskom-recpt-types-list) ;; add on lyskom-reading-list and lyskom-to-do-list if ;; this recipient is a recipient that has been checked. (if (and (eq (misc-info->recipient-no misc-info) lyskom-pers-no) (not (eq (text-stat->author text-stat) lyskom-pers-no))) (lyskom-beep kom-ding-on-new-letter)) (initiate-get-conf-stat 'async 'lyskom-add-new-text (misc-info->recipient-no misc-info) (text-stat->text-no text-stat) (misc-info->local-no misc-info))) ((eq type 'COMM-TO) (cache-del-text-stat (misc-info->comm-to misc-info))) ((eq type 'FOOTN-TO) (cache-del-text-stat (misc-info->footn-to misc-info))) (t (signal 'lyskom-internal-error (list 'lyskom-async-new-text "Unexpected misc-info in new text " type)))))) (lyskom-prefetch-text-stat-all text-stat) ;; Give a message if the user is waiting. Update the prompt. (lyskom-run 'async 'lyskom-default-new-text-hook text-stat) (lyskom-run 'async 'lyskom-prefetch-and-print-prompt)) (defun lyskom-async-deleted-text (text-stat) "Take care of a message that a text has been deleted." (cache-del-pers-stat (text-stat->author text-stat)) (lyskom-traverse misc-info (text-stat->misc-info-list text-stat) (let ((type (misc-info->type misc-info))) (cond ((memq type lyskom-recpt-types-list) (initiate-get-conf-stat 'async 'lyskom-delete-old-text (misc-info->recipient-no misc-info) text-stat (misc-info->local-no misc-info))) ((eq type 'COMM-TO) (cache-del-text-stat (misc-info->comm-to misc-info))) ((eq type 'FOOTN-TO) (cache-del-text-stat (misc-info->footn-to misc-info)))))) (lyskom-run 'async 'lyskom-default-deleted-text-hook text-stat) (lyskom-run 'async 'lyskom-prefetch-and-print-prompt)) (defun lyskom-delete-old-text (recipient text-stat local-no) "RECIPIENT is a conf-stat and previous recipient of TEXT-STAT. This call is used in response to a deleted text message" (when recipient ;; Update the cache (cache-del-text-stat (text-stat->text-no text-stat)) (cache-del-text (text-stat->text-no text-stat)) (set-conf-stat->no-of-texts recipient (min (conf-stat->no-of-texts recipient) (min (conf-stat->no-of-texts recipient) (1- (conf-stat->no-of-texts recipient))))) ;; Update the read lists (let ((membership (lyskom-try-get-membership (conf-stat->conf-no recipient)))) (when (and membership (lyskom-visible-membership membership)) (read-list-delete-text (text-stat->text-no text-stat) lyskom-to-do-list) (read-list-delete-text (text-stat->text-no text-stat) lyskom-reading-list))) (lyskom-set-mode-line))) (defun lyskom-add-new-text (recipient text-no local-no) "RECIPIENT is a conf-stat and recipient of TEXT-NO. Args: RECIPIENT TEXT-NO LOCAL-NO. LOCAL-NO is the texts local number in RECIPIENT. This info is used to update the no-of-texts field in the cache. Also add this info in lyskom-to-do-list if info about RECIPIENT as been fetched. Does not try to print prompt or do any prefetch. That will be done after all the confs has been handled. If recipient is nil this means we are crossposting to a protected conference. In that case, just discard this call." (cond (recipient ;+++ Annan felhantering. ;; Update the cache. (set-conf-stat->no-of-texts recipient (max (conf-stat->no-of-texts recipient) (+ local-no -1 (- (conf-stat->first-local-no recipient))))) ;; Update the read-lists. ;; Prefetch thoughts: ;; We need a way to check if a conferences is fetched. ;; davidk /960924 (let ((membership (lyskom-try-get-membership (conf-stat->conf-no recipient)))) (if (and membership ;; (lyskom-conf-fetched-p (conf-stat->conf-no recipient)) (lyskom-visible-membership membership) (not (read-list-enter-text text-no recipient lyskom-to-do-list))) ;; If we have already read all texts in the conference or the ;; text has not been prefetched (let ((info (lyskom-create-read-info 'CONF recipient (membership->priority membership) (lyskom-create-text-list (list text-no))))) (read-list-enter-read-info info lyskom-to-do-list) (if (= lyskom-current-conf (conf-stat->conf-no recipient)) (read-list-enter-read-info info lyskom-reading-list))) ;; We don't have the membership yet. Treat it as an unread conf ;; and prefetch it. This might result in two prefetches of the ;; same conference, but the prefetch should be able to deal with ;; that. (unless membership (lyskom-prefetch-one-membership (conf-stat->conf-no recipient) lyskom-pers-no)))) (lyskom-set-mode-line)))) ;;; Local Variables: ;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2) ;;; end: ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: mship-edit.el,v 44.53 2005/01/09 22:09:00 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: mship-edit.el ;;;; ;;;; Mode for editing the membership. Replaced prioritize.el ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: mship-edit.el,v 44.53 2005/01/09 22:09:00 byers Exp $\n")) ;; KNOWN BUGS AND TO DO ;; -------------------- ;; ;; Messed up redraw of an entry ;; ;; Sometimes an entry will be redrawn and appear twice, with one of ;; the old entries on the same line as one of the duplicates. This ;; seems to happen if two redraws using delayed printing are initiated ;; at once (the second starts before the first one finishes). ;; ;; Remembers that lyskom-insert-membership and lyskom-replace-membership ;; call lp--update-buffer, so it's rarely necessary to call it from ;; anywhere else. ;; ;; Endast-function to all marked memberships ;; ;; Uppskjut-function to all marked memberships ;; ;; Remove and add membership functions. ;; (require 'advice) ;;; Code: (def-komtype lp--entry (start-marker ; Where the entry is in the buffer end-marker ; Where it ends in the buffer priority ; The saved priority of the membership membership ; The membership selected ; Selected or not state ; Expanded display or not visible ; Non-nil when visible extents ; Alist of extents/overlays )) (defvar lp--format-string nil "The format string for entries.") ;;; Local variables in the prioritize buffer ;;; There should be no reason to use these at all. There are functional ;;; abstractions that let you access their contents. (defvar lp--entry-list nil) (defvar lp--headers nil) (defvar lp--header-end-marker nil) (defvar lp--list-start-marker nil) (defvar lp--list-end-marker nil) (defvar lp--selected-entry-list nil) (defvar lp--buffer-done nil) (defvar lp--conf-name-width nil) (defvar lp--inhibit-update nil) (defvar lp--hidden-entries nil) (defvar lp--entry-filter nil) ;;; ============================================================ ;;; Utility functions and really basic stuff (defun lp--entry-update-extents (entry) "Update the start and end positions for extents of ENTRY. Update the start and end positions of all extents or overlays listed in the extent list of ENTRY to match the start and end markers. If the start or end markers point nowhere, detatch the extents. If overlays are used, set the start and end positions to zero." (let ((extents (lp--entry->extents entry))) (while extents (lyskom-xemacs-or-gnu (progn (set-extent-property (cdr (car extents)) 'end-open t) (set-extent-property (cdr (car extents)) 'start-open t) (set-extent-endpoints (cdr (car extents)) (lp--entry->start-marker entry) (lp--entry->end-marker entry))) (progn (move-overlay (cdr (car extents)) (or (lp--entry->start-marker entry) 0) (or (lp--entry->end-marker entry) 0)))) (setq extents (cdr extents))))) (defun lyskom-change-membership-priority (conf-no new-priority) "Change the priority of memberhip for CONF-NO to NEW-POSITION. This function does not tell the server about the change." (let* ((mship (lyskom-get-membership conf-no t)) (old-priority (and mship (membership->priority mship)))) (when mship (set-membership->priority mship new-priority) (lyskom-replace-membership mship) (cond ((and (>= old-priority lyskom-session-priority) (>= new-priority lyskom-session-priority)) ;; Do nothing ) ((and (< old-priority lyskom-session-priority) (>= new-priority lyskom-session-priority)) (let ((mship (lyskom-get-membership conf-no t))) (when mship (lyskom-prefetch-map conf-no mship)))) ((and (>= old-priority lyskom-session-priority) (< new-priority lyskom-session-priority)) (read-list-delete-read-info conf-no lyskom-to-do-list) (when (eq conf-no lyskom-current-conf) (lyskom-leave-current-conf)) (lyskom-update-prompt t)) )))) (defun lyskom-change-membership-position (conf-no new-position) "Change the position of memberhip for CONF-NO to NEW-POSITION. This function does not tell the server about the change." (let* ((mship (lyskom-get-membership conf-no t))) (when mship (set-membership->position mship new-position) (lyskom-replace-membership mship)))) ;;; ============================================================ ;; Entry drawing (defun lp--entry-set-background (entry color) "Use extents or overlays to set the background of ENTRY to COLOR." (save-excursion (set-buffer (marker-buffer (lp--entry->start-marker entry))) (if (null color) (let* ((extent (assq 'color (lp--entry->extents entry)))) (when extent (lyskom-xemacs-or-gnu (delete-extent (cdr extent)) (delete-overlay (cdr extent))) (set-lp--entry->extents entry (delq extent (lp--entry->extents entry))))) (let* ((extent (cdr (assq 'color (lp--entry->extents entry)))) (facename (intern (format "lyskom-%s-background" (lyskom-safe-color-name color)))) (face (or (lyskom-find-face facename) (lyskom-make-face facename t)))) (unless extent (lyskom-xemacs-or-gnu (setq extent (make-extent (lp--entry->start-marker entry) (lp--entry->end-marker entry))) (setq extent (make-overlay (lp--entry->start-marker entry) (lp--entry->end-marker entry) nil t))) (set-lp--entry->extents entry (cons (cons 'color extent) (lp--entry->extents entry)))) (set-face-background face color) (lyskom-xemacs-or-gnu (progn (set-extent-property extent 'end-open t) (set-extent-property extent 'start-open t) (set-extent-property extent 'priority 1000) (set-extent-property extent 'face face)) (progn (overlay-put extent 'priority 1000) (overlay-put extent 'face face))))))) (defun lp--entry-set-foreground (entry color) "Use extents or overlays to set the foreground of ENTRY to COLOR." (save-excursion (set-buffer (marker-buffer (lp--entry->start-marker entry))) (if (null color) (let* ((extent (assq 'fcolor (lp--entry->extents entry)))) (when extent (lyskom-xemacs-or-gnu (delete-extent (cdr extent)) (delete-overlay (cdr extent))) (set-lp--entry->extents entry (delq extent (lp--entry->extents entry))))) (let* ((extent (cdr (assq 'fcolor (lp--entry->extents entry)))) (facename (intern (format "lyskom-%s-foreground" (lyskom-safe-color-name color)))) (face (or (lyskom-find-face facename) (lyskom-make-face facename t)))) (unless extent (lyskom-xemacs-or-gnu (setq extent (make-extent (lp--entry->start-marker entry) (lp--entry->end-marker entry))) (setq extent (make-overlay (lp--entry->start-marker entry) (lp--entry->end-marker entry) nil t))) (set-lp--entry->extents entry (cons (cons 'fcolor extent) (lp--entry->extents entry)))) (set-face-foreground face color) (lyskom-xemacs-or-gnu (progn (set-extent-property extent 'end-open t) (set-extent-property extent 'start-open t) (set-extent-property extent 'priority 1000) (set-extent-property extent 'face face)) (progn (overlay-put extent 'priority 1000) (overlay-put extent 'face face))))))) (defmacro lp--save-excursion (&rest body) "Evecute BODY and restore the current location of point. The location of point is in relation to the entry it is in. Point will move as the entry moves. The location of point is restored even if the character at point is deleted." `(let* ((lp--saved-entry (lp--entry-at (point))) (lp--saved-column (and lp--saved-entry (- (point) (lp--entry->start-marker lp--saved-entry))))) (save-excursion ,@body) (if (and lp--saved-entry (lp--entry->start-marker lp--saved-entry)) (goto-char (+ lp--saved-column (lp--entry->start-marker lp--saved-entry)))))) (defun lp--compute-format-string () "Compute the format string for an entry in the buffer. To save time, the format string is cached in `lp--format-string'. It is only recomputed if the window width changes." (let ((total (- (window-width) 1 3 3 2 12 2 5 2 4 1))) (setq lp--conf-name-width total) (setq lp--format-string (concat "%#1c %=3#2s %#10c %=-" (number-to-string total) "#3M %=-12#4s %[%#15@%=5#5s%] %[%#11@%#6c%]%[%#12@%#7c%]%[%#13@%#8c%]%[%#14@%#9c%]")))) (defun lp--format-insert-entry (entry) "Format ENTRY and insert it into the current buffer at point." (let* ((mship-conf-no (membership->conf-no (lp--entry->membership entry))) (adder-conf-no (membership->created-by (lp--entry->membership entry))) (mship-conf-stat (cache-get-conf-stat mship-conf-no)) (adder-conf-stat (cache-get-conf-stat adder-conf-no))) (if (null mship-conf-stat) (lyskom-format-insert-at-point "%#1D" (lyskom-create-defer-info 'get-conf-stat mship-conf-no 'lp--format-entry (point-marker) (length lyskom-defer-indicator) "%#1s" entry)) (lp--format-entry mship-conf-stat entry)) (when (eq (lp--entry->state entry) 'expanded) (lyskom-insert-at-point "\n ") (if (null adder-conf-stat) (lyskom-format-insert-at-point "%#1D" (lyskom-create-defer-info 'get-conf-stat adder-conf-no 'lp--format-entry-expansion (point-marker) (length lyskom-defer-indicator) "%#1s" entry)) (lp--format-entry-expansion adder-conf-stat entry))))) (defun lp--format-entry (conf-stat defer-info) (let ((entry nil)) (if (lyskom-lp--entry-p defer-info) (progn (setq entry defer-info) (setq defer-info nil)) (setq entry (defer-info->data defer-info))) (let* ((un (lyskom-find-unread (membership->conf-no (lp--entry->membership entry)))) (string (lyskom-format lp--format-string (if (lp--entry->selected entry) ?* ?\ ) (if (zerop (membership->priority (lp--entry->membership entry))) "-" (int-to-string (membership->priority (lp--entry->membership entry)))) (if (null conf-stat) (lyskom-format 'conference-does-not-exist (membership->conf-no (lp--entry->membership entry))) conf-stat) (lyskom-format-time 'date (membership->last-time-read (lp--entry->membership entry))) (if un (int-to-string un) "") (if (membership-type->invitation (membership->type (lp--entry->membership entry))) ?I ?.) (if (membership-type->secret (membership->type (lp--entry->membership entry))) ?H ?.) (if (membership-type->passive (membership->type (lp--entry->membership entry))) ?P ?.) (if (membership-type->message-flag (membership->type (lp--entry->membership entry))) ?M ?.) (if (and conf-stat (eq lyskom-pers-no (conf-stat->supervisor conf-stat))) ?O ?\ ) (lyskom-default-button 'prioritize-flag-menu (list entry 'invitation) (list "%#1s (%=#2M)" (lyskom-get-string 'Invitation-mt-type) (membership->conf-no (lp--entry->membership entry)))) (lyskom-default-button 'prioritize-flag-menu (list entry 'secret) (list "%#1s (%=#2M)" (lyskom-get-string 'Secret-mt-type) (membership->conf-no (lp--entry->membership entry)))) (lyskom-default-button 'prioritize-flag-menu (list entry 'passive) (list "%#1s (%=#2M)" (lyskom-get-string 'Passive-mt-type) (membership->conf-no (lp--entry->membership entry)))) (lyskom-default-button 'prioritize-flag-menu (list entry 'message-flag) (list "%#1s (%=#2M)" (lyskom-get-string 'Message-flag-mt-type) (membership->conf-no (lp--entry->membership entry)))) '(lp--unread t) ))) (if defer-info (lyskom-replace-deferred defer-info string) (lyskom-insert-at-point string)) (if (membership-type->passive (membership->type (lp--entry->membership entry))) (lp--entry-set-foreground entry (lyskom-face-foreground kom-dim-face)) (lp--entry-set-foreground entry nil)) (cond ((lp--entry->selected entry) (lp--entry-set-background entry (lyskom-face-background kom-mark-face))) (t (lp--entry-set-background entry nil))) (cond ((eq (membership->conf-no (lp--entry->membership entry)) (lyskom-default-value 'lyskom-current-conf)) (lp--entry-set-foreground entry (lyskom-face-foreground kom-url-face))) (t (lp--entry-set-foreground entry nil))) ))) (defun lp--format-entry-expansion (conf-stat defer-info) (let ((entry nil)) (if (lyskom-lp--entry-p defer-info) (progn (setq entry defer-info) (setq defer-info nil)) (setq entry (defer-info->data defer-info))) (let* ((membership (lp--entry->membership entry)) (string (if (and (null conf-stat) (eq 0 (time->sec (membership->created-at membership))) (eq 0 (time->min (membership->created-at membership))) (eq 1 (time->mon (membership->created-at membership))) (eq 1 (time->mday (membership->created-at membership))) (eq 1970 (time->year (membership->created-at membership)))) (lyskom-get-string 'lp-no-creation-info) (lyskom-format "%#1s %#2s av %#3P" (lyskom-get-string (if (membership-type->invitation (membership->type (lp--entry->membership entry))) 'lp-invited 'lp-added)) (lyskom-format-time 'date-and-time (membership->created-at (lp--entry->membership entry))) (if (null conf-stat) (lyskom-format 'person-does-not-exist (membership->created-by (lp--entry->membership entry))) conf-stat))))) (if defer-info (lyskom-replace-deferred defer-info string) (lyskom-insert-at-point string))))) (defun lp--print-entry (entry) "Print the entry ENTRY at the current position in the buffer. The start and end markers of the entry are adjusted" (if (lp--entry-set-visible entry (lp--entry-compute-visible entry)) (let ((buffer-read-only nil)) (insert-before-markers "\n") (if (lp--entry->end-marker entry) (set-marker (lp--entry->end-marker entry) nil)) (set-lp--entry->end-marker entry (point-marker)) (forward-char -1) (if (lp--entry->start-marker entry) (set-marker (lp--entry->start-marker entry) nil)) (set-lp--entry->start-marker entry (point-marker)) (lp--format-insert-entry entry) ; End marker should be before \n. (set-marker (lp--entry->end-marker entry) (1- (lp--entry->end-marker entry))) (lp--entry-update-extents entry) (forward-char 1)) (lp--erase-entry entry))) (defun lp--erase-entry (entry) "Erase the printed representation of the entry ENTRY in the buffer." (let ((buffer-read-only nil)) (when (and (lp--entry->start-marker entry) (lp--entry->end-marker entry)) (delete-region (lp--entry->start-marker entry) (1+ (lp--entry->end-marker entry)))) (if (lp--entry->start-marker entry) (set-marker (lp--entry->start-marker entry) nil)) (set-lp--entry->start-marker entry nil) (if (lp--entry->end-marker entry) (set-marker (lp--entry->end-marker entry) nil)) (set-lp--entry->end-marker entry nil) (lp--entry-update-extents entry))) (defun lp--redraw-entry-mark (entry) "Redraw the mark for ENTRY." (let ((buffer-read-only nil)) (lp--save-excursion (goto-char (lp--entry->start-marker entry)) (insert (if (lp--entry->selected entry) ?* ?\ )) (if (lp--entry->selected entry) (lp--entry-set-background entry (lyskom-face-background kom-mark-face)) (lp--entry-set-background entry nil)) (delete-char 1) (lp--entry-update-extents entry)))) (defun lp--redraw-entry (entry) "Redraw the entry ENTRY." (lp--save-excursion (if (null (lp--entry->start-marker entry)) (goto-char (let ((ne (lp--get-entry (lp--next-visible-entry (membership->position (lp--entry->membership entry)))))) (if ne (lp--entry->start-marker ne) lp--list-end-marker))) (goto-char (lp--entry->start-marker entry)) (lp--erase-entry entry)) (lp--print-entry entry))) (defun lp--perform-in-all-buffers (fn &rest args) "Perform FN in all prioritization buffers. ARGS are arguments for FN. Normally there should only be one buffer, but who knows..." (when lyskom-buffer (save-excursion (set-buffer lyskom-buffer) (let ((prioritize-buffers (lyskom-buffers-of-category 'prioritize))) (lyskom-traverse buffer prioritize-buffers (when (buffer-live-p buffer) (set-buffer buffer) (apply fn args))))))) (defun lp--maybe-update-entry-for-conf (conf-no) (lp--perform-in-all-buffers (lambda (conf-no) (let ((entry (lp--conf-no-entry conf-no))) (when entry (lp--redraw-entry entry)))) conf-no)) (defun lp--maybe-update-unreads (conf-no) (lp--perform-in-all-buffers (lambda (conf-no unread) (let ((entry (lp--conf-no-entry conf-no))) (when entry (let ((vis (lp--entry-compute-visible entry))) (cond ((not (eq vis (lp--entry->visible entry))) (lp--redraw-entry entry)) ((lp--entry->visible entry) (let ((bounds (lyskom-next-property-bounds (lp--entry->start-marker entry) (lp--entry->end-marker entry) 'lp--unread))) (when bounds (lp--save-excursion (let ((buffer-read-only nil)) (delete-region (car bounds) (cdr bounds)) (goto-char (car bounds)) (insert (lyskom-format "%#2@%=5#1s" (if (and unread (> unread 0)) (int-to-string unread) "") '(lp--unread t))))))))))))) conf-no (lyskom-find-unread conf-no))) ;;; ============================================================ ;; List management (defun lp--set-entry-list (entries) "Set the list of entries to ENTRIES." (setq lp--entry-list entries)) (defun lp--all-entries () "Return a list of all entries." lp--entry-list) (defun lp--conf-no-entry (conf-no) "Find the entry for a membership in CONF-NO." (let ((entries (lp--all-entries)) (found nil)) (while (and entries (null found)) (when (eq conf-no (membership->conf-no (lp--entry->membership (car entries)))) (setq found (car entries))) (setq entries (cdr entries))) found)) (defun lp--find-new-position (entry priority &optional pos) "Find the new position for ENTRY it is were given priority PRIORITY. If priority is lower than the entry priority this is the last position currently occupied by an entry with a higher priority. If priority is higher, then it is the first position with a priority less than the entry priority" (let ((entries (lp--all-entries)) (result nil) (tmp nil)) (cond ;; Moving down. Return the last entry spotted with a higher ;; than requested priority ((if priority (> (lp--entry->priority entry) priority) (< (lp--entry-position entry) pos)) (while (and entries (null result)) (when (if priority (<= (lp--entry->priority (car entries)) priority) (>= (lp--entry-position (car entries)) pos)) (setq result tmp)) (setq tmp (car entries)) (setq entries (cdr entries))) (unless result (setq result tmp))) ;; Moving up. Return the first entry with a priority strictly ;; less than the requested one ((if priority (< (lp--entry->priority entry) priority) (> (lp--entry-position entry) pos)) (while (and entries (null result)) (when (if priority (< (lp--entry->priority (car entries)) priority) (>= (lp--entry-position (car entries)) pos)) (setq result (car entries))) (setq entries (cdr entries)))) (t (setq result entry))) result)) (defun lp--get-last-visible-entry () "Return the last visible entry in the list." (let* ((pos (1- (length (lp--all-entries)))) (entry (lp--get-entry pos))) (while (and (> pos 0) entry (not (lp--entry->visible entry))) (setq pos (1- pos)) (setq entry (lp--get-entry pos))) (if (and entry (lp--entry->visible entry)) entry nil))) (defun lp--get-entry (pos) "Return the entry at position POS in the list." (elt lp--entry-list pos)) (defun lp--entry-position (entry) "Return the position in the list for ENTRY." (- (length (lp--all-entries)) (length (memq entry (lp--all-entries))))) ;;(defun lp--entry-at (where) ;; "Return the entry at WHERE." ;; (let* ((pos (save-excursion (goto-char where) ;; (beginning-of-line) ;; (point))) ;; (idx (lyskom-binsearch ;; pos (lp--all-entries) nil nil ;; (lambda (a b) ;; (cond ((numberp a) ;; (and (lp--entry->start-marker b) ;; (lp--entry->end-marker b) ;; (< a (lp--entry->start-marker b)))) ;; (t ;; (and (lp--entry->start-marker a) ;; (lp--entry->end-marker a) ;; (< (lp--entry->end-marker a) b)))))))) ;; (and idx (lp--get-entry idx)))) (defun lp--entry-at (where) "Return the entry at WHERE." (let ((pos (save-excursion (goto-char where) (beginning-of-line) (point)))) (lyskom-traverse entry (lp--all-entries) (when (and (lp--entry->visible entry) (>= pos (lp--entry->start-marker entry)) (<= pos (lp--entry->end-marker entry))) (lyskom-traverse-break entry))))) (defun lp--move-entry (entry to) "Move the entry ENTRY to position TO in the list." (when (or (< to 0) (> to (length (lp--all-entries)))) (error "Position out of range: %d" to)) (lp--erase-entry entry) (lp--set-entry-list (lp--remove-from-list entry (lp--all-entries))) (let ((cur (lp--get-entry (lp--next-visible-entry to)))) (if cur (goto-char (lp--entry->start-marker cur)) (goto-char lp--list-end-marker)) (lp--set-entry-list (lp--add-to-list to entry (lp--all-entries))) (lp--print-entry entry))) (defun lp--remove-from-list (elem l) "Destructively remove ELEM from the list L." (let* ((n (- (length l) (length (memq elem l))))) (cond ((= 0 n) (cdr l)) ((= n (length l)) l) (t (setcdr (nthcdr (1- n) l) (nthcdr (1+ n) l)) l)))) (defun lp--add-to-list (elem data l) "At the position ELEM, add DATA to the list L using side effects." (if (> elem (length l)) (error "Args out of range: %S, %d" l elem)) (if (= 0 elem) (cons data l) (setcdr (nthcdr (1- elem) l) (cons data (nthcdr elem l))) l)) (defun lp--list-move-element (el to list) "Move element EL by side effects so it appears at position TO in LIST." (lp--add-to-list to el (lp--remove-from-list el list))) (defun lp--update-buffer (conf-no) "Update the entry for CONF-NO in the buffer. If optional NEW-MSHIP is non-nil, then get the membership again." (unless lp--inhibit-update (lp--perform-in-all-buffers (lambda () (lp--save-excursion (let ((entry (lp--conf-no-entry conf-no)) (mship (lyskom-get-membership conf-no t))) (cond ((and (null entry) mship) ; New membership (let* ((pos (membership->position mship)) (elem (and pos (lp--get-entry (lp--next-visible-entry pos)))) (entry (lyskom-create-lp--entry nil nil (membership->priority mship) mship nil (if (memq (membership->created-by mship) (list lyskom-pers-no 0)) 'contracted 'expanded) t nil))) (when pos (save-excursion (goto-char (if elem (lp--entry->start-marker elem) lp--list-end-marker)) (lp--set-entry-list (lp--add-to-list pos entry (lp--all-entries))) (lp--print-entry entry))))) ;; We have unsubscribed for good ((null mship) (when entry (lp--set-entry-list (lp--remove-from-list entry (lp--all-entries))) (lp--erase-entry entry))) ;; The priority or position of a membership has changed ((or (/= (lp--entry->priority entry) (membership->priority mship)) (/= (lp--entry-position entry) (membership->position mship))) (let ((new-pos (or (membership->position mship) (lp--entry-position (lp--find-new-position entry (membership->priority mship)))))) (lp--set-entry-pri-and-pos entry (membership->priority mship) new-pos) (set-lp--entry->membership entry mship))) (t (set-lp--entry->membership entry mship) (lp--redraw-entry entry))))))))) (defun lp--map-region (start end function &rest args) "For each element from START to END, apply FUNCTION. Apply FUNCTION to each element in the region from START to END, returning a list of results. ARGS will be passed as additional arguments to FUNCTION. Args: START END FUNCTION ARGS." (let ((results nil) (entry nil)) (save-excursion (goto-char (lp--entry->start-marker (lp--entry-at start))) (setq start (set-marker (make-marker) (point))) (goto-char (lp--entry->end-marker (lp--entry-at end))) (setq end (set-marker (make-marker) (point))) (goto-char start) (while (<= (point) end) (setq entry (lp--entry-at (point))) (setq results (cons (apply function entry args) results)) (goto-char (lp--entry->end-marker entry)) (forward-char 2))) results)) ;;; ============================================================ ;; Menu and button functions ;;; ------------------------------------------------------------ ;; Flag menu ;; Argument is a list of entry and flag (defun lp--flag-menu-get (entry flag) "For the membership in ENTRY, return the value of flag FLAG. FLAG must be one of 'invitation, 'secret or 'passive." (funcall (cond ((eq flag 'invitation) 'membership-type->invitation) ((eq flag 'secret) 'membership-type->secret) ((eq flag 'passive) 'membership-type->passive) ((eq flag 'message-flag) 'membership-type->message-flag)) (membership->type (lp--entry->membership entry)))) (defun lp--flag-menu-set (entry flag value) "For the membership in ENTRY, set FLAG to VALUE. FLAG must be one of 'invitation, 'secret or 'passive." (funcall (cond ((eq flag 'invitation) 'set-membership-type->invitation) ((eq flag 'secret) 'set-membership-type->secret) ((eq flag 'passive) 'set-membership-type->passive) ((eq flag 'message-flag) 'set-membership-type->message-flag)) (membership->type (lp--entry->membership entry)) value)) (defun lyskom-prioritize-flag-clear (buf arg text) "Clear the membership flag the user clicked on. This function should not be called directly. It is called in response to a mouse click. BUF is the buffer in which the mouse click took place. ARG is a list of (ENTRY FLAG), where ENTRY is the entry the flag belongs to and FLAG is one of invitation, secret or passive. TEXT is the text that the user clicked on." (interactive) (let ((entry (elt arg 0)) (flag (elt arg 1))) (when (lp--flag-menu-get entry flag) (lyskom-prioritize-flag-toggle buf arg text)))) (defun lyskom-prioritize-flag-set (buf arg text) "Set the membership flag the user clicked on. This function should not be called directly. It is called in response to a mouse click. BUF is the buffer in which the mouse click took place. ARG is a list of (ENTRY FLAG), where ENTRY is the entry the flag belongs to and FLAG is one of invitation, secret or passive. TEXT is the text that the user clicked on." (interactive) (let ((entry (elt arg 0)) (flag (elt arg 1))) (unless (lp--flag-menu-get entry flag) (lyskom-prioritize-flag-toggle buf arg text)))) (defun lyskom-prioritize-flag-toggle (buf arg text) "Toggle the membership flag the user clicked on. This function should not be called directly. It is called in response to a mouse click. BUF is the buffer in which the mouse click took place. ARG is a list of (ENTRY FLAG), where ENTRY is the entry the flag belongs to and FLAG is one of invitation, secret or passive. TEXT is the text that the user clicked on." (interactive) (let ((entry (elt arg 0)) (flag (elt arg 1))) (save-excursion (set-buffer (marker-buffer (lp--entry->start-marker entry))) (lp--flag-menu-set entry flag (not (lp--flag-menu-get entry flag))) ;; Attempt to perform the change (save-excursion (set-buffer lyskom-buffer) (let ((result (blocking-do 'set-membership-type lyskom-pers-no (membership->conf-no (lp--entry->membership entry)) (membership->type (lp--entry->membership entry))))) (unless result (lyskom-message (lyskom-format 'lp-nope (lyskom-get-error-text lyskom-errno))))) ;; Update the display (let ((mship (blocking-do 'query-read-texts lyskom-pers-no (membership->conf-no (lp--entry->membership entry)) t 0))) (lyskom-replace-membership mship) (set-lp--entry->membership entry mship) (when (eq flag 'passive) (cond ((membership-type->passive (membership->type mship)) (save-excursion (set-buffer lyskom-buffer) (when (eq (membership->conf-no mship) lyskom-current-conf) (lyskom-leave-current-conf)) (read-list-delete-read-info (membership->conf-no mship) lyskom-to-do-list) (lyskom-update-prompt t))) (t (lyskom-prefetch-map (membership->conf-no mship) mship)))) (blocking-do 'get-conf-stat (membership->conf-no mship)))) (lp--redraw-entry entry)))) (defun lp--selected-or-current-arg () "Return a list of selected entries or the current entry. This function is suitable to call from interactive." (if (and lp--selected-entry-list (not (zerop (length lp--selected-entry-list)))) lp--selected-entry-list (list (lp--entry-at (point))))) (defun lp--postpone (arg entries) "Postpone reading of all but the last ENTRIES text in selected/ current conferences." (interactive (list current-prefix-arg (lp--selected-or-current-arg))) (lyskom-with-lyskom-buffer (let ((n (or (and arg (prefix-numeric-value arg)) (lyskom-read-number (lyskom-get-string 'postpone-prompt) kom-postpone-default))) (l (mapcar (lambda (i) (if (eq 'CONF (read-info->type i)) (list (read-info->conf-stat i) (read-info->text-list i)) '(nil nil))) (read-list->all-entries lyskom-to-do-list)))) (lyskom-traverse cur entries (unless cur (error (lyskom-get-string 'lp-no-entry))) (let* ((conf-no (membership->conf-no (lp--entry->membership cur))) (conf-stat (blocking-do 'get-conf-stat conf-no))) (if (null conf-stat) (lyskom-message (lyskom-format (lyskom-get-string 'lp-skipping-missing-meeting) conf-no)) (let ((rl (assoc conf-stat l))) (when (and (nth 1 rl) ; Handle passive conferences (< n (text-list->length (nth 1 rl)))) (text-list->trim-head (nth 1 rl) n) (lp--update-buffer conf-no) (when (= lyskom-current-conf conf-no) (lyskom-go-to-conf conf-no t)))))))) (read-list-delete-text nil lyskom-reading-list) (read-list-delete-text nil lyskom-to-do-list))) (defun lp--set-unread (arg entries) "Set number of unread messages in selected/current conference(s)." ; Should probably unify with (interactive (list current-prefix-arg (lp--selected-or-current-arg))) (let ((num-unread (or (and arg (prefix-numeric-value arg)) (lyskom-read-num-range-or-date 0 ; Does this really promote the user experience? Would it ; be better to fix lyskom-read-num-range-or-date to ; be able to get a number or a date (ignoring ther range)? (let ((max-unread 0)) (lyskom-traverse cur entries (when cur (setq max-unread (max max-unread (conf-stat->no-of-texts (blocking-do 'get-conf-stat (membership->conf-no (lp--entry->membership cur)))))))) max-unread) (lyskom-format 'lp--only-last))))) (lyskom-with-lyskom-buffer (lyskom-traverse cur entries (unless cur (error (lyskom-get-string 'lp-no-entry))) (let* ((conf-no (membership->conf-no (lp--entry->membership cur))) (conf-stat (progn (cache-del-conf-stat conf-no) (blocking-do 'get-conf-stat conf-no)))) (if (null conf-stat) (lyskom-message (lyskom-format (lyskom-get-string 'lp-skipping-missing-meeting) conf-no)) (let ((num-unread-this-conf (if (listp num-unread) num-unread (min num-unread (conf-stat->no-of-texts conf-stat))))) (cond ((listp num-unread-this-conf) (lyskom-format-insert 'set-unread-date (elt num-unread-this-conf 0) (car (rassq (elt num-unread-this-conf 1) lyskom-month-names)) (elt num-unread-this-conf 2)) (let* ((target-date (lyskom-create-time 0 0 0 (elt num-unread-this-conf 2) (elt num-unread-this-conf 1) (elt num-unread-this-conf 0) 0 0 nil)) (text (lyskom-find-text-by-date conf-stat target-date))) (when text (blocking-do 'set-last-read (conf-stat->conf-no conf-stat) (car text))))) ((numberp num-unread-this-conf) (blocking-do 'set-unread conf-no num-unread-this-conf))) ; FIXME: Does not handle the current conf right, ; prefetch problem? (lyskom-replace-membership (lp--entry->membership cur)) (when (= conf-no lyskom-current-conf) (read-list-delete-read-info conf-no lyskom-reading-list)) (read-list-delete-read-info conf-no lyskom-to-do-list) (lyskom-prefetch-one-membership conf-no lyskom-pers-no) (when (and (= conf-no lyskom-current-conf) (not (zerop num-unread-this-conf))) (lyskom-go-to-conf conf-no t)))))) (read-list-delete-text nil lyskom-reading-list) (read-list-delete-text nil lyskom-to-do-list)))) (defun lp--toggle-flag (flag entries) "Toggle the given FLAG for given ENTRIES." (lp--save-excursion (lyskom-traverse cur entries (cond ((null cur) (error (lyskom-get-string 'lp-no-entry))) (t (lyskom-prioritize-flag-toggle (current-buffer) (list cur flag) "")))))) (defun lp--toggle-invitation (entries) "Toggle the invitation bit of the current entry" (interactive (list (lp--selected-or-current-arg))) (lp--toggle-flag 'invitation entries)) (defun lp--toggle-passive (entries) "Toggle the passive bit of the current entry" (interactive (list (lp--selected-or-current-arg))) (lp--toggle-flag 'passive entries)) (defun lp--toggle-message-flag (entries) "Toggle the message flag bit of current or selected entries" (interactive (list (lp--selected-or-current-arg))) (lp--toggle-flag 'message-flag entries)) (defun lp--toggle-secret (entries) "Toggle the secret bit of the current entry" (interactive (list (lp--selected-or-current-arg))) (lp--toggle-flag 'secret entries)) ;;; ============================================================ ;; Marking and unmarking memberships ;; (defun lp--select-entries (entry-list state) "Set the selection value of all entries in ENTRY-LIST to STATE. Forces a mode line update" (lp--do-select-entries entry-list state) (lp--update-mode-line)) (defun lp--do-select-entries (entry-list state) "Set the selection value of all entries in ENTRY-LIST to STATE." (mapcar (lambda (entry) (when entry (if (and state (lp--entry->visible entry)) (add-to-list 'lp--selected-entry-list entry) (setq lp--selected-entry-list (delq entry lp--selected-entry-list))) (set-lp--entry->selected entry state) (lp--redraw-entry-mark entry))) entry-list)) (defun lp--all-selected-entries () "Return a list of all selected entries." lp--selected-entry-list) (defun lp--set-selected-entries (entry-list) "Set the selected entries to exactly the entries in ENTRY-LIST. Forces a mode line update" (lp--do-select-entries (lp--all-selected-entries) nil) (lp--do-select-entries entry-list t) (lp--update-mode-line)) ;;; ============================================================ ;;; Hiding and unhiding entries ;;; FIXME: This doesn't work yet (defun lp--entry-compute-visible (entry) "Compute the visibility of ENTRY." (not (lyskom-traverse filter lp--entry-filter (unless (apply (car filter) entry (cdr filter)) (lyskom-traverse-break t))))) (defun lp--entry-set-visible (entry state) "Set the visibility of ENTRY to STATE" (let ((old-state (lp--entry->visible entry))) (unless (eq state old-state) (set-lp--entry->visible entry state) (if state (setq lp--hidden-entries (delq entry lp--hidden-entries)) (setq lp--hidden-entries (cons entry lp--hidden-entries))) (lp--update-mode-line))) state) (defun lp--show-all () (interactive) (setq lp--entry-filter nil) (lyskom-traverse entry lp--hidden-entries (lp--redraw-entry entry)) (setq lp--hidden-entries nil)) ;;; ------------------------------------------------------------ ;; Server update functions (defun lp--update-membership (entry old-pri old-pos) "Update the server and local versions of membership in ENTRY." (save-excursion (let ((saved-pos (lp--entry-position entry))) (set-buffer lyskom-buffer) (let ((mship (lp--entry->membership entry))) (unless (eq old-pos saved-pos) (lyskom-change-membership-position (membership->conf-no mship) saved-pos)) (unless (eq old-pri (lp--entry->priority entry)) (lyskom-change-membership-priority (membership->conf-no mship) (lp--entry->priority entry))) (cond ((and (>= old-pri lyskom-session-priority) (< (membership->priority mship) lyskom-session-priority)) (when (eq lyskom-current-conf (membership->conf-no mship)) (lyskom-leave-current-conf)) (read-list-delete-read-info (membership->conf-no mship) lyskom-to-do-list) (lyskom-update-prompt t)) ((and (< old-pri lyskom-session-priority) (>= (membership->priority mship) lyskom-session-priority)) (lyskom-prefetch-map (membership->conf-no mship) mship))) (initiate-add-member 'background nil (membership->conf-no mship) lyskom-pers-no (membership->priority mship) (membership->position mship) (membership->type mship)))))) ;;; ============================================================ ;;; Support (defun lp--next-visible-entry (pos) "Return the position of the first visible entry following POS." (let ((max (length (lp--all-entries))) (result nil)) (while (and (< pos max) (null result)) (if (lp--entry->visible (lp--get-entry pos)) (setq result pos pos max) (setq pos (1+ pos)))) (or result max))) (defun lp--calculate-distance (pos delta) "Return one more than the number of entries between POS and POS+DELTA. This includes visible and invisible entries. The sign of the returned value has the same sign as DELTA. The result is clipped to the size of the list." (let ((step (lyskom-signum delta)) (num (abs delta)) (result 0)) (while (> num 0) (setq pos (+ step pos)) (if (< pos 0) (setq num 0) (setq result (1+ result)) (let ((entry (lp--get-entry pos))) (cond ((null entry) (setq result (1+ result) num 0)) ((lp--entry->visible (lp--get-entry pos)) (setq num (1- num))))))) (* result step))) ;;; ---------------------------------------------------------------- ;;; Filtration (defun lp--entry-filter-active (filter) "Return non-nil if FILTER is an active entry filter." (assq filter lp--entry-filter)) (defun lp--add-entry-filter (filter &rest filter-args) "Add entry filter FILTER. FILTER is a function that should take one argument, an lp--entry, and return non-nil if the entry should be visible. If optional arguments FILTER-ARGS are supplied, these are also passed to the filter function." (unless (symbolp filter) (error "entry filter must be a symbol")) (unless (assq filter lp--entry-filter) (setq lp--entry-filter (cons (cons filter filter-args) lp--entry-filter)) (lp--apply-entry-filter))) (defun lp--replace-entry-filter (filter &rest filter-args) "Replace existing entry filter FILTER. See `lp--add-entry-filter' for more information." (unless (symbolp filter) (error "entry filter must be a symbol")) (if (assq filter lp--entry-filter) (setcdr (assq filter lp--entry-filter) filter-args) (setq lp--entry-filter (cons (cons filter filter-args) lp--entry-filter))) (lp--apply-entry-filter)) (defun lp--del-entry-filter (filter) "Remove the entry filter FILTER." (let ((el (assq filter lp--entry-filter))) (when el (setq lp--entry-filter (delq el lp--entry-filter)) (lp--apply-entry-filter)))) (defun lp--apply-entry-filter () "Apply the current filter list to all entries." (lp--save-excursion (lp--update-filter-description) (lyskom-traverse entry (lp--all-entries) (let ((vis (lp--entry-compute-visible entry))) (unless (eq vis (lp--entry->visible entry)) (lp--redraw-entry entry)))))) (defun lp--entry-filter-description () "Return a string representing the current entry filters." (let (res) (lyskom-traverse filter lp--entry-filter (let ((name (car filter))) (when name (setq res (cons name res))))) (or (and res (mapconcat 'symbol-name (nreverse res) ", ")) (lyskom-get-string 'lp-no-active-filter)))) (defun lp--update-filter-description () "Update the filter description shown in the buffer." (lp--set-header 'filter (lyskom-format 'lp-active-filters (lp--entry-filter-description)))) ;; Filter functions should return the desired visibility state (defun lp--entry-filter-read (entry) "Entry filter that displays only conferences with unread texts." (let ((n (lyskom-find-unread (membership->conf-no (lp--entry->membership entry))))) (or (eq (membership->conf-no (lp--entry->membership entry)) (lyskom-default-value 'lyskom-current-conf)) (and n (> n 0))))) (defun lp--entry-filter-passive (entry) "Entry filter that displays only active memberships." (not (membership-type->passive (membership->type (lp--entry->membership entry))))) (defun lp--entry-filter-after (entry time) "Hide entries read after a certain time" (not (lyskom-time-greater (membership->last-time-read (lp--entry->membership entry)) time))) (defun lp--entry-filter-before (entry time) "Hide entries read before a certain time" (lyskom-time-greater (membership->last-time-read (lp--entry->membership entry)) time)) ;;; ================================================================ ;;; User-level functions (defun lp--select-membership () "Select the membership that point is on." (interactive) (let ((entry (lp--entry-at (point)))) (when entry (lp--select-entries (list entry) t)))) (defun lp--deselect-membership () "Deselect the membership that point is on." (interactive) (let ((entry (lp--entry-at (point)))) (when entry (lp--select-entries (list entry) nil)))) (defun lp--toggle-membership-selection (where) "Toggle selection of the membership at WHERE." (interactive "d") (let ((entry (lp--entry-at where))) (when entry (lp--select-entries (list entry) (not (lp--entry->selected entry)))))) (defun lp--select-region (start end) "Select all entries in the region. With prefix arg, deselect. START and END are the starting and ending points of the region." (interactive "r") (let ((entry-list (lp--map-region start end 'identity))) (lp--select-entries entry-list (not current-prefix-arg)))) (defun lp--select-priority (priority) "Select all entries with a priority PRIORITY. With numeric prefix argument select entries with that priority." (interactive "P") (lp--do-select-priority priority t)) (defun lp--deselect-priority (priority) "Deselect all entries with a priority PRIORITY. With numeric prefix argument deselect entries with that priority." (interactive "P") (lp--do-select-priority priority nil)) (defun lp--do-select-priority (priority select) "Select or deselect all entries with priority PRIORITY. SELECT specifies new select." (when (not (numberp priority)) (let ((entry (lp--entry-at (point)))) (setq priority (lyskom-read-num-range 0 255 (lyskom-get-string (if select 'lp-mark-mship-with-prio 'lp-unmark-mship-with-prio)) nil (and entry (membership->priority (lp--entry->membership entry))))))) (lp--select-entries (mapcar (lambda (entry) (and (eq priority (membership->priority (lp--entry->membership entry))) entry)) (lp--all-entries)) select)) (defun lp--deselect-all () "Deselect all memberships." (interactive) (lp--set-selected-entries nil)) ;;; ============================================================ ;;; Reprioritization functions (defun lp--set-entry-pri-and-pos (entry priority position) "Set the priority of ENTRY to PRIORITY and the position to POSITION. If PRIORITY or POSITION is nil, the parameter is ignored. If the position changes, lp--move-entry is called. lp--update-membership is called automatically before this function exits." (let ((old-pri (lp--entry->priority entry)) (old-pos (lp--entry-position entry)) (lp--inhibit-update t) (need-redraw nil)) (when (and priority (not (eq priority old-pri))) (set-lp--entry->priority entry priority) (set-membership->priority (lp--entry->membership entry) priority) (setq need-redraw t)) (when (and position (not (eq position old-pos))) (lp--move-entry entry position) (set-membership->position (lp--entry->membership entry) position) (setq need-redraw nil)) (lyskom-replace-membership (lp--entry->membership entry)) (sit-for 0) (lp--update-membership entry old-pri old-pos) (when need-redraw (lp--redraw-entry entry)))) (defun lp--yank () "Insert all the selected memberships before the entry at point." (interactive) (lp--save-excursion (let* ((cur (lp--entry-at (point))) (pos (and cur (lp--entry-position cur))) (priority (and cur (lp--entry->priority cur))) (entries (lp--all-selected-entries))) (cond ((null cur) (error (lyskom-get-string 'lp-no-entry))) ((null entries) (error (lyskom-get-string 'lp-no-selection))) (t (mapcar (lambda (entry) (lp--set-entry-pri-and-pos entry priority (lp--entry-position (lp--find-new-position entry nil pos)))) entries)))))) (defun lp--set-priority (priority) "Set the priority of selected memberships to PRIORITY. Memberships that must be moved will be moved the shortest distance possible in the list." (interactive "P") (let* ((entries (or (lp--all-selected-entries) (list (lp--entry-at (point)))))) (unless entries (error (lyskom-get-string 'lp-no-selection))) (unless (numberp priority) (cond ((> (length entries) 1) (setq priority (lyskom-read-num-range 0 255 (lyskom-get-string 'priority-prompt-marked) t))) (t (setq priority (lyskom-read-num-range 0 255 (lyskom-format 'priority-prompt (membership->conf-no (lp--entry->membership (car entries)))) t))))) (lp--save-excursion (mapcar (lambda (entry) (let ((new-pos (lp--entry-position (lp--find-new-position entry priority)))) (lp--set-entry-pri-and-pos entry priority new-pos))) entries)))) (defun lp--bump-priority (amount) "Increase the priority of the current entry by one" (lp--save-excursion (let* ((cur (lp--entry-at (point))) (pri (and cur (lp--entry->priority cur))) (pos (lp--entry-position cur)) (new-pri (+ pri amount))) (when (> new-pri 255) (setq new-pri 255)) (when (< new-pri 0) (setq new-pri 0)) (when (and cur (eq pri new-pri) (eq pri 0) (eq pos (1- (length (lp--all-entries))))) (error (lyskom-get-string 'lp-at-min-prio))) (when (and cur (eq pri new-pri) (eq pri 255) (eq pos 0)) (error (lyskom-get-string 'lp-at-max-prio))) (cond ((null cur) (error (lyskom-get-string 'lp-no-entry))) (t (let ((new-pos (lp--entry-position (lp--find-new-position cur (+ pri amount))))) (lp--set-entry-pri-and-pos cur new-pri new-pos))))))) (defun lp--increase-priority (arg) (interactive "p") (lp--bump-priority arg)) (defun lp--decrease-priority (arg) (interactive "p") (lp--bump-priority (- arg))) (defun lp--move-up () "Move the current entry up one notch." (interactive) (lp--save-excursion (let* ((cur (lp--entry-at (point))) (pos (and cur (lp--entry-position cur))) (place (and cur (> pos 0) (+ pos (lp--calculate-distance pos -1)))) (prev (and place (lp--get-entry place)))) (cond ((null cur) (error (lyskom-get-string 'lp-no-entry))) ((null prev) (error (lyskom-get-string 'lp-beginning-of-list))) (t (if (/= (lp--entry->priority cur) (lp--entry->priority prev)) (progn (lp--set-entry-pri-and-pos cur (lp--entry->priority prev) (if (= pos (1+ place)) nil (1+ place))) (lp--redraw-entry cur)) (lp--set-entry-pri-and-pos cur nil place))))))) (defun lp--move-down () "Move the current entry up down notch." (interactive) (lp--save-excursion (let* ((cur (lp--entry-at (point))) (pos (and cur (lp--entry-position cur))) (place (and cur (+ pos (lp--calculate-distance pos 1)))) (prev (and place (lp--get-entry place)))) (cond ((null cur) (error (lyskom-get-string 'lp-no-entry))) ((null prev) (error (lyskom-get-string 'lp-end-of-list))) (t (if (/= (lp--entry->priority cur) (lp--entry->priority prev)) (progn (lp--set-entry-pri-and-pos cur (lp--entry->priority prev) (if (= pos (1- place)) nil (1- place))) (lp--redraw-entry cur)) (lp--set-entry-pri-and-pos cur nil place))))))) ;;; ============================================================ ;;; Motion commands (defmacro lp--save-column (&rest body) `(let ((lp--saved-column (current-column))) ,@body (end-of-line) (if (> (current-column) lp--saved-column) (progn (beginning-of-line) (forward-char lp--saved-column))))) ;;; FIXME: Deal with invisible entries (defun lp--previous-entry (count) "Move the cursor up COUNT lines. The cursor will always move to the start of the target entry." (interactive "p") (let* ((entry (lp--entry-at (point))) (last-entry (lp--get-last-visible-entry)) (first-entry (lp--next-visible-entry 0)) (pos (lp--entry-position entry)) (new-pos (cond ((null last-entry) nil) ((and (null entry) (< (point) (lp--entry->start-marker (lp--get-entry first-entry)))) (lp--get-entry first-entry)) ((and (null entry) (> (point) (lp--entry->end-marker last-entry))) last-entry) (t (lp--get-entry (max 0 (+ pos (lp--calculate-distance pos (- count))))))))) (condition-case nil (goto-char (lp--entry->start-marker new-pos)) (error nil)))) (defun lp--next-entry (count) "Move the cursor down COUNT lines. The cursor will always move to the start of the target entry." (interactive "p") (let* ((entry (lp--entry-at (point))) (last-entry (lp--get-last-visible-entry)) (first-entry (lp--next-visible-entry 0)) (pos (lp--entry-position entry)) (new-pos (cond ((null last-entry) nil) ((and (null entry) (< (point) (lp--entry->start-marker (lp--get-entry first-entry)))) (lp--get-entry first-entry)) ((and (null entry) (> (point) (lp--entry->end-marker last-entry))) last-entry) (t (lp--get-entry (min (1- (length (lp--all-entries))) (+ pos (lp--calculate-distance pos count)))))))) (condition-case nil (goto-char (lp--entry->start-marker new-pos)) (error nil)))) (defun lp--first-entry () "Move point to the first entry in the membership list." (interactive) (condition-case nil (let ((entry (lp--get-entry (lp--next-visible-entry 0)))) (cond ((null entry) (goto-char lp--list-end-marker)) (t (goto-char (lp--entry->start-marker (lp--get-entry (lp--next-visible-entry 0))))))) (error nil))) (defun lp--last-entry () "Move point to the last entry in the membership list." (interactive) (condition-case nil (let ((entry (lp--get-last-visible-entry))) (cond ((null entry) (goto-char lp--list-end-marker)) (t (goto-char (lp--entry->start-marker entry))))) (error nil))) (defun lp--goto-priority (priority) "Move to the closest entry with priority PRIORITY. If there is no entry with the specified priority, move to the nearest entry with an adjacent priority." (interactive "P") (let* ((entry (lp--entry-at (point))) (seen-me nil) (done nil) (entry-list (lp--all-entries))) ;; Get the priority to move to (unless (numberp priority) (setq priority (lyskom-read-num-range 0 255 (lyskom-get-string 'lp-goto-priority) t))) ;; Figure out where to move ;; Loop over all entries (while (and (not done) (cdr entry-list)) (when (eq (car entry-list) entry) (setq seen-me t)) (if (or (< (lp--entry->priority (car entry-list)) priority) (and seen-me (= (lp--entry->priority (car entry-list)) priority))) (setq done t) (setq entry-list (cdr entry-list)))) (when entry-list (goto-char (lp--entry->start-marker (car entry-list)))))) (defun lp--toggle-entry-expansion () "Toggle the expanded state of the current entry." (interactive) (let ((entry (lp--entry-at (point)))) (when entry (set-lp--entry->state entry (if (eq (lp--entry->state entry) 'expanded) 'contracted 'expanded)) (lp--redraw-entry entry)))) (defun lp--expand-entry (arg) "Expand selected entries. With prefix arg, expand only those that were created by someone else." (interactive "P") (let ((entries (or (lp--all-selected-entries) (list (lp--entry-at (point))))) (hidden-list (list lyskom-pers-no 0))) (mapcar (lambda (entry) (when (and (or (null arg) (not (memq (membership->created-by (lp--entry->membership entry)) hidden-list))) (not (eq (lp--entry->state entry) 'expanded))) (set-lp--entry->state entry 'expanded) (lp--redraw-entry entry))) entries))) (defun lp--contract-entry (arg) "Contract selected entries. With prefix arg, contract only those that were created by self." (interactive "P") (let ((entries (or (lp--all-selected-entries) (list (lp--entry-at (point))))) (hidden-list (list lyskom-pers-no 0))) (mapcar (lambda (entry) (when (and (or (null arg) (memq (membership->created-by (lp--entry->membership entry)) hidden-list)) (not (eq (lp--entry->state entry) 'contracted))) (set-lp--entry->state entry 'contracted) (lp--redraw-entry entry))) entries))) (defun lp--quit () "Remove the membership buffer and quit" (interactive) (lyskom-undisplay-buffer)) (defun lp--scroll-advice (fn) (let ((cur (current-column))) (funcall fn) (when (and (boundp 'lyskom-buffer-category) (eq lyskom-buffer-category 'prioritize)) (let ((last-entry (lp--get-last-visible-entry )) (first-entry (lp--next-visible-entry 0))) (cond ((null last-entry) (goto-char lp--list-end-marker)) ((> (point) (lp--entry->end-marker last-entry)) (goto-char (lp--entry->end-marker last-entry)) (when (> (current-column) cur) (beginning-of-line) (forward-char cur))) ((< (point) (lp--entry->start-marker (lp--get-entry first-entry))) (goto-char (lp--entry->start-marker (lp--get-entry first-entry))) (end-of-line) (when (> (current-column) cur) (beginning-of-line) (forward-char cur)))))))) (defadvice scroll-up-command (around lp--scroll-up-advice activate) (lp--scroll-advice (lambda () ad-do-it))) (defadvice scroll-down-command (around lp--scroll-up-advice activate) (lp--scroll-advice (lambda () ad-do-it))) ;;; ============================================================ ;; The mode (defvar lp--mode-line '("--" mode-line-buffer-identification " " global-mode-string " %[(" mode-name mode-line-process minor-mode-alist ")%] " lp--mode-line-selected "--" lp--mode-line-hidden "--" (-3 . "%p") "-%-")) (defvar lp--mode-line-selected "" "String showing number of selected entries.") (defvar lp--mode-line-hidden "" "String showing number of hidden entries.") (defun lp--update-mode-line () (setq lp--mode-line-selected (cond ((= (length (lp--all-selected-entries)) 0) (lyskom-get-string 'no-selection)) (t (lyskom-format 'selection (length (lp--all-selected-entries)))))) (setq lp--mode-line-hidden (cond ((= (length lp--hidden-entries) 0) (lyskom-get-string 'lp-no-hidden)) (t (lyskom-format 'lp-hidden (length lp--hidden-entries))))) (force-mode-line-update)) (def-kom-command kom-prioritize () "Display a list of all memberships with the option to change order, priority, flags, and a number of other things. See `kom-prioritize-in-window'." (interactive) (lyskom-prioritize)) (defun lyskom-prioritize () (let ((kom-deferred-printing nil)) (set-buffer (lp--create-buffer))) (lp--mode) (lp--first-entry)) (defun lp--mode () "\\Mode for prioritizing conferences in LysKOM. \\[lp--move-up] moves a single conference up in the list. \\[lp--mode-down] moves a single conference down in the list. SPC toggles the selection of a single membership. \\[lp--select-region] selects all conferences between point and mark. \\[lp--select-priority] selects all conferences with a certain priority. \\[lp--deselect-region] clears the selection. \\[lp--yank] moves all selected conferences to where point is in the list. \\[lp--set-priority] changes the priority of all selected conferences. \\[lp--toggle-passive] makes passive memberships active and vice versa. \\[lp--toggle-invitation] toggles the invitation flag of a membership. \\[lp--toggle-secret] makes secret memberships non-secret and vice versa. \\[lp--toggle-message-flag] toggles reception of group messages for that conference. Changes take effect immediately. This mode is still under development and is subject to problems. In particular, it is unlikely to handle all error conditions gracefully, which may lead to inconsistencies between the buffer and reality. Should a problem occur, killing the buffer and reopening it usually clears the problem. All bindings: \\{lyskom-prioritize-mode-map} Entry to this mode runs lp--mode-hook, but since the name of this hook is subject to change, be careful when using it." (interactive) (setq major-mode 'lp--mode) (setq mode-name (lyskom-get-string 'lp-mode-name)) (make-local-variable 'lp--format-string) (make-local-variable 'lp--conf-name-width) (make-local-variable 'lp--entry-list) (make-local-variable 'lp--list-start-marker) (make-local-variable 'lp--list-end-marker) (make-local-variable 'lp--selected-entry-list) (make-local-variable 'lp--mode-line-selected) (make-local-variable 'lp--hidden-entries) (make-local-variable 'lp--entry-filter) (setq lp--hidden-entries nil) (setq lp--entry-filter nil) (lyskom-set-menus 'lp--mode lyskom-prioritize-mode-map) (setq lp--mode-line-selected "") (setq mode-line-format lp--mode-line) (lp--update-mode-line) (setq buffer-read-only t) (lyskom-use-local-map lyskom-prioritize-mode-map) (run-hooks 'lp--mode-hook)) (defun lp--set-header (id string) "Set header ID of the current membership buffer to STRING." (save-excursion (let ((inhibit-read-only t) (pos (assq id lp--headers))) (setq lp--headers (delq pos lp--headers)) (if (not pos) (goto-char lp--header-end-marker) (goto-char (elt pos 1)) (delete-region (elt pos 1) (elt pos 2))) (if (null string) (delete-char 1) (let ((start (point-marker)) (end nil)) (set-marker-insertion-type start nil) (insert string) (setq end (point-marker)) (unless pos (insert "\n")) (setq lp--headers (cons (list id start end) lp--headers))))))) (defun lp--create-buffer () "Create a buffer for managing memberships." (let ((buf (lyskom-get-buffer-create 'prioritize (concat (buffer-name) "-membership") t)) (entry-list nil)) (lyskom-save-excursion (set-buffer buf) (let ((buffer-read-only nil)) (erase-buffer) (make-local-variable 'lp--entry-list) (make-local-variable 'lp--list-start-marker) (make-local-variable 'lp--list-end-marker) (make-local-variable 'lp--buffer-done) (make-local-variable 'lp--end-marker) (make-local-variable 'lp--header-end-marker) (make-local-variable 'lp--headers) (setq lp--entry-list nil) (setq lp--buffer-done nil) (lp--compute-format-string) (setq lp--header-end-marker (point-marker)) (set-marker-insertion-type lp--header-end-marker nil) (lyskom-insert (make-string (1- (window-width)) ?=)) (lyskom-insert "\n") (set-marker-insertion-type lp--header-end-marker t) (lp--set-header 'main (lyskom-format 'lp-header-main lyskom-pers-no lyskom-server-name)) (lyskom-format-insert 'lp-list-header (concat (lyskom-get-string 'conference) (make-string (- lp--conf-name-width (length (lyskom-get-string 'conference))) ?\ ))) (lyskom-insert (make-string (1- (window-width)) ?-)) (lyskom-insert "\n") (setq lp--list-start-marker (point-marker)) (goto-char (point-max)) (lyskom-display-buffer buf) (lyskom-traverse-membership mship (let ((entry (lyskom-create-lp--entry nil ; Start nil ; End (membership->priority mship) mship nil (if (memq (membership->created-by mship) (list lyskom-pers-no 0)) 'contracted 'expanded) t nil))) (lp--print-entry entry) (setq entry-list (cons entry entry-list)))) (lp--set-entry-list (nreverse entry-list)) (setq lp--list-end-marker (point-marker)) (lyskom-insert (make-string (1- (window-width)) ?=)) (lyskom-insert (lyskom-get-string 'lp-help-footer)) )) (lyskom-wait-queue 'deferred) buf )) ;;; ================================================================ ;;; User functions for filtering (defun lp--show-hide-memberships-read-before (arg) "Hide memberships that have not been read since a specific date. With prefix arg, removes any such filter that has been applied." (interactive "P") (if arg (lp--del-entry-filter 'lp--entry-filter-before) (let* ((n (lyskom-read-date (lyskom-get-string 'lp-hide-read-sice))) (date (and n (lyskom-create-time 0 0 0 (elt n 2) (elt n 1) (elt n 0) 0 0 nil)))) (lp--replace-entry-filter 'lp--entry-filter-before date)))) (defun lp--show-hide-memberships-read-after (arg) "Hide memberships that have been read since a specific date. With prefix arg, removes any such filter that has been applied." (interactive "P") (if arg (lp--del-entry-filter 'lp--entry-filter-after) (let* ((n (lyskom-read-date (lyskom-get-string 'lp-hide-read-after))) (date (and n (lyskom-create-time 0 0 0 (elt n 2) (elt n 1) (elt n 0) 0 0 nil)))) (lp--replace-entry-filter 'lp--entry-filter-after date)))) (defun lp--show-hide-read-memberships (arg) "Toggle display of memberships with no unread texts." (interactive "P") (if (lp--entry-filter-active 'lp--entry-filter-read) (lp--del-entry-filter 'lp--entry-filter-read) (lp--add-entry-filter 'lp--entry-filter-read))) (defun lp--show-hide-passive-memberships (arg) "Toggle display of passive memberships." (interactive "P") (if (lp--entry-filter-active 'lp--entry-filter-passive) (lp--del-entry-filter 'lp--entry-filter-passive) (lp--add-entry-filter 'lp--entry-filter-passive))) (provide 'mship-edit) ;;; mship-edit.el ends here ;;; Local Variables: ;;; eval: (put 'lp--save-excursion 'edebug-form-spec t) ;;; end: ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: flags.el,v 44.42 2004/02/29 15:12:49 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: flags.el ;;;; ;;;; This file contains code for editing the user variables and saving ;;;; them in the user area. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: flags.el,v 44.42 2004/02/29 15:12:49 byers Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) (put 'lyskom-invalid-flag-type 'error-conditions '(error lyskom-error lyskom-invalid-flag-type)) (defvar lyskom-options-text nil "Text mass when reading options.") (def-kom-var lyskom-options-done nil "When we have read all options this is turned non-nil." local) (def-kom-command kom-save-options (arg) "Save all LysKOM settings. This will save settings in the server but not save anything to your Emacs init file (usually .emacs). With a prefix argument, remove all unknown settings. To edit settings, use `kom-customize'. This command can also save settings to your emacs init file." (interactive "P") (when arg (setq lyskom-saved-unknown-variables nil)) (lyskom-save-options (or lyskom-buffer (current-buffer)) (lyskom-get-string 'saving-settings) (lyskom-get-string 'saving-settings-done) (lyskom-get-string 'could-not-save-options))) (def-kom-command kom-copy-options () "Copy settings from one LysKOM session to another. This is useful if you have configured on session to your liking and want ths settings to be used on other servers as well. This command will save settings to the LysKOM server, but will not save anything to your Emacs init file. Use `kom-customize' to edit settings and save them to your emacs init file." (interactive) (let* ((completions (mapcar (lambda (x) (cons (save-excursion (set-buffer x) (buffer-name)) x)) (delq (or lyskom-buffer (current-buffer)) (copy-sequence lyskom-buffer-list)))) (from-session (completing-read (lyskom-get-string 'session-to-copy-options-from) completions nil t))) (lyskom-message (lyskom-get-string 'reading-settings-from) from-session) (setq lyskom-saved-unknown-variables (lyskom-read-options from-session)) (lyskom-message (lyskom-get-string 'reading-settings-from-done) from-session) ;; Inline kom-save-options (lyskom-save-options (or lyskom-buffer (current-buffer)) (lyskom-get-string 'saving-settings) (lyskom-get-string 'saving-settings-done) (lyskom-get-string 'could-not-save-options)) )) ;;;============================================================ ;;; lyskom-save-options ;;; ;;; Save user-area without feedback in the KOM buffer. This ;;; is for use by all functions but edit-options. ;;; ;;; Messages are given in the minibuffer (defun lyskom-save-options (kombuf start-message done-message error-message) ;; `kom-presence-messages' isn't used directly by the emacs lisp client. ;; Since there is much finer control of what presence messages to give ;; it's hard to encode this is a single boolean, so usually don't try. ;; Ony if the user sees all or no presence messages is it rather clear ;; what the common block value should be: (cond ((or (eq kom-presence-messages-in-buffer t) (eq kom-presence-messages-in-echo-area t)) (setq kom-presence-messages t)) ((not (or kom-presence-messages-in-buffer kom-presence-messages-in-echo-area)) (setq kom-presence-messages nil))) (let* ((print-readably t) (common-block (concat (mapconcat (lambda (var) (condition-case nil (let ((common-name (elt var 0)) (elisp-name (elt var 1)) (type (elt var 2))) (lyskom-format-objects (symbol-name common-name) (funcall (cdr (assq 'write (cdr (assq (or type t) lyskom-global-variable-types)))) (symbol-value elisp-name)))) (lyskom-invalid-flag-type ""))) lyskom-global-variables "\n") )) (elisp-block (concat (mapconcat (lambda (var) (let ((name (lyskom-encode-coding-string (symbol-name var) (or lyskom-server-coding-system 'raw-text))) (data (lyskom-encode-coding-string (lyskom-flag-value-to-string var) (or lyskom-server-coding-system 'raw-text)))) (format "%dH%s %dH%s" (lyskom-string-bytes name) name (lyskom-string-bytes data) data))) lyskom-elisp-variables "\n") (mapconcat (lambda (el) (let ((var (lyskom-encode-coding-string (symbol-name (car el)) (or lyskom-server-coding-system 'raw-text))) (data (lyskom-encode-coding-string (cdr el) (or lyskom-server-coding-system 'raw-text)))) (format "\n%dH%s %dH%s" (lyskom-string-bytes var) var (lyskom-string-bytes data) data))) lyskom-saved-unknown-variables ""))) (user-area (apply 'lyskom-format-objects (apply 'lyskom-format-objects "common" "elisp" (mapcar (lambda (el) (cons 'STRING (cons 'raw-text (car el)))) lyskom-other-clients-user-areas)) (cons 'STRING (cons 'raw-text common-block)) (cons 'STRING (cons 'raw-text elisp-block)) (mapcar (lambda (el) (cons 'STRING (cons 'raw-text (cdr el)))) lyskom-other-clients-user-areas)))) (if (or (lyskom-multibyte-string-p elisp-block) (lyskom-multibyte-string-p common-block) (memq t (mapcar 'lyskom-multibyte-string-p lyskom-other-clients-user-areas))) (lyskom-save-excursion (set-buffer kombuf) (lyskom-format-insert 'save-options-failed-internal (lyskom-multibyte-string-p common-block) (lyskom-multibyte-string-p elisp-block) (memq t (mapcar 'lyskom-multibyte-string-p lyskom-other-clients-user-areas))) (when error-message (lyskom-message "%s" error-message))) (save-excursion (set-buffer kombuf) (when start-message (lyskom-message "%s" start-message)) (initiate-create-text 'options 'lyskom-save-options-2 (cons 'raw-text user-area) (lyskom-create-misc-list) (list (lyskom-create-aux-item 0 1 nil nil (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 "x-kom/user-area")) kombuf done-message error-message))))) ;; This was in lyskom-save-options, to encode each string usgin ;; its own coding system ;; ;; (coding ;; (lyskom-mime-charset-coding-system ;; (lyskom-mime-string-charset data))) ;; (val (condition-case nil ;; (lyskom-encode-coding-string data coding) ;; (error nil))) ;; (lyskom-ignore val) ;; (format "%dC%s%dH%s" ;; (lyskom-string-bytes (symbol-name coding)) ;; (symbol-name coding) ;; (lyskom-string-bytes val) ;; val) (defun lyskom-save-options-2 (text-no kombuf done-message error-message) (if text-no (progn (setq lyskom-current-user-area text-no) (initiate-set-user-area 'options 'lyskom-save-options-3 lyskom-pers-no text-no kombuf done-message error-message text-no)) (save-excursion (set-buffer kombuf) (lyskom-insert-string 'could-not-save-options) (lyskom-message "%s" (lyskom-get-string 'could-not-save-options))))) (defun lyskom-save-options-3 (success kombuf done-message error-message text-no) (save-excursion (set-buffer kombuf) (if success (let ((pers-stat (cache-get-pers-stat lyskom-pers-no))) (when pers-stat (set-pers-stat->user-area pers-stat text-no)) (setq lyskom-current-user-area text-no) (when done-message (lyskom-message "%s" done-message))) (lyskom-format-insert 'could-not-set-user-area lyskom-errno) (when error-message (lyskom-message "%s" error-message))))) (defun lyskom-read-options (&optional buffer) "Reads the user-area and sets the variables according to the choises. Returns a association list of variables that were ignored. Each list element is a cons (NAME . VALUE), where NAME is the name of the variable and VALUE is the unparsed value (i.e. it is always a string). If optional BUFFER is non-nil, read settings in that buffer." (if (and lyskom-pers-no (not (zerop lyskom-pers-no))) (let ((pers-stat (save-excursion (when buffer (set-buffer buffer)) (blocking-do 'get-pers-stat lyskom-pers-no)))) (if (not pers-stat) ;+++ Other error handler. (progn (lyskom-insert-string 'you-dont-exist) nil) (setq lyskom-other-clients-user-areas nil) (if (zerop (pers-stat->user-area pers-stat)) (progn ;; (lyskom-tell-phrases-validate) (setq lyskom-options-done t) nil) (lyskom-read-options-eval (save-excursion (when buffer (set-buffer buffer)) (blocking-do 'get-text (pers-stat->user-area pers-stat))))))) nil)) (defun lyskom-read-options-eval (text) "Handles the call from where we have the text. Returns a alist of variables that were ignored. See lyskom-read-options for more information." (let ((ignored-user-area-vars nil)) (condition-case nil (when text ;+++ Other error handler (let* ((lyskom-options-text (text->text-mass text)) (pointers (lyskom-read-options-eval-get-holerith t)) common-no elisp-no (rest lyskom-options-text) working (r 1)) (let* ((lyskom-options-text pointers) word (r 1)) (while (> (length lyskom-options-text) 2) (setq word (lyskom-read-options-eval-get-holerith t)) (cond ((lyskom-string= word "common") (setq common-no r)) ((lyskom-string= word "elisp") (setq elisp-no r)) (t ;; Build up lyskom-other-clients-user-areas so that it ;; contains a list of pairs: (name . number). (string, int). (setq lyskom-other-clients-user-areas (cons (cons word r) lyskom-other-clients-user-areas)))) (++ r))) (setq lyskom-other-clients-user-areas (nreverse lyskom-other-clients-user-areas)) (setq lyskom-options-text rest) (while (> (length lyskom-options-text) 2) (setq working (lyskom-read-options-eval-get-holerith t)) (cond ;; Note that common-no may be nil here, so the comparison ;; cannot be performed with '=. ((equal r common-no) (let ((lyskom-options-text working) spec name value) (while (> (length lyskom-options-text) 2) (setq name (intern (lyskom-read-options-eval-get-holerith))) (setq value (lyskom-read-options-eval-get-holerith)) (setq spec (cond ((lyskom-flag-global-variable-from-common name)) (t (let ((tmp (vector name (intern (format "lyskom-UNK-%S" name)) nil))) (setq lyskom-global-variables (cons tmp lyskom-global-variables)) tmp)))) (unless (lyskom-maybe-set-var-from-string (elt spec 1) value (elt spec 2)) (setq ignored-user-area-vars (cons (cons (elt spec 1) value) ignored-user-area-vars)))))) ;; Note that elisp-no may be nil here, so the comparison ;; cannot be performed with '=. ((equal r elisp-no) (let ((lyskom-options-text working) name value) (while (> (length lyskom-options-text) 2) (setq name (intern (lyskom-read-options-eval-get-holerith))) (setq value (lyskom-read-options-eval-get-holerith)) (if (lyskom-maybe-set-var-from-string name value) (when (functionp (cdr (assq name lyskom-transition-variables))) (set name (funcall (cdr (assq name lyskom-transition-variables)) (symbol-value name)))) (setq ignored-user-area-vars (cons (cons name value) ignored-user-area-vars)))))) (t (let ((pos lyskom-other-clients-user-areas)) (while (and pos (not (equal (cdr (car pos)) ;The position or the string. r))) (setq pos (cdr pos))) (if pos (setcdr (car pos) working))))) ;Insert the string ;where the position ;was stored. (++ r)) (mapcar 'lyskom-recompile-filter kom-permanent-filter-list) (mapcar 'lyskom-recompile-filter kom-session-filter-list) (setq lyskom-filter-list (append kom-permanent-filter-list kom-session-filter-list)) (setq lyskom-do-when-done (cons kom-do-when-done kom-do-when-done)) ;; Remove not found user-areas (let ((pos lyskom-other-clients-user-areas)) (if pos (progn (while (stringp (cdr (car (cdr pos)))) (setq pos (cdr pos))) (setcdr pos nil))))) (setq lyskom-current-user-area (text->text-no text))) (error (lyskom-message "%s" (lyskom-get-string 'error-in-options-short)))) (setq lyskom-options-done t) (setq lyskom-current-user-area (if text (text->text-no text) 0)) ignored-user-area-vars)) (defun lyskom-read-options-eval-get-holerith (&optional no-coding) (let ((coding (if no-coding 'raw-text lyskom-server-coding-system))) (while (string-match "\\(\\s-\\|[\n\r]\\)" (substring lyskom-options-text 0 1)) (setq lyskom-options-text (substring lyskom-options-text 1))) ;; Read the explicit coding, if any (when (string-match "^[0-9]+C" lyskom-options-text) (let ((len (string-to-int lyskom-options-text))) (setq coding (intern (substring lyskom-options-text (match-end 0) (+ (match-end 0) len)))) (setq lyskom-options-text (substring lyskom-options-text (+ (match-end 0) len))))) ;; Read the string (let ((len (string-to-int lyskom-options-text)) (start (progn (string-match "[0-9]+H" lyskom-options-text) (match-end 0)))) (let ((name (substring lyskom-options-text start (+ start len)))) (setq lyskom-options-text (substring lyskom-options-text (+ start len))) (condition-case nil (lyskom-decode-coding-string name coding) (error name)))))) (defun lyskom-get-holerith (string &optional no-coding) "Get the first holerith string in STRING. If optional NO-CODING is set, assume the string has internal coding." (let ((coding (if no-coding 'raw-text lyskom-server-coding-system))) ;; Strip initial whitespace (when (string-match "^\\(\\s-\\|[\n\r]\\)+" string) (setq string (substring string (match-end 0)))) ;; Read the explicit coding, if any (when (string-match "^[0-9]+C" string) (let ((len (string-to-int string))) (setq coding (intern (substring string (match-end 0) (+ (match-end 0) len)))) (setq string (substring string (+ (match-end 0) len))))) ;; Read the string (let ((len (string-to-int string)) (start (progn (string-match "[0-9]+H" string) (match-end 0)))) (let ((name (substring string start (+ start len)))) (setq string (substring string (+ start len))) (condition-case nil (cons (lyskom-decode-coding-string name coding) string) (error (cons name string))))))) (defun lyskom-maybe-set-var-from-string (var string &optional type) "This is a wrapper around lyskom-set-var-from-string that does nothing if the variable is in kom-dont-read-saved-variables. Return non-nil if the variable shouldn't have been set in the first place." (cond ((eq kom-dont-read-saved-variables t) t) ((memq var kom-dont-read-saved-variables) t) ((not (or (memq var lyskom-elisp-variables) (assq var lyskom-transition-variables) (lyskom-flag-global-variable-from-elisp var))) nil) (t (lyskom-set-var-from-string var string type) t))) (defun lyskom-set-var-from-string (var string &optional type) "This is a wrapper aroud read-from-string. It returns nil, and writes a message when an error occurs." (set var (condition-case nil (funcall (cdr (assq 'read (cdr (assq (or type t) lyskom-global-variable-types)))) string) (error (lyskom-format-insert (lyskom-get-string 'error-in-options) var string) nil)))) (defun lyskom-flag-value-to-string (symbol) "Convert value of SYMBOL to a string." (cond ((eq symbol 'kom-permanent-filter-list) (prin1-to-string (mapcar (lambda (filter) (lyskom-create-filter (filter->pattern filter) (filter->attribute-list filter) nil)) kom-permanent-filter-list))) (t (prin1-to-string (symbol-value symbol))))) (defun lyskom-flag-global-variable-from-common (var) "Return the element from lyskom-global-variables corresponding to VAR." (lyskom-traverse el lyskom-global-variables (when (eq (aref el 0) var) (lyskom-traverse-break el)))) (defun lyskom-flag-global-variable-from-elisp (var) "Return the element from lyskom-global-variables corresponding to elisp variable VAR." (lyskom-traverse el lyskom-global-variables (when (eq (aref el 1) var) (lyskom-traverse-break el)))) (defun lyskom-flag-write-boolean (val) (if val "1" "0")) (defun lyskom-flag-read-boolean (str) (string= "1" str)) (defun lyskom-flag-write-symbol-list (val) (cond ((symbolp val) (lyskom-format-objects (symbol-name val))) (t (mapconcat (lambda (x) (lyskom-format-objects (symbol-name x))) val " ")))) (defun lyskom-flag-read-symbol-list (str) (mapcar 'intern (lyskom-get-holerith-list str))) (defun lyskom-flag-read-from-string (str) (car (read-from-string str))) (defun lyskom-flag-read-integer (str) (cond ((equal str "nil") nil) (t (string-to-int str)))) (defun lyskom-flag-write-integer (val) (cond ((integerp val) (prin1-to-string val)) (t (signal 'lyskom-invalid-flag-type nil)))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: messages.el,v 44.10 2003/08/25 08:07:22 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: messages.el ;;;; Author: David Byers ;;;; ;;;; This file implements the personal message handler queue ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: messages.el,v 44.10 2003/08/25 08:07:22 byers Exp $\n")) (defvar lyskom-personal-message-handlers nil "A list of personal message handlers. Each element of the list is a function of four arguments, MESSAGE-TYPE SENDER RECIPIENT and TEXT. MESSAGE-TYPE is one of personal, group or common and denotes the type of message. SENDER is the conf-stat of the sender of the message. RECIPIENT is the conf-stat of the message recipient or zero for common messages. The functions may use the lyskom-set-current-message-text function to modify the message text. A non-nil return value from the function indicates that the message was handled and no other handlers need to be called and a nil return value means that the message was not handled and should be sent to the next handler.") (defvar lyskom-message-current-text "" "The text of the current message. Use lyskom-set-current-message-text to modify this variable.") (defun lyskom-set-current-message-text (text) "Set the current message text to TEXT. For use by personal message handlers." (setq lyskom-message-current-text text)) (defun lyskom-handle-personal-message (sender recipient text) "Handle a personal message. SENDER is the sender of the message (a conf-stat). RECIPIENT is the recipient of the message (a conf-stat or 0 for common messages). TEXT is the text of the message." (let ((message-type (cond ((eq recipient 0) 'common) ((= (conf-stat->conf-no recipient) lyskom-pers-no) 'personal) (t 'group))) (lyskom-message-current-text text) (handlers lyskom-personal-message-handlers) (done nil)) (while (and (not done) handlers) (setq done (funcall (car handlers) message-type sender recipient lyskom-message-current-text)) (setq handlers (cdr handlers))) (if (not done) (lyskom-show-personal-message sender recipient lyskom-message-current-text)))) (defun lyskom-add-personal-message-handler (handler &optional place relative new) "Add HANDLER to the queue of personal message handlers. Optional argument PLACE can be one of 'before or 'after. Optional argument RELATIVE can be another handler in the queue. IF fourth argument NEW is t, the handler is only added if it does not already exist in the list. The new handler is placed first in the queue if PLACE is 'before and RELATIVE is not specified; last if PLACE is 'after and RELATIVE is not specified; or before or after the handler RELATIVE in the queue, depending on the value of PLACE. If PLACE is nil, 'after is assumed." (if (or (not new) (not (memq handler lyskom-personal-message-handlers))) (progn (setq place (or (and (eq place 'before) 'before) 'after)) (setq relative (car-safe (memq relative lyskom-personal-message-handlers))) (let ((pos (if relative (- (length lyskom-personal-message-handlers) (length (memq relative lyskom-personal-message-handlers)))))) (cond ((and relative (eq place 'after)) (setcdr (nthcdr pos lyskom-personal-message-handlers) (cons handler (nthcdr (1+ pos) lyskom-personal-message-handlers))) ) ((and relative (eq place 'before) (> pos 0)) (setcdr (nthcdr (1- pos) lyskom-personal-message-handlers) (cons handler (nthcdr pos lyskom-personal-message-handlers))) ) ((and lyskom-personal-message-handlers (eq place 'after)) (setcdr (nthcdr (1- (length lyskom-personal-message-handlers)) lyskom-personal-message-handlers) (cons handler nil))) ((or (null lyskom-personal-message-handlers) (eq place 'before)) (setq lyskom-personal-message-handlers (cons handler lyskom-personal-message-handlers))) (t (setcdr (nthcdr (1- (length lyskom-personal-message-handlers)) lyskom-personal-message-handlers) (cons handler nil))))) lyskom-personal-message-handlers))) (defun lyskom-info-request-handler (message-type sender recipient text) (if (lyskom-string= text "\011\016\006\017") (progn (initiate-send-message 'follow nil (conf-stat->conf-no sender) (format "emacs-version: %s\nclient-version: %s" (emacs-version) lyskom-clientversion)) t) nil)) (defun lyskom-filter-message-handler (message-type sender recipient text) "Optionally kill messages from certain senders or to certain recipients. See the documentation for kom-ignore-message-recipients and kom-ignore-message-senders for more information." (condition-case nil (or (memq (cond ((lyskom-conf-stat-p sender) (conf-stat->conf-no sender)) ((lyskom-uconf-stat-p sender) (uconf-stat->conf-no sender)) (t sender)) kom-ignore-message-senders) (memq (cond ((lyskom-conf-stat-p recipient) (conf-stat->conf-no recipient)) ((lyskom-uconf-stat-p recipient) (uconf-stat->conf-no recipient)) (t recipient)) kom-ignore-message-recipients)) (error nil))) (lyskom-add-personal-message-handler 'lyskom-filter-message-handler 'before) (lyskom-add-personal-message-handler 'lyskom-info-request-handler 'before) (eval-and-compile (provide 'lyskom-messages)) ;;; messages.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: ansaphone.el,v 44.12 2003/01/08 00:33:14 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: ansaphone.el ;;;; Author: David Byers ;;;; ;;;; This file implements the auto-reply facility. ;;;; It must be loaded after messages.el ;;;; (eval-when-compile (require 'lyskom-vars "vars") (require 'lyskom-macros "macros") (require 'lyskom-command "command") (require 'lyskom-language "language") (require 'lyskom-messages "messages") (require 'lyskom-services "services")) (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: ansaphone.el,v 44.12 2003/01/08 00:33:14 byers Exp $\n")) (defconst lyskom-ansaphone-tag "Auto-reply:\n") ;;;============================================================ ;;; ;;; User functions ;;; (def-kom-command kom-change-auto-reply (&optional message) "Change the default automatic reply message. This message is sent in reply to personal messages when auto reply is turned on. See `kom-toggle-auto-reply'." (interactive) (let ((message (or message (lyskom-read-from-minibuffer (lyskom-get-string 'ansaphone-new-message) (if (stringp kom-ansaphone-default-reply) (cons kom-ansaphone-default-reply 0))))) (lyskom-last-text-format-flags nil)) (setq kom-ansaphone-default-reply message) (lyskom-format-insert (lyskom-get-string-sol 'ansaphone-message) kom-ansaphone-default-reply))) (def-kom-command kom-toggle-auto-reply () "Toggle automatic replies to personal messages. When this is turned on, replies will be sent automatically to personal messages (sent with `kom-send-message'). The reply sent depents on `kom-ansaphone-default-reply' and `kom-ansaphone-replies'. Messages received when automatic replies are on may also be recorded. See `kom-ansaphone-record-messages'" (interactive) (setq kom-ansaphone-on (not kom-ansaphone-on)) (lyskom-format-insert (lyskom-get-string 'ansaphone-state-r) (lyskom-get-string (if kom-ansaphone-on 'state-on 'state-off))) (if kom-ansaphone-on (progn (setq lyskom-ansaphone-when-set (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm)) (lyskom-format-insert (lyskom-get-string-sol 'ansaphone-message) kom-ansaphone-default-reply)))) (def-kom-command kom-list-messages () "List messages recorded when automatic replies are on. To erase recorded messages, use `kom-erase-messages'. See `kom-toggle-auto-reply' and `kom-ansaphone-record-messages'." (interactive) (if (null lyskom-ansaphone-messages) (lyskom-format-insert (lyskom-get-string 'ansaphone-no-messages)) (progn (lyskom-format-insert (lyskom-get-string 'ansaphone-message-list-start)) (mapcar (function (lambda (msg) (lyskom-show-personal-message (blocking-do 'get-conf-stat (elt msg 0)) (blocking-do 'get-conf-stat (elt msg 1)) (elt msg 2) (elt msg 3) 'nobeep))) (reverse lyskom-ansaphone-messages)) (lyskom-format-insert (lyskom-get-string 'ansaphone-message-list-end))))) (def-kom-command kom-erase-messages () "Erase messages recorded when automatic replies are on. To list recorded messages, use `kom-list-messages'. See `kom-toggle-auto-reply' and `kom-ansaphone-record-messages'." (interactive) (lyskom-message "%s" (lyskom-get-string 'ansaphone-messages-gone)) (setq lyskom-ansaphone-messages nil)) (defun lyskom-ansaphone-send-message (recipient message) (initiate-send-message 'async nil (if (numberp recipient) recipient (conf-stat->conf-no recipient)) (concat lyskom-ansaphone-tag message))) (defun lyskom-ansaphone-message-handler (message-type sender recipient text) "Personal message handler. Automatically reply to certain personal messages and strip auto-reply identification from messages. See kom-ansaphone-on" (let ((is-automatic (eq 0 (string-match lyskom-ansaphone-tag text)))) (if is-automatic (progn (string-match (concat "^" lyskom-ansaphone-tag "\\(\\(.\\|\n\\)*\\)") text) (lyskom-set-current-message-text (substring text (match-beginning 1) (match-end 1))))) ;; ;; See if we want to reply to this message ;; (if (and kom-ansaphone-on sender recipient (not is-automatic)) (let ((reply (lyskom-ansaphone-find-reply message-type (conf-stat->conf-no sender) (cond ((numberp recipient) recipient) (t (conf-stat->conf-no recipient))) text))) (if (and reply (elt reply 4)) (progn (setq reply (concat (lyskom-format (lyskom-get-string 'ansaphone-message-header) lyskom-ansaphone-when-set) (elt reply 4))) (lyskom-ansaphone-send-message sender reply))))) ;; ;; See if we want to record this message ;; (if (and kom-ansaphone-on kom-ansaphone-record-messages sender) (lyskom-ansaphone-record-message sender recipient lyskom-message-current-text))) ;; ;; Perhaps we want to show the message, perhaps not ;; (if kom-ansaphone-on (not kom-ansaphone-show-messages) nil)) (defun lyskom-ansaphone-find-reply (message-type sender recipient text) "Find an automatic reply suitable for messages of type MESSAGE-TYPE from SENDER to RECIPIENT consisting of TEXT. See the documentation for kom-ansaphone-default-reply and kom-ansaphone-replies." (let ((exprs kom-ansaphone-replies) (result nil)) (while exprs (if (and (or (null (elt (car exprs) 0)) (eq (elt (car exprs) 0) message-type)) (or (null (elt (car exprs) 1)) (eq (elt (car exprs) 1) sender) (and (listp (elt (car exprs) 1)) (memq sender (elt (car exprs) 1)))) (or (null (elt (car exprs) 2)) (eq (elt (car exprs) 2) recipient) (and (listp (elt (car exprs) 2)) (memq recipient (elt (car exprs) 2)))) (or (null (elt (car exprs) 3)) (string-match (elt (car exprs) 3) text))) (progn (setq result (car exprs)) (setq exprs nil))) (setq exprs (cdr-safe exprs))) (or result (and (eq message-type 'personal) (list nil nil nil nil kom-ansaphone-default-reply))))) (defun lyskom-ansaphone-record-message (sender recipient text) (if (not (numberp sender)) (setq sender (conf-stat->conf-no sender))) (if (not (numberp recipient)) (setq recipient (conf-stat->conf-no recipient))) (setq lyskom-ansaphone-messages (cons (list sender recipient text (lyskom-current-client-time)) lyskom-ansaphone-messages))) (lyskom-add-personal-message-handler 'lyskom-ansaphone-message-handler 'before nil t) (eval-and-compile (provide 'lyskom-ansaphone)) ;;; ansaphone.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: remote-control.el,v 44.11 2003/08/24 21:12:44 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: remote-control.el ;;;; Author: David Byers ;;;; ;;;; This file implements the remote control mechanism. ;;;; It must be loaded after messages.el ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: remote-control.el,v 44.11 2003/08/24 21:12:44 byers Exp $\n")) (eval-when-compile (require 'lyskom-command "command")) ;;;============================================================ ;;; ;;; Internal variables. ;;; (defconst lyskom-remote-commands '(("set message" . lyskom-remote-set-message) ("list messages" . lyskom-remote-list-messages) ("erase messages" . lyskom-remote-erase-messages) ("autoreply" . lyskom-remote-autoreply) ("quit" . lyskom-remote-quit))) ;;;============================================================ ;;; ;;; Interactive functions ;;; (def-kom-command kom-remote-autoreply (&optional session-no state) "Remotely turn on or off the auto reply facility of another client. This is similar to `kom-toggle-auto-reply', but operates on another session. You will be prompted for which session to control. For remote control to work the target session must have remote control turned on, and the user you are logged on as must have permission to manipulate that session. See `kom-remote-controllers' and `kom-self-control' for settings that affect remote control." (interactive) (setq session-no (or session-no (car (lyskom-read-session-no 'remote-control-who nil nil t)))) (setq state (or state (cdr-safe (assoc (lyskom-completing-read (lyskom-get-string 'remote-control-autoreply) (lyskom-maybe-frob-completion-table lyskom-onoff-table t) nil t nil nil) (lyskom-maybe-frob-completion-table lyskom-onoff-table t))))) (let ((info (blocking-do 'get-session-info session-no))) (lyskom-send-message (session-info->pers-no info) (format "Remote-command: %d %d\nautoreply\n%s" lyskom-session-no session-no (cond ((eq state 'on) "on") ((eq state 'off) "off") (t ""))) t))) (def-kom-command kom-remote-set-message (&optional session-no message) "Remotely set the default auto reply message of another client. This is similar to `kom-change-auto-reply', but operates on another session. You will be prompted for which session to control. For remote control to work the target session must have remote control turned on, and the user you are logged on as must have permission to manipulate that session. See `kom-remote-controllers' and `kom-self-control' for settings that affect remote control." (interactive) (setq session-no (or session-no (car (lyskom-read-session-no 'remote-control-who nil nil t)))) (setq message (or message (lyskom-read-string (lyskom-get-string 'message-prompt)))) (let ((info (blocking-do 'get-session-info session-no))) (lyskom-send-message (session-info->pers-no info) (format "Remote-command: %d %d\nset message\n%s" lyskom-session-no session-no message) t))) (def-kom-command kom-remote-list-messages (&optional session-no) "List messages collected from a remote auto reply facility. This is similar to `kom-list-messages', but operates on another session. You will be prompted for which session to control. For remote control to work the target session must have remote control turned on, and the user you are logged on as must have permission to manipulate that session. See `kom-remote-controllers' and `kom-self-control' for settings that affect remote control." (interactive) (setq session-no (or session-no (car (lyskom-read-session-no 'remote-control-who nil nil t)))) (let ((info (blocking-do 'get-session-info session-no))) (lyskom-send-message (session-info->pers-no info) (format "Remote-command: %d %d\nlist messages\n" lyskom-session-no session-no) t))) (def-kom-command kom-remote-erase-messages (&optional session-no) "Erase stored messages on a remote auto reply facility. This is similar to `kom-erase-messages', but operates on another session. You will be prompted for which session to control. For remote control to work the target session must have remote control turned on, and the user you are logged on as must have permission to manipulate that session. See `kom-remote-controllers' and `kom-self-control' for settings that affect remote control." (interactive) (setq session-no (or session-no (car (lyskom-read-session-no 'remote-control-who nil nil t)))) (let ((info (blocking-do 'get-session-info session-no))) (lyskom-send-message (session-info->pers-no info) (format "Remote-command: %d %d\nerase messages\n" lyskom-session-no session-no) t))) (def-kom-command kom-remote-quit (&optional session-no) "Quit a remote client. The difference between this command and `kom-force-logout' is that the latter uses server facilities to forcefully disconnect the session, while the former allows the client to cleanly disconnect from the server. You will be prompted for which session to control. For remote control to work the target session must have remote control turned on, and the user you are logged on as must have permission to manipulate that session. See `kom-remote-controllers' and `kom-self-control' for settings that affect remote control." (interactive) (setq session-no (or session-no (car (lyskom-read-session-no 'remote-control-who nil nil t)))) (let ((info (blocking-do 'get-session-info session-no))) (lyskom-send-message (session-info->pers-no info) (format "Remote-command: %d %d\nquit\n" lyskom-session-no session-no) t))) ;;;============================================================ ;;; ;;; Main handler function ;;; (defun lyskom-remote-handler (message-type sender recipient text) "Personal message handler. Handler to implement remote control of the ansaphone." (let* ((error nil) (is-remote (eq 0 (string-match "^Remote-command: \\([0-9]+\\) \\([0-9]+\\)\n" text))) (is-from-me (and is-remote (= (string-to-number (substring text (match-beginning 1) (match-end 1))) lyskom-session-no))) (is-to-me (and is-remote (= (string-to-number (substring text (match-beginning 2) (match-end 2))) lyskom-session-no))) (is-valid (eq 0 (string-match "^Remote-command: \\([0-9]+\\) \\([0-9]+\\)\n\\(.*\\)\n\\(\\(\n\\|.\\)*\\)$" text))) (is-trusted (or (memq (conf-stat->conf-no sender) kom-remote-controllers) (and kom-self-control (eq (conf-stat->conf-no sender) lyskom-pers-no))))) (cond ((not is-remote) nil) (is-from-me t) ((not is-to-me) t) ((not is-trusted) (lyskom-ansaphone-send-message lyskom-pers-no (lyskom-format (lyskom-get-string 'illegal-remote) (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm) sender recipient text)) (lyskom-ansaphone-send-message sender (lyskom-format (lyskom-get-string 'illegal-remote-reply) (lyskom-get-string 'remote-not-in-list))) t) ((not is-valid) (setq error 'remote-bad-command)) (t (let* ((command (substring text (match-beginning 3) (match-end 3))) (arg (substring text (match-beginning 4) (match-end 4))) (desc (assoc command lyskom-remote-commands))) (if (null desc) (setq error 'remote-bad-command) (setq error (funcall (cdr desc) arg sender recipient text)))))) (if error (progn (lyskom-ansaphone-send-message sender (lyskom-format (lyskom-get-string 'illegal-remote-reply) (or (lyskom-get-string error) (lyskom-get-string 'remote-unknown-error)))))) is-remote)) (defun lyskom-remote-set-message (arg sender recipient text) (if arg (let ((lyskom-last-text-format-flags nil)) (setq kom-ansaphone-default-reply arg) (setq lyskom-ansaphone-when-set (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm)) (lyskom-ansaphone-send-message sender (concat (lyskom-get-string 'ansaphone-new-message) arg)) (lyskom-insert-before-prompt (lyskom-format (lyskom-get-string-sol 'remote-set-message) sender (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm) arg)) nil) 'remote-bad-command)) ;;;============================================================ ;;; ;;; Command handlers ;;; (defun lyskom-remote-autoreply (arg sender recipient text) (cond ((string= (downcase arg) "on") (setq kom-ansaphone-on t)) ((string= (downcase arg) "off") (setq kom-ansaphone-on nil)) (t (setq kom-ansaphone-on (not kom-ansaphone-on)))) (lyskom-ansaphone-send-message sender (lyskom-format (lyskom-get-string 'ansaphone-state) (lyskom-get-string (if kom-ansaphone-on 'state-on 'state-off)))) (lyskom-insert-before-prompt (lyskom-format (lyskom-get-string 'remote-set-ansaphone) sender (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm) (lyskom-get-string (if kom-ansaphone-on 'state-on 'state-off)))) nil) (defun lyskom-remote-list-messages (arg sender recipient text) (if (null lyskom-ansaphone-messages) (lyskom-ansaphone-send-message sender (lyskom-get-string 'ansaphone-no-messages)) (progn (lyskom-collect 'follow) (let ((tmp (reverse lyskom-ansaphone-messages))) (while tmp (initiate-get-conf-stat 'follow nil (elt (car tmp) 0)) (initiate-get-conf-stat 'follow nil (elt (car tmp) 1)) (setq tmp (cdr tmp)))) (lyskom-use 'follow 'lyskom-remote-list-messages-1 sender))) nil) (defun lyskom-remote-list-messages-1 (sender &rest pairs) (let ((message "") (tmp (reverse lyskom-ansaphone-messages)) (from nil) (to nil)) (while pairs (setq from (car pairs) to (car (cdr pairs))) (setq pairs (cdr (cdr pairs))) (setq message (concat message (lyskom-format-as-personal-message from to (elt (car tmp) 2) (elt (car tmp) 3)) (if pairs "\n\n" ""))) (setq tmp (cdr tmp))) (lyskom-ansaphone-send-message sender message) (lyskom-insert-before-prompt (lyskom-format (lyskom-get-string 'remote-list-messages) sender (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm))))) (defun lyskom-remote-erase-messages (arg sender recipient text) (setq lyskom-ansaphone-messages nil) (lyskom-format-insert-before-prompt (lyskom-get-string 'remote-erase-messages) sender (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm)) nil) (defun lyskom-remote-quit (arg sender recipient text) (lyskom-insert-before-prompt (lyskom-format (lyskom-get-string 'remote-quit) sender (lyskom-format-time 'timeformat-yyyy-mm-dd-hh-mm))) (lyskom-quit)) ;;;============================================================ ;;; ;;; Clean-up and installation ;;; (lyskom-add-personal-message-handler 'lyskom-remote-handler 'before 'lyskom-ansaphone-message-handler t) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: menus.el,v 44.38 2005/01/11 15:00:14 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: menus.el ;;;; Author: Niels Möller ;;;; ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: menus.el,v 44.38 2005/01/11 15:00:14 _cvs_pont_lyskomelisp Exp $\n")) (lyskom-external-function set-buffer-menubar) (lyskom-external-function popup-menu) (lyskom-external-function add-submenu) (def-kom-var lyskom-current-menu-category nil "Category of menus currently used in buffer" local) (defvar lyskom-menu-template '((menu read ((item kom-view-next-text) (item kom-list-news) (item kom-list-summary) (item kom-go-to-conf) (hline) (menu review ((item kom-view) (item kom-review-next) (item kom-review-last-normally-read) (item kom-review-noconversion) (item kom-review-converted) (item kom-review-rot13) (item kom-review-mail-headers) (hline) (item kom-find-root) (item kom-view-commented-text) (item kom-review-comments) (item kom-review-cross-references) (item kom-review-tree) (item kom-find-root-review) (hline) (item kom-review-by-to) (item kom-review-first) (item kom-review-all) (item kom-review-more) (hline) (item kom-make-review-mark-as-read) (item kom-make-review-not-mark-as-read) (hline) (item kom-review-stack) (item kom-review-backward) (item kom-review-clear))) (menu unread ((item kom-mark-unread) (item kom-unread-last-normally-read) (hline) (item kom-unread-root) (item kom-unread-commented-text) (item kom-unread-comments) (item kom-unread-tree) (item kom-unread-root-review) (hline) (item kom-unread-by-to) (item kom-unread-first) (item kom-unread-all) (item kom-unread-more) (hline) (item kom-unread-presentation) (item kom-unread-faq) (item kom-unread-server-faq))) (menu marks ((item kom-mark-text) (item kom-unmark-text) (hline) (item kom-list-marks) (item kom-review-marked-texts) (item kom-review-all-marked-texts) (hline) (item kom-unread-marked-texts) (item kom-unread-all-marked-texts))) (menu filters ((item kom-filter-author) (item kom-filter-subject) (item kom-filter-text) (item kom-filter-recipient) (hline) (item kom-list-filters) (item kom-filter-edit))) (hline) (item kom-save-text) (item kom-save-text-body) (hline) (item kom-compare-texts) (item kom-diff-texts) (hline) (item kom-postpone) (item kom-jump) (item kom-super-jump) (item kom-set-unread))) (menu write ((item kom-write-text) (item kom-send-letter) (item kom-write-comment) (item kom-private-answer) (item kom-write-footnote) (hline) (menu receivers ((item kom-will-person-read-text) (hline) (item kom-add-recipient) (item kom-add-copy) (item kom-add-bcc) (item kom-sub-recipient) (hline) (item kom-move-text) (item kom-move-text-tree))) (menu commented ((item kom-add-comment) (item kom-sub-comment) (item kom-add-footnote) (item kom-sub-footnote))) (menu aux-items ((item kom-add-cross-reference) (item kom-add-private-answer) (item kom-add-no-comments) (item kom-add-request-confirm) (item kom-fast-reply) (item kom-agree))) (hline) (item kom-next-kom) (item kom-next-unread-kom) (item kom-previous-kom) (hline) (item kom-set-session-priority) (hline) (item kom-send-message))) (menu conference ((item kom-go-to-conf) (item kom-go-to-next-conf) (hline) (item kom-review-presentation) (item kom-status-conf) (item kom-review-faq) (item kom-list-faqs) (hline) (item kom-list-conferences) (item kom-list-re) (item kom-list-new-conferences) (hline) (menu conf-admin ((item kom-change-presentation) (item kom-set-presentation) (item kom-remove-presentation) (hline) (item kom-change-name) (item kom-change-supervisor) (item kom-set-garb-nice) (item kom-set-super-conf) (item kom-set-permitted-submitters) (item kom-change-conf-type) (item kom-limit-import) (hline) (item kom-change-conf-motd) (item kom-set-motd-text) (item kom-unset-conf-motd) (hline) (item kom-change-conf-faq) (item kom-add-faq) (item kom-del-faq) (hline) (item kom-sub-member) (hline) (item kom-create-conf) (item kom-delete-conf) (item kom-list-created-conferences))) (hline) (item kom-add-self) (item kom-sub-self) (item kom-add-member) (item kom-prioritize))) (menu person ((item kom-who-is-on) (item kom-who-is-on-in-conference) (item kom-who-is-present-in-conference) (item kom-who-is-on-and-friend) (hline) (item kom-list-persons) (item kom-list-re) (item kom-list-new-persons) (hline) (item kom-review-presentation) (item kom-status-person) (item kom-status-session) (item kom-list-created-conferences) (item kom-is-person-member-of-conference) (item kom-will-person-read-text) (hline) (menu membership ((item kom-add-self) (item kom-sub-self) (hline) (item kom-join-all-conferences) (item kom-leave-all-conferences) (hline) (item kom-change-priority) (item kom-change-message-flag) (item kom-prioritize))) (menu pers-admin ((item kom-change-presentation) (item kom-change-name) (item kom-change-parenthesis) (item kom-change-password) (item kom-redirect-comments) (item kom-change-privileges))) (hline) (item kom-who-am-i))) (menu server ((item kom-status-server) (item kom-review-server-faq) (item kom-list-server-faqs) (hline) (menu server-admin ((item kom-change-server-faq) (item kom-add-server-faq) (item kom-del-server-faq) (hline) (item kom-set-motd) (item kom-remove-motd) (hline) (item kom-recommend-conference) (hline) (item kom-enable-adm-caps) (item kom-disable-adm-caps) (hline) (item kom-shutdown-server) (item kom-sync-database))) )) (menu other ((item kom-help) (menu language ((item kom-change-global-language) (item kom-change-local-language))) (item kom-where-is) (item kom-display-time) (item kom-calculate) (hline) (item kom-customize) (item kom-copy-options) (item kom-save-options) (item kom-show-user-area) (hline) (menu remote-control ((item kom-remote-autoreply) (item kom-remote-set-message) (item kom-remote-list-messages) (item kom-remote-erase-messages) (item kom-remote-quit))) (menu autoreply ((item kom-toggle-auto-reply) (item kom-change-auto-reply) (item kom-list-messages) (item kom-erase-messages))) (hline) (item kom-keep-alive) (item kom-stop-keep-alive) (hline) (item kom-recover) (item kom-start-anew) (item kom-force-logout) (item kom-list-sessions) (item kom-quit)))) "The menus used in LysKOM.") (defvar lyskom-popup-menu-template (` (menu lyskom ((,@ lyskom-menu-template)))) "Popup-menu in the backgrouond of the LysKOM window") (defvar lyskom-edit-menu-template '((menu lyskom ((item kom-ispell-message) (item kom-edit-send) (hline receiver-separator) (item kom-edit-add-recipient) (item kom-edit-add-copy) (item kom-edit-add-bcc) (item kom-edit-move-text) (item kom-edit-add-cross-reference) (hline special-separator) (item kom-edit-add-no-comments) (item kom-edit-add-personal-comments) (item kom-edit-add-read-confirm-request) (hline comment-separator) (item kom-edit-show-commented) (hline send-separator) (item kom-edit-quit)))) "The menus for editing LysKOM messages.") (defvar lyskom-prioritize-menu-template '((menu lyskom ((item lp--toggle-membership-selection) (hline select-separator-1) (item lp--select-region) (item lp--select-priority) (hline select-separator-2) (item lp--deselect-priority) (item lp--deselect-all) (hline select-separator-3) (menu lp--membership-priority ((item lp--set-priority) (item lp--move-up) (item lp--move-down) (item lp--increase-priority) (item lp--decrease-priority) (item lp--yank))) (menu lp--membership-type ((item lp--toggle-invitation) (item lp--toggle-passive) (item lp--toggle-message-flag) (item lp--toggle-secret))) (menu lp--filter ((item lp--show-hide-memberships-read-before) (item lp--show-hide-memberships-read-after) (item lp--show-hide-read-memberships) (item lp--show-hide-passive-memberships) (hline filter-separator) (item lp--show-all))) (menu lp--membership-expansion ((item lp--toggle-entry-expansion) (item lp--expand-entry) (item lp--contract-entry)) (hline quit-separator) (item lp--quit)))))) (defvar lyskom-menu-list '((lyskom-mode . lyskom-menu) (lyskom-edit-mode . lyskom-edit-menu) (lp--mode . lyskom-prioritize-menu)) "List of menu sets in LysKOM") (defvar lyskom-menu nil "A keymap describing the LysKOM top menu.") (defvar lyskom-edit-menu nil "A keymap the LysKOM menu in the edit buffer.") (defvar lyskom-prioritize-menu nil "Menus for the prioritize mode.") (defvar lyskom-popup-menu nil "A keymap the LysKOM menu in the edit buffer.") ;;; ================================================================ ;;; Hack for swedish bindings and shortcuts (defvar lyskom-swedish-bindings `((å . (aring Aring ,(elt (kbd "å") 0) ,(elt (kbd "Å") 0) å Å 229 197 2277 2245 3909 3941)) (ä . (adiaeresis Adiaeresis ,(elt (kbd "ä") 0) ,(elt (kbd "Ä") 0) ä Ä 228 196 2276 2244 3908 3940))) "Hack to deal with binding swedish characters") (defvar lyskom-swedish-bindings-reverse (let ((tmp nil) (seq lyskom-swedish-bindings)) (while seq (let ((el (car seq))) (setq tmp (nconc tmp (mapcar (lambda (x) (cons x (car el))) (cdr el))))) (setq seq (cdr seq))) tmp) "Hack to deal with binding swedish characters") (defun lyskom-menu-guess-shortcuts (keymap &optional prefix result force) (lyskom-traverse-keymap (lambda (key binding) (when binding (let ((force (or force (assq key lyskom-swedish-bindings-reverse)))) (if (keymapp binding) (setq result (lyskom-menu-guess-shortcuts (cond ((symbolp binding) (symbol-value binding)) (t binding)) (append prefix (list key)) result force)) (when force (setq key `(,@prefix ,key)) (if (assq binding result) (setcdr (assq binding result) (cons (apply 'vector key) (cdr (assq binding result)))) (setq result (cons (cons binding (list (apply 'vector key))) result)))))))) keymap) result) (defun lyskom-build-menus () "Create menus according to LYSKOM-MENUS" (lyskom-xemacs-or-gnu (lyskom-build-menus-xemacs) (lyskom-build-menus-gnu))) (defun lyskom-build-menus-xemacs () (setq lyskom-prioritize-menu (lyskom-define-menu-xemacs lyskom-prioritize-menu-template)) (setq lyskom-edit-menu (lyskom-define-menu-xemacs lyskom-edit-menu-template)) (setq lyskom-popup-menu (lyskom-define-menu-xemacs lyskom-popup-menu-template)) (setq lyskom-menu (lyskom-define-menu-xemacs lyskom-menu-template))) (defun lyskom-build-menus-gnu () "Rebuilds the LysKOM menus" (setq lyskom-menu (make-sparse-keymap)) (setq lyskom-edit-menu (make-sparse-keymap)) (setq lyskom-popup-menu (make-sparse-keymap)) (setq lyskom-prioritize-menu (make-sparse-keymap)) (lyskom-define-menu-gnu lyskom-prioritize-menu lyskom-prioritize-menu-template) (lyskom-define-menu-gnu lyskom-menu lyskom-menu-template) (lyskom-define-menu-gnu lyskom-edit-menu lyskom-edit-menu-template) (lyskom-define-menu-gnu lyskom-popup-menu (list lyskom-popup-menu-template)) (setq lyskom-popup-menu (lookup-key lyskom-popup-menu [lyskom]))) (defun lyskom-define-menu-xemacs (menus &optional specials) (let ((specials (or specials (lyskom-menu-guess-shortcuts (current-local-map))))) (cond ((null (car menus))) ((listp (car menus)) ; Menu bar (mapcar (lambda (x) (lyskom-define-menu-xemacs x specials)) menus)) ((eq (car menus) 'menu) ; A menu (let ((menu-title (car (cdr menus))) (menu-items (car (cdr (cdr menus))))) (cons (lyskom-get-menu-string menu-title) (mapcar (lambda (item) (let ((type (car item)) (symbol (car (cdr item)))) (cond ((eq type 'item) (let ((shortcut nil)) (when (assq symbol specials) (unless (lyskom-traverse key (cdr (assq symbol specials)) (unless (condition-case nil (eq (lookup-key (current-local-map) key) symbol) (error nil)) (lyskom-traverse-break t))) (setq shortcut (mapconcat (lambda (key) (if (assq key lyskom-swedish-bindings-reverse) (symbol-name (cdr (assq key lyskom-swedish-bindings-reverse))) (single-key-description key))) (car (cdr (assq symbol specials))) " ")))) (if shortcut (vector (lyskom-get-menu-string symbol) symbol ':active t ':keys shortcut) (vector (lyskom-get-menu-string symbol) symbol ':active t)))) ((eq type 'hline) "--:shadowEtchedIn") ((eq type 'menu) (lyskom-define-menu-xemacs item specials)) (t (error "Bad menu item: %S" item))))) menu-items)))) (t nil)))) (defun lyskom-define-menu-gnu (map menus &optional specials) (let ((specials (or specials (when (current-local-map) (lyskom-menu-guess-shortcuts (current-local-map)))))) (when menus (lyskom-define-menu-gnu map (cdr menus) specials) (let ((type (car (car menus))) (symbol (car (cdr (car menus))))) (cond ((eq 'hline type) (define-key map (vector (lyskom-gensym)) '("--"))) ((eq 'menu type) (let* ((name (lyskom-get-menu-string symbol)) (submap (make-sparse-keymap name))) (define-key map (vector symbol) (cons name submap)) (lyskom-define-menu-gnu submap (car (cdr (cdr (car menus)))) specials))) ((eq 'item type) (let ((shortcut nil)) (when (assq symbol specials) (unless (lyskom-traverse key (cdr (assq symbol specials)) (unless (condition-case nil (eq (lookup-key (current-local-map) key) symbol) (error nil)) (lyskom-traverse-break t))) (setq shortcut (mapconcat (lambda (key) (if (assq key lyskom-swedish-bindings-reverse) (symbol-name (cdr (assq key lyskom-swedish-bindings-reverse))) (single-key-description key))) (car (cdr (assq symbol specials))) " ")))) (if shortcut (progn (when (memq window-system '(win32 mswindows w32)) (setq shortcut (lyskom-encode-coding-string shortcut 'iso-8859-1))) (define-key map (vector symbol) `(menu-item ,(lyskom-get-menu-string symbol) ,symbol :keys ,shortcut))) (define-key map (vector symbol) (cons (lyskom-get-menu-string symbol) symbol))))) (t (error "Menu description invalid in lyskom-define-menu"))))))) (defun lyskom-get-menu-category (menu-category) (symbol-value (cdr (assq menu-category lyskom-menu-list)))) (defun lyskom-update-menus () (lyskom-build-menus) (when (and (boundp 'lyskom-current-menu-category) lyskom-current-menu-category) (mapcar (lambda (mc) (lyskom-set-menus mc (current-local-map))) lyskom-current-menu-category))) (defun lyskom-set-menus (menu-category keymap) (lyskom-xemacs-or-gnu (lyskom-set-menus-xemacs menu-category) (lyskom-set-menus-gnu menu-category keymap))) (defun lyskom-set-menus-gnu (menu-category keymap) "Update the menus" (define-key keymap [menu-bar] (lyskom-get-menu-category menu-category)) (make-local-variable 'lyskom-current-menu-category) (if (not (boundp 'lyskom-current-menu-category)) (setq lyskom-current-menu-category (list menu-category)) (add-to-list 'lyskom-current-menu-category menu-category))) (eval-when-compile (defvar default-menubar nil)) (defun lyskom-set-menus-xemacs (menu-category) "Update the menus" (make-local-variable 'current-menubar) (make-local-variable 'lyskom-current-menu-category) (set-buffer-menubar default-menubar) (mapcar (function (lambda (menu) (add-submenu nil menu))) (lyskom-get-menu-category menu-category)) (setq lyskom-current-menu-category (list menu-category))) ;;; ;;; This function would have been completely unnecessary if Gnu Emacs ;;; didn't carry around an ancient version of popup-menu that is ;;; completely incompatible with XEmacs version of the same function. ;;; Sometimes I hate elisp. ;;; (defun lyskom-do-popup-menu (menu event) "Pop up a menu" (lyskom-xemacs-or-gnu (popup-menu menu event) (let* ((result (nreverse (x-popup-menu (or event t) (list menu))))) (cond ((null result)) ((listp (car result)) (apply (car (car result)) (cdr (car result)))) ((commandp (car result)) (call-interactively (car result))) ((functionp (car result)) (funcall (car result))) (t nil))))) (defun lyskom-background-menu (pos event) "Pop up a menu with LysKOM commands and execute the selected command." (let* ((menu lyskom-popup-menu) (result (lyskom-do-popup-menu menu event))))) ;;;;(Återse) Baklänges Addera extra kopiemottagare ;;;;Addera kommentar Addera medlem ;;;;Addera mottagare Automatsvar ;;;;Avmarkera (inlägg) Bli medlem i möte ;;;;Börja med nytt namn Endast läsa senaste ;;;;Filtrera författare Filtrera innehåll ;;;;Filtrera ärende Fjärrkontrollera automatsvar ;;;;Fjärrkontrollera avsluta Fjärrkontrollera lista meddelanden ;;;;Fjärrkontrollera radera meddelanden ;;;;Fjärrkontrollera ändra svarsmeddelande ;;;;Flytta inlägg Fotnot till inlägg ;;;;Få skäll Få uppmuntran ;;;;Gå till möte Gå till nästa möte ;;;;Hjälp Hoppa över alla kommentarer ;;;;Kasta ut en session Kommentera föregående inlägg ;;;;Kommentera inlägget Ladda ner fil ;;;;Ladda upp fil Lista (med) regexpar ;;;;Lista filarean Lista filter ;;;;Lista klienter Lista meddelanden ;;;;Lista medlemsskap Lista möten ;;;;Lista nyheter Lista personer ;;;;Lista ärenden Läsa nästa inlägg ;;;;Långsamma kommandon Markera (inlägg) ;;;;Personligt svar Personligt svar på föregående inlägg ;;;;Prioritera möten Radera inlägg ;;;;Radera meddelanden Se tiden ;;;;Skapa möte Skicka brev ;;;;Skriva ett inlägg Sluta ;;;;Snabba kommandon Spara text (på fil) ;;;;Spara variabler Status (för) möte ;;;;Status (för) person Status (för) session ;;;;Subtrahera kommentar Subtrahera mottagare ;;;;Superhoppa Sända meddelande ;;;;Sätt lapp på dörren Sätt läsnivå ;;;;Ta bort lapp på dörren Uppskjuta läsning ;;;;Uteslut medlem Utplåna ;;;;Utträda ur möte Var (är) jag ;;;;Vilka är inloggade Visa user-arean ;;;;Vänta på ett inlägg Ändra filter ;;;;Ändra livslängd Ändra lösenord ;;;;Ändra mötestyp Ändra namn ;;;;Ändra organisatör Ändra presentation ;;;;Ändra supermöte Ändra svarsmeddelande ;;;;Ändra tillåtna författare Ändra variabler ;;;;Återse alla Återse alla kommentarer ;;;;Återse alla kommentarer rekursivt Återse alla markerade ;;;;Återse det föregående kommenterade ;;;;Återse det kommenterade Återse första ;;;;Återse hoppa Återse igen ;;;;Återse inlägg Återse lista ;;;;Återse markerade Återse nästa ;;;;Återse omodifierat Återse presentation ;;;;Återse senaste Återse träd ;;;;Återse urinlägget Återstarta kom ;;;;Övergå till administratörsmod (eval-and-compile (provide 'lyskom-menus)) ;;; menus.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: slow.el,v 44.19 2004/02/27 18:55:43 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: slow.el ;;;; ;;;; This file contains the code that makes it possible to run a ;;;; long-commands mode in the lyskom-buffer. ;;;; ;;;; ================================================================ ;;;; ;;; Author: Linus Tolke ;;; Modified by: David Kågedal (defvar lyskom-slow-mode-map (make-sparse-keymap) "Mode map for the `slow' lyskom command mode.") (define-key lyskom-slow-mode-map (kbd "RET") 'kom-parse-command-and-execute) (define-key lyskom-slow-mode-map (kbd "SPC") 'kom-expand-slow-or-next-command) (define-key lyskom-slow-mode-map (kbd "C-a") 'kom-slow-start-of-line) (define-key lyskom-slow-mode-map (kbd "?") 'kom-slow-list-completions) (define-key lyskom-slow-mode-map (kbd "*") 'kom-slow-button-press) (define-key lyskom-slow-mode-map (kbd "=") 'kom-slow-menu-button-press) (define-key lyskom-slow-mode-map (kbd "TAB") 'kom-expand-slow-command-or-next-link) (define-key lyskom-slow-mode-map (kbd "M-TAB") 'kom-previous-link) (define-key lyskom-slow-mode-map (kbd "C-i") 'kom-expand-slow-command-or-next-link) (define-key lyskom-slow-mode-map (kbd "M-C-i") 'kom-previous-link) (define-key lyskom-slow-mode-map (kbd (lyskom-keys 'button2up)) 'kom-slow-click-or-yank) (define-key lyskom-slow-mode-map (kbd (lyskom-keys 'button3up)) 'kom-popup-menu) (defun lyskom-slow-start-of-line () "Move point to start of command, after LysKOM prompt." (goto-char (point-max)) (save-restriction (when (> lyskom-last-viewed (point-max)) (setq lyskom-last-viewed (point-max-marker))) (narrow-to-region lyskom-last-viewed (point-max)) (if (search-backward lyskom-current-prompt-text nil t) (forward-char (length lyskom-current-prompt-text)) (goto-char (point-max)) (beginning-of-line)) (when (looking-at "\\(\\s-+\\)") (goto-char (match-end 0))))) (defun lyskom-slow-start-of-line-pos () "Return the starting position for entry text on the current line." (save-excursion (lyskom-slow-start-of-line) (point))) (defun lyskom-get-entered-slow-command () "Get the text that the user has entered after the last prompt. Note that this function leaves point at the end of the prompt. If no text is entered, nil is returned." (lyskom-slow-start-of-line) (if (= (point) (point-max)) nil (buffer-substring (point) (point-max)))) (defun lyskom-slow-on-prompt-line (&optional where) "Return non-nil if point is on the line containing the prompt. Currently the prompt is assumed to be on the last line of the buffer." (eq (save-excursion (when where (goto-char where)) (beginning-of-line) (point)) (save-excursion (goto-char (point-max)) (beginning-of-line) (point)))) (defun kom-slow-click-or-yank (event) "Click on a LysKOM button or do the default action if after the prompt." (interactive "@e") (let ((pos (lyskom-event-closest-point event))) (if (and (lyskom-slow-on-prompt-line pos) (<= (lyskom-slow-start-of-line-pos) pos)) (let ((fn (lookup-key global-map (this-command-keys)))) (when (commandp fn) (call-interactively fn))) (kom-button-click event)))) (defun kom-slow-button-press () "Run kom-button-press unless on the prompt line." (interactive) (if (lyskom-slow-on-prompt-line) (call-interactively 'self-insert-command) (kom-button-press))) (defun kom-slow-menu-button-press () "Run kom-menu-button-press unless on the prompt line." (interactive) (if (lyskom-slow-on-prompt-line) (call-interactively 'self-insert-command) (kom-menu-button-press))) (defun kom-slow-start-of-line () "Move to the beginning of line or start of command if on the prompt line." (interactive) (if (lyskom-slow-on-prompt-line) (lyskom-slow-start-of-line) (beginning-of-line))) (defun lyskom-expand-slow-command (try-exact eager-completion) (let* ((saved-point (point-marker)) (text (lyskom-get-entered-slow-command)) (exact (and text try-exact (lyskom-complete-command text nil 'lambda))) (completes (and text (all-completions text 'lyskom-complete-command))) (command nil)) (cond ((null text) (lyskom-beep t) nil) ((null completes) (goto-char saved-point) (lyskom-insert-before-prompt (lyskom-get-string 'no-such-command)) (lyskom-beep t) nil) (exact (setq command (cons (lyskom-lookup-command-by-name (elt exact 0)) (point)))) ((= (length completes) 1) (setq command (cons (lyskom-lookup-command-by-name (car completes)) (point))) (delete-region (point) (point-max)) (insert (car completes))) ((> (length completes) 1) (let ((longest (try-completion text 'lyskom-complete-command))) (cond ((eq longest 't) (delete-region (point) (point-max)) (insert (car completes))) ((stringp longest) (delete-region (point) (point-max)) (insert longest) ;; If the completion is the same as the entered string ;; then we either add a space if there was none at the ;; end or list all possible completions *and* add a ;; space (since it has been killed). (let* ((have-space (string-match "\\s-+$" text)) (text (if have-space (substring text 0 (match-beginning 0)) text)) (longest (if (string-match "\\s-+$" longest) (substring longest 0 (match-beginning 0)) longest))) (when (lyskom-string= (lyskom-unicase longest) (lyskom-unicase text)) (if (or have-space eager-completion) (lyskom-slow-list-completions completes)) (unless (or eager-completion (eq ?\ (lyskom-char-before (point))) (insert " ")))) )) (t (signal 'lyskom-internal-error '())))))) command)) (defun kom-expand-slow-command-or-next-link () "If on the prompt line, run kom-expand-slow-command. Otherwise run kom-next-link." (interactive) (if (lyskom-slow-on-prompt-line) (call-interactively 'kom-expand-slow-command) (call-interactively 'kom-next-link))) (defun kom-expand-slow-command (&optional try-exact) "Tries to complete the command at point. If optional TRY-EXACT is non-nil, look for an exact match. If the completion was exact return a pair `(COMMAND . POINT)' where COMMAND is the command and POINT is the point where the command text starts. If the completion was not exact it returns nil." (interactive) (lyskom-expand-slow-command try-exact t)) (defun kom-expand-slow-or-next-command (&optional try-exact) "If any part of a slow command has been entered, call `kom-expand-slow-command'. Otherwise, do `kom-next-command'." (interactive) (if (save-excursion (lyskom-get-entered-slow-command)) (lyskom-expand-slow-command try-exact nil) (buffer-disable-undo) (kom-next-command))) (defun kom-parse-command-and-execute () "Reads a command from the last line in the buffer and executes it." (interactive) (let* ((text (lyskom-get-entered-slow-command)) (command (and text (lyskom-expand-slow-command t nil)))) (buffer-disable-undo) (cond ((null text) (call-interactively 'kom-next-command)) (command (delete-region (cdr command) (point-max)) (call-interactively (car command)))))) (defun lyskom-slow-list-completions (completes) "List strings in COMPLETES as possible completions for a command." (cond (completes (lyskom-format-insert-before-prompt 'command-completions (mapconcat 'identity (sort completes 'string-lessp) "\n "))) (t (lyskom-insert-before-prompt (lyskom-get-string 'no-such-command))))) (defun kom-slow-list-completions () (interactive) (save-excursion (lyskom-slow-list-completions (all-completions (or (lyskom-get-entered-slow-command) "") 'lyskom-complete-command)))) (def-kom-command kom-slow-mode () "Starts the slow-command-mode. In this mode you write commands in the main LysKOM buffer instead of using keyboard shortcuts." (interactive) (unless lyskom-slow-mode (setq lyskom-saved-read-only buffer-read-only) (setq lyskom-slow-mode t) (setq buffer-read-only nil) (use-local-map lyskom-slow-mode-map))) (def-kom-command kom-quick-mode () "Starts the quick command mode. This is the standard mode for LysKOM, where you use keyboard shortcuts for most commands, and the \"x\" prefix for all other commands." (interactive) (when lyskom-slow-mode (setq buffer-read-only lyskom-saved-read-only) (setq lyskom-slow-mode nil) (use-local-map lyskom-mode-map))) ;;;;; -*-coding: iso-8859-1;-*- ;;;; $Id: elib-string.el,v 44.2 1999/11/19 13:37:49 byers Exp $ ;;;; This file contains some miscellaneous string functions ;; Copyright (C) 1991-1995 Free Software Foundation ;; Author: Sebastian Kremer ;; Per Cederqvist ;; Inge Wallin ;; Maintainer: elib-maintainers@lysator.liu.se ;; Created: before 9 May 1991 ;; Keywords: extensions, lisp ;;;; This file is part of the GNU Emacs lisp library, Elib. ;;;; ;;;; GNU Elib is free software; you can redistribute it and/or modify ;;;; it under the terms of the GNU General Public License as published by ;;;; the Free Software Foundation; either version 2, or (at your option) ;;;; any later version. ;;;; ;;;; GNU Elib is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;;; GNU General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU General Public License ;;;; along with GNU Elib; see the file COPYING. If not, write to ;;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;;;; Boston, MA 02111-1307, USA ;;;; ;;;; Author: Sebastian Kremer ;;;; sk@thp.Uni-Koeln.DE ;;;; ;;; Commentary: ;;; ;;; This file is part of the elisp library Elib. ;;; It implements simple generic string functions for use in other ;;; elisp code: replace regexps in strings, split strings on regexps. ;;; ;;; NOTE NOTE NOTE NOTE NOTE ;;; ;;; This package has been slightly modified in the following section: (defvar newtext) (defvar string) ;;; Code: (provide 'string) ;; This function is a near-equivalent of the elisp function replace-match ;; which work on strings instead of a buffer. The FIXEDCASE parameter ;; of replace-match is not implemented. (defun string-replace-match (regexp string newtext &optional literal global) "Replace first match of REGEXP in STRING with NEWTEXT. If no match is found, nil is returned instead of the new string. Optional arg LITERAL non-nil means to take NEWTEXT literally. If LITERAL is nil, character `\\' is the start of one of the following sequences: \\\\ will be replaced by a single \\. \\& will be replaced by the text which matched the regexp. \\N where N is a number and 1 <= N <= 9, will be replaced by the Nth subexpression in REGEXP. Subexpressions are grouped inside \\( \\). Optional arg GLOBAL means to replace all matches instead of only the first." (let ((data (match-data))) (unwind-protect (if global (let ((result "") (start 0) matchbeginning matchend) (while (string-match regexp string start) (setq matchbeginning (match-beginning 0) matchend (match-end 0) result (concat result (substring string start matchbeginning) (if literal newtext (elib-string-expand-newtext))) start matchend)) (if matchbeginning ; matched at least once (concat result (substring string start)) nil)) ;; not GLOBAL (if (not (string-match regexp string 0)) nil (concat (substring string 0 (match-beginning 0)) (if literal newtext (elib-string-expand-newtext)) (substring string (match-end 0))))) (store-match-data data)))) (defun elib-string-expand-newtext () ;; Expand \& and \1..\9 (referring to STRING) in NEWTEXT. ;; Uses match data and fluid vars `newtext', `string'. ;; Note that in Emacs 18 match data are clipped to current buffer ;; size...so the buffer should better not be smaller than STRING. (let ((pos 0) (len (length newtext)) (expanded-newtext "")) (while (< pos len) (setq expanded-newtext (concat expanded-newtext (let ((c (aref newtext pos))) (if (= ?\\ c) (cond ((= ?\& (setq c (aref newtext (setq pos (1+ pos))))) (substring string (match-beginning 0) (match-end 0))) ((and (>= c ?1) (<= c ?9)) ;; return empty string if N'th ;; sub-regexp did not match: (let ((n (- c ?0))) (if (match-beginning n) (substring string (match-beginning n) (match-end n)) ""))) (t (char-to-string c))) (char-to-string c))))) (setq pos (1+ pos))) expanded-newtext)) (defun string-split (pattern string &optional limit) "Splitting on regexp PATTERN, turn string STRING into a list of substrings. Optional third arg LIMIT (>= 1) is a limit to the length of the resulting list." (let ((data (match-data))) (unwind-protect (let* ((start (string-match pattern string)) (result (list (substring string 0 start))) (count 1) (end (if start (match-end 0)))) (if end ; else nothing left (while (and (or (not (integerp limit)) (< count limit)) (string-match pattern string end)) (setq start (match-beginning 0) count (1+ count) result (cons (substring string end start) result) end (match-end 0) start end))) (if (and (or (not (integerp limit)) (< count limit)) end) ; else nothing left (setq result (cons (substring string end) result))) (nreverse result)) (store-match-data data)))) ;;; string.el ends here ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: option-edit.el,v 44.114 2005/01/12 11:42:13 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: option-edit.el ;;;; ;;;; Customization for LysKOM ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: option-edit.el,v 44.114 2005/01/12 11:42:13 _cvs_pont_lyskomelisp Exp $\n")) (lyskom-external-function widget-default-format-handler) (lyskom-external-function popup-mode-menu) ;;; ====================================================================== ;;; Require Per Abrahamsens widget package, version 0.991 or later. ;;; ;;; ====================================================================== ;;; Global variables (defvar lyskom-widgets nil "List of widgets in the customize buffer.") (defvar lyskom-customize-buffer-format '("\n" (lyskom bold centered) "\n\n" lyskom-doc "\n\n" [kom-customize-format] "\n\n" section (look-and-feel-misc bold centered) section "\n" [kom-default-language] [kom-show-namedays] [kom-show-week-number] [kom-print-relative-dates] [kom-print-seconds-in-time-strings] "\n" [kom-extended-status-information] [kom-auto-list-faqs] [kom-auto-review-faqs] "\n" [kom-auto-confirm-new-conferences] "\n" [kom-idle-hide] [kom-relogin-behaviour] [kom-relogin-inhibit-commands] [kom-remember-password] [kom-show-where-and-what] [kom-show-since-and-when] "\n" [kom-highlight-conferences] [kom-friends] [kom-morons] "\n" [kom-show-unread-in-frame-title] [kom-unread-mode-line-type] [kom-presence-messages-in-echo-area] [kom-presence-messages-in-buffer] "\n" [kom-text-no-prompts] [kom-keyboard-menu-immediate-selection] [kom-page-before-command] [kom-deferred-printing] [kom-max-buffer-size] [kom-trim-buffer-minimum] [kom-bury-buffers] [kom-keep-alive-interval] [kom-show-sync-messages] "\n" [kom-agree-text] [kom-mercial] "\n" [kom-user-prompt-format] [kom-user-prompt-format-executing] [kom-anonymous-prompt-format] [kom-anonymous-prompt-format-executing] [kom-enabled-prompt-format] [kom-enabled-prompt-format-executing] "\n\n" section (window-locations bold centered) section "\n" (windows-where bold centered) "\n" windows-doc "\n\n" [kom-customize-in-window] [kom-edit-filters-in-window] [kom-prioritize-in-window] [kom-list-membership-in-window] [kom-write-texts-in-window] [kom-view-commented-in-window] [kom-personal-messages-in-window] "\n\n" section (predefined-fonts bold centered) section "\n" [kom-active-face] [kom-url-face] [kom-me-face] [kom-highlight-face] [kom-subject-face] [kom-text-no-face] [kom-friends-face] [kom-morons-face] [kom-presence-face] [kom-first-line-face] [kom-warning-face] [kom-mark-face] [kom-dim-face] [kom-text-body-face] [kom-dashed-lines-face] [kom-async-text-body-face] [kom-async-dashed-lines-face] "\n\n" section (other-fonts bold centered) section "\n" [kom-active-highlight-face] [kom-active-strikethrough-face] "\n\n" section (audio-cues bold centered) section "\n" [kom-audio-player] "\n" (audio-cues-when bold centered) "\n" audio-cues-doc "\n\n" [kom-ding-on-priority-break] [kom-ding-on-new-letter] [kom-ding-on-wait-done] [kom-ding-on-no-subject] [kom-ding-on-common-messages] [kom-ding-on-group-messages] [kom-ding-on-personal-messages] "\n" [kom-silent-ansaphone] "\n\n" section (reading bold centered) section "\n" [kom-default-session-priority] [kom-print-number-of-unread-on-entrance] [kom-allow-incompleteness] [kom-permissive-completion] [kom-complete-numbers-before-names] [kom-continuous-scrolling] [kom-inhibit-typeahead] [kom-confirm-add-recipients] "\n" [kom-higher-priority-breaks] [kom-review-priority] [kom-server-priority] [kom-server-priority-breaks] [kom-session-nickname] "\n" [kom-read-depth-first] [kom-reading-puts-comments-in-pointers-last] [kom-show-footnotes-immediately] [kom-follow-comments-outside-membership] [kom-follow-attachments] [kom-mark-read-texts-as-read-in-new-recipient] [kom-created-texts-are-read] [kom-created-texts-are-saved] [kom-review-uses-cache] [kom-review-marks-texts-as-read] "\n" [kom-saved-file-name] [kom-default-mark] [kom-symbolic-marks-alist] [kom-membership-default-message-flag] [kom-membership-default-priority] [kom-membership-default-placement] [kom-unsubscribe-makes-passive] [kom-postpone-default] "\n" [kom-autowrap] [kom-autowrap-timeout] [kom-show-author-at-end] [kom-show-creating-software] [kom-show-imported-importer] [kom-show-imported-external-recipients] [kom-show-imported-envelope-sender] [kom-show-imported-message-id] [kom-text-properties] [kom-fontify-text] [kom-smileys] [kom-w3-simplify-body] [kom-format-html-authors] [kom-format-show-images] "\n" [kom-max-overlays] [kom-highlight-first-line] [kom-highlight-dashed-lines] [kom-highlight-text-body] [kom-async-highlight-dashed-lines] [kom-async-highlight-text-body] "\n" [kom-dashed-lines] [kom-long-lines] [kom-text-footer-format] [kom-text-header-dash-length] [kom-text-footer-dash-length] "\n" [kom-truncate-threshold] [kom-truncate-show-lines] "\n" [kom-ignore-message-senders] [kom-ignore-message-recipients] [kom-show-personal-message-date] [kom-filter-outgoing-messages] "\n\n" section (writing bold centered) section "\n" [kom-edit-hide-add-button] [kom-cite-string] [kom-ispell-dictionary] "\n" sending-doc "\n\n" [kom-confirm-multiple-recipients] [kom-check-commented-author-membership] [kom-dont-check-commented-authors] [kom-check-for-new-comments] "\n\n" section (urls bold centered) section "\n" [kom-text-links] [kom-url-transformation-rules] [kom-url-viewer-preferences] [kom-windows-browser-command] [kom-mosaic-command] [kom-netscape-command] [kom-netscape-variant] [kom-galeon-command] [kom-lynx-terminal] [kom-lynx-xterm-command] [kom-lynx-terminal-command] "\n\n" section (personal-messages bold centered) section "\n" [kom-show-personal-messages-in-buffer] [kom-pop-personal-messages] [kom-default-message-recipient] "\n" (automatic-replies bold centered) "\n" [kom-ansaphone-record-messages] [kom-ansaphone-show-messages] "\n" [kom-ansaphone-default-reply] "\n" [kom-ansaphone-replies] "\n\n" section (remote-control bold centered) section "\n" [kom-remote-control] [kom-self-control] "\n" [kom-remote-controllers] "\n\n" section (hooks bold centered) section "\n" [kom-login-hook] [kom-do-when-done] )) ;;; ====================================================================== ;;; User functions ;;; (defun lyskom-customize-apply () "Set the variables in the LysKOM buffer according to their values in the customize buffer but do not save them to the server." (interactive) (let ((tmp lyskom-widgets)) (save-excursion (set-buffer lyskom-buffer) (when (listp kom-dont-read-saved-variables) (setq kom-dont-read-saved-variables nil)) (while tmp (set (car (car tmp)) (widget-value (cdr (car tmp)))) (when (not (widget-value (widget-get (cdr (car tmp)) ':lyskom-storage-widget))) (set-default (car (car tmp)) (widget-value (cdr (car tmp)))) (when (and (listp kom-dont-read-saved-variables) (or (memq (car (car tmp)) lyskom-elisp-variables) (lyskom-flag-global-variable-from-elisp (car (car tmp))))) (setq kom-dont-read-saved-variables (cons (car (car tmp)) kom-dont-read-saved-variables)))) (setq tmp (cdr tmp)))))) (eval-when-compile (defvar save-options-init-file nil)) (defun lyskom-customize-send () "Save variables to the server" (save-excursion (set-buffer lyskom-buffer) (lyskom-save-options (current-buffer) (lyskom-get-string 'saving-settings) (lyskom-get-string 'saving-settings-done) (lyskom-get-string 'could-not-save-options)) (let ((var-list nil)) (mapcar (function (lambda (e) (when (and (vectorp e) (symbolp (elt e 0)) (or (and (not (memq (elt e 0) lyskom-elisp-variables)) (not (lyskom-flag-global-variable-from-elisp (elt e 0)))) (memq (elt e 0) kom-dont-read-saved-variables)) (boundp (elt e 0))) (setq var-list (cons (cons (elt e 0) (symbol-value (elt e 0))) var-list))))) lyskom-customize-buffer-format) (let* ((actual-save-options-init-file (or (and (boundp 'save-options-init-file) save-options-init-file) (and (not (equal user-init-file "")) user-init-file) (and (eq system-type 'ms-dos) (concat "~" (user-login-name) "/_emacs")) (concat "~" (user-login-name) "/.emacs"))) (init-output-buffer (find-file-noselect actual-save-options-init-file)) (init-output-marker nil)) (save-excursion (set-buffer init-output-buffer) ;; ;; Find and delete the previously saved data, and position to write. ;; (goto-char (point-min)) (if (re-search-forward "^;;; LysKOM Settings *\n" nil 'move) (let ((p (match-beginning 0))) (goto-char p) (or (re-search-forward "^;;; End of LysKOM Settings *\\(\n\\|\\'\\)" nil t) (error "can't find END of saved state in .emacs")) (delete-region p (match-end 0))) (goto-char (point-max)) (insert "\n")) (setq init-output-marker (point-marker))) (let ((standard-output init-output-marker)) (princ ";;; LysKOM Settings\n") (princ ";;; =====================\n") (mapcar (lambda (x) (princ (format "(setq-default %S %s%S)\n" (car x) (cond ((eq (cdr x) t) "") ((null (cdr x)) "") ((symbolp (cdr x)) "'") ((listp (cdr x)) "'") (t "")) (cdr x)))) var-list) (princ ";;; ============================\n") (princ ";;; End of LysKOM Settings\n")) (set-marker init-output-marker nil) (save-excursion (set-buffer init-output-buffer) (save-buffer)) )))) (defun lyskom-customize-save () "Apply changes and save them to the server." (interactive) (lyskom-customize-apply) (lyskom-customize-send)) (defun lyskom-customize-quit () "Quit the customize buffer without saving" (interactive) (let ((buf (current-buffer))) (lyskom-undisplay-buffer buf) (kill-buffer buf))) (defun lyskom-customize-save-and-quit () "Save and quit the customize buffer" (interactive) (lyskom-customize-apply) (lyskom-customize-send) (lyskom-customize-quit)) (defun lyskom-customize-help () (interactive) (message (lyskom-get-string 'customize-help))) (defun lyskom-widget-click (event) (interactive "e") (let ((pos (lyskom-event-point event))) (if (and pos (widget-at pos)) (widget-button-click event) (popup-mode-menu)))) (defun lyskom-customize-mode () "Major mode for editing LysKOM settings. See the top of the buffer for localized help. These commands work outside editable text fields. \\[lyskom-customize-save-and-quit] to save and quit, \\[lyskom-customize-save-and-quit] to save and quit, \\[lyskom-customize-save] to save without quitting, \\[lyskom-customize-quit] to quit without saving. \\[widget-forward] moves to the next setting \\[widget-button-press] changes the value Press C-h m for a complete list of commands. Documentation: [?] Show documentation [!] Hide documentation Lists etc. : [INS] Add a line [DEL] Remove a line [*] Modify If the box before the name of the setting is selected, the setting will be saved in the server. Otherwise it will be saved in your .emacs. Click prompts with the middle mouse button to change values and bring up menus. All key bindings: \\{lyskom-customize-map} " (kill-all-local-variables) (use-local-map lyskom-customize-map) (make-local-variable 'lyskom-widgets) (setq lyskom-widgets nil) (let ((inhibit-read-only t)) (erase-buffer)) (condition-case nil (lyskom-copy-face kom-active-face 'widget-button-face) (error nil)) (mapcar 'lyskom-custom-insert lyskom-customize-buffer-format) (widget-setup) (mapcar (function (lambda (variable) (widget-value-set (cdr variable) (save-excursion (set-buffer lyskom-buffer) (symbol-value (car variable)))))) lyskom-widgets) (widget-setup) (setq mode-name "LysKOM Settings") (setq major-mode 'lyskom-customize-mode) ) (defun kom-customize () "Open the customize buffer" (interactive) (let ((buf (lyskom-get-buffer-create 'customize (lyskom-format (lyskom-custom-string 'buffer-name) lyskom-server-name) t))) (unwind-protect (progn (lyskom-start-of-command 'kom-customize) (sit-for 0) (save-excursion (set-buffer buf) (lyskom-customize-mode)) (lyskom-display-buffer buf)) (save-excursion (set-buffer lyskom-buffer) (lyskom-end-of-command))) (goto-char (point-min)))) ;;; ============================================================ ;;; Non-user functions ;;; (defun lyskom-custom-insert (w) (cond ((symbolp w) (widget-insert (substitute-command-keys (lyskom-custom-string w)))) ((listp w) (let ((start (point)) (end nil) (inhibit-read-only t)) (widget-insert (lyskom-custom-string (car w))) (setq end (point)) (mapcar (function (lambda (fn) (funcall (intern (concat "lyskom-custom-insert-" (symbol-name fn))) start end))) (cdr w)))) ((stringp w) (widget-insert w)) ((vectorp w) (setq lyskom-widgets (cons (cons (aref w 0) (lyskom-create-widget (aref w 0))) lyskom-widgets))))) ;;UNUSED: lyskom-custom-insert-bold (defun lyskom-custom-insert-bold (s e) (add-text-properties s e (list 'face 'bold 'end-closed nil))) ;;UNUSED: lyskom-custom-insert-centered (defun lyskom-custom-insert-centered (s e) (save-excursion (goto-char s) (center-line 1))) (defun lyskom-custom-get-value (var) (save-excursion (set-buffer lyskom-buffer) (symbol-value var))) (defun lyskom-custom-string (s) (lyskom-get-string s 'lyskom-custom-strings)) (defvar lyskom-custom-variables-missing '(kom-permanent-filter-list kom-quit-hook lyskom-last-known-conf-no lyskom-last-known-pers-no kom-presence-messages kom-dont-complain-about-missing-presentation lyskom-settings-version) "List of user variables not in lyskom-custom-variables.") (defvar lyskom-custom-variables '( (kom-max-overlays (choice ((number nil :tag limited-number :format "%[%t%] (%v)") (const (unlimited-number nil))))) (kom-highlight-first-line (toggle (on off))) (kom-highlight-dashed-lines (toggle (on off))) (kom-highlight-text-body (toggle (on off))) (kom-async-highlight-dashed-lines (toggle (on off))) (kom-async-highlight-text-body (toggle (on off))) (kom-personal-messages-in-window (open-window)) (kom-write-texts-in-window (open-window)) (kom-list-membership-in-window (open-window)) (kom-edit-filters-in-window (open-window)) (kom-prioritize-in-window (open-window)) (kom-customize-in-window (open-window)) (kom-view-commented-in-window (open-window)) (kom-edit-filters-in-window (open-window)) (kom-list-membership-in-window (open-window)) (kom-customize-format (choice ((const (long-format long)) (const (short-format short))))) (kom-default-language (repeat (language-choice nil :format "%[%t%] %v\n"))) (kom-user-prompt-format (string)) (kom-user-prompt-format-executing (string)) (kom-anonymous-prompt-format (string)) (kom-anonymous-prompt-format-executing (string)) (kom-enabled-prompt-format (string)) (kom-enabled-prompt-format-executing (string)) (kom-cite-string (string)) (kom-created-texts-are-read (toggle (yes no))) (kom-mark-read-texts-as-read-in-new-recipient (toggle (yes no))) (kom-review-uses-cache (toggle (yes no))) (kom-review-marks-texts-as-read (toggle (yes no))) (kom-created-texts-are-saved (choice ((const (no nil)) (file nil :tag to-file)))) (kom-default-mark (choice ((number (0 255) :tag selected-mark :format "%[%t%] (%v)" :size 0) (const (ask nil))))) (kom-symbolic-marks-alist (repeat (mark-association nil :tag symbolic-mark-association :mark-key-prompt symbolic-mark-name :mark-value-prompt mark-type-to-assoc) :indent 4)) (kom-reading-puts-comments-in-pointers-last (toggle (after before))) (kom-autowrap (choice ((const (on t)) (const (off nil)) (number nil :tag max-text-length)))) (kom-autowrap-timeout (choice ((const (no-timeout nil)) (number nil :tag autowrap-timeout)))) (kom-auto-list-faqs (toggle (on off))) (kom-auto-review-faqs (toggle (on off))) (kom-dashed-lines (toggle (on off))) (kom-show-author-at-end (toggle (on off))) (kom-truncate-threshold (choice ((const (off nil)) (number nil :tag truncate-threshold-lines)))) (kom-truncate-show-lines (number nil)) (kom-print-number-of-unread-on-entrance (toggle (yes no))) (kom-presence-messages-in-echo-area (choice ((const (on t)) (const (friends friends)) (repeat (person nil :tag name) :indent 4 :tag some-persons :menu-tag some-persons)))) (kom-presence-messages-in-buffer (choice ((const (on t)) (const (friends friends)) (repeat (person nil :tag name) :indent 4 :tag some-persons :menu-tag some-persons)))) (kom-show-where-and-what (toggle (yes no))) (kom-show-since-and-when (toggle (yes no))) (kom-remember-password (toggle (yes no))) (kom-idle-hide (number)) (kom-show-footnotes-immediately (toggle (yes no))) (kom-follow-comments-outside-membership (toggle (yes no))) (kom-read-depth-first (toggle (depth-first time-order))) (kom-continuous-scrolling (toggle (on off))) (kom-deferred-printing (toggle (on off))) (kom-higher-priority-breaks (choice ((const (express-break express)) (const (break t)) (const (no-break nil))))) (kom-server-priority (number)) (kom-server-priority-breaks (choice ((const (express-server-break express)) (const (express-server-letters-break express-letters)) (const (server-break t)) (const (letters-server-break letters)) (const (after-conf-server-break after-conf)) (const (after-conf-letters-server-break after-conf-letters)) (const (when-done-server-break when-done)) (const (no-server-break nil))))) (kom-session-nickname (choice ((const (automatic-session-name nil)) (string nil :tag given-session-name :help-echo select-buffer)))) (kom-relogin-inhibit-commands (repeat (command nil :tag command) :indent 4)) (kom-login-hook (repeat (command nil :tag command) :indent 4)) (kom-do-when-done (repeat (choice ((command nil :tag command) (kbd-macro nil :tag kbd-macro)) :tag execute :help-echo select-what-to-execute :format "%[%t%] %v") :indent 4)) (kom-page-before-command (choice ((const (page-none nil)) (const (page-all t)) (repeat (command nil :tag command) :indent 4 :tag page-some :menu-tag page-some :format "%[%t%] %v" :value (kom-view-next-text))) :format "%[%t%] %v")) (kom-permissive-completion (noggle (on off))) (kom-membership-default-priority (choice ((const (ask-every-time ask)) (const (ask-every-time nil)) (number (0 255) :tag fixed-priority :help-echo select-priority :format "%[%t%] (%v)" :size 0)))) (kom-membership-default-message-flag (choice ((const (ask-every-time ask)) (const (yes t)) (const (no nil))))) (kom-show-personal-messages-in-buffer (choice ((const (messages-in-lyskom-buffer t)) (const (discard-messages nil)) (string nil :tag in-named-buffer :help-echo select-buffer)))) (kom-pop-personal-messages (choice ((const (yes t)) (const (yes-dont-pop yes)) (const (no nil))))) (kom-ding-on-new-letter (ding)) (kom-ding-on-priority-break (ding)) (kom-ding-on-wait-done (ding)) (kom-ding-on-common-messages (ding)) (kom-ding-on-group-messages (ding)) (kom-ding-on-personal-messages (ding)) (kom-ding-on-no-subject (ding)) (kom-audio-player (file)) (kom-default-message-recipient (choice ((const (everybody-rcpt everybody)) (const (group-rcpt group)) (const (sender-rcpt sender)) (const (last-recipient-recpt last-recipient))))) (kom-filter-outgoing-messages (noggle (yes no))) (kom-highlight-conferences (repeat (cons ((choice ((const (morons kom-morons)) (const (friends kom-friends)) (const (me lyskom-pers-no)) (const (i-am-supervisor lyskom-highlight-i-am-supervisor)) (const (has-no-presentation lyskom-highlight-has-no-presentation)) (repeat (person nil :tag name) :indent 12 :tag highlight-conflist :lyskom-predicate (pers conf) :menu-tag highlight-conflist) ) :tag highlight-conferences :format "%[%t%] %v\n" ) (face (kom-active-face kom-active-highlight-face kom-active-strikethrough-face kom-friends-face kom-morons-face kom-me-face) :tag highlight-face)) :format "%v" ) )) (kom-friends (repeat (person nil :tag name) :indent 4)) (kom-morons (repeat (person nil :tag name) :indent 4)) (kom-url-viewer-preferences (repeat (url-viewer nil :tag viewer-program) :indent 4)) (kom-windows-browser-command (file)) (kom-mosaic-command (choice ((file nil :tag ext-simple-command :format "%[%t:%] %v\n") (repeat (string nil :tag ext-complex-component :format "%[%t:%] %v\n") :tag ext-complex-command :menu-tag ext-complex-command)))) (kom-netscape-command (choice ((file nil :tag ext-simple-command :format "%[%t:%] %v\n") (repeat (string nil :tag ext-complex-component :format "%[%t:%] %v\n") :tag ext-complex-command :menu-tag ext-complex-command)))) (kom-galeon-command (choice ((file nil :tag ext-simple-command :format "%[%t:%] %v\n") (repeat (string nil :tag ext-complex-component :format "%[%t:%] %v\n") :tag ext-complex-command :menu-tag ext-complex-command)))) (kom-lynx-terminal (choice ((const (lynx-xterm xterm)) (const (lynx-emacs terminal))))) (kom-lynx-terminal-command (file)) (kom-lynx-xterm-command (choice ((file nil :tag ext-simple-command :format "%[%t:%] %v\n") (repeat (string nil :tag ext-complex-component :format "%[%t:%] %v\n") :tag ext-complex-command :menu-tag ext-complex-command)))) (kom-confirm-multiple-recipients (choice ((const (dont-check nil)) (const (check-before-open before)) (const (check-before-send after) :match (lambda (w v) (and v (not (eq v 'before)))))))) (kom-check-commented-author-membership (toggle (yes no))) (kom-check-for-new-comments (toggle (yes no))) (kom-inhibit-typeahead (noggle (yes no))) (kom-max-buffer-size (choice ((const (no-size-limit nil)) (number nil :tag max-size-in-bytes :help-echo select-buffer-size)))) (kom-ansaphone-record-messages (toggle (yes no))) (kom-ansaphone-show-messages (toggle (yes no))) (kom-ansaphone-default-reply (string nil :format "%[%t%]\n%v")) (kom-remote-control (toggle (on off))) (kom-remote-controllers (repeat (person nil :tag name) :indent 4)) (kom-self-control (toggle (yes no))) (kom-ispell-dictionary (ispell-dictionary)) (kom-show-namedays (choice ((const (off nil)) (const (default-namedays t)) (repeat (nameday nil :format "%[%t%]: `%v'\n" :tag specific-namedays) :tag several-name-lists :menu-tag several-name-lists :indent 4) (nameday nil :tag specific-namedays)))) (kom-show-week-number (toggle (on off))) (kom-relogin-behaviour (choice ((const (off nil)) (const (ask ask)) (const (on t))))) (kom-membership-default-placement (choice ((const (last last)) (const (first first)) (number nil :tag specific-placement )))) (kom-show-imported-importer (toggle (on off))) (kom-show-imported-envelope-sender (toggle (on off))) (kom-show-imported-external-recipients (toggle (on off))) (kom-show-imported-message-id (toggle (on off))) (kom-agree-text (choice ((string nil :tag a-string) (repeat (string nil :tag a-string :format "%[%t%] `%v'\n") :indent 4 :tag some-string :menu-tag some-string)))) (kom-silent-ansaphone (noggle (on off))) (kom-default-session-priority (choice ((const (unspecified nil)) (number nil :tag priority)))) (kom-unsubscribe-makes-passive (toggle (on off))) (kom-review-priority (choice ((const (same-as-conf nil)) (number nil :tag fixed-priority)))) (kom-show-creating-software (toggle (on off))) (kom-text-footer-format (choice ((const (default-format nil)) (string nil :tag custom-format)))) (kom-long-lines (toggle (on off))) (kom-postpone-default (number)) (kom-allow-incompleteness (toggle (on off))) (kom-smileys (toggle (on off))) (kom-ignore-message-senders (repeat (person nil :tag name) :indent 4)) (kom-ignore-message-recipients (repeat (person nil :tag name :lyskom-predicate (pers conf)) :indent 4)) (kom-text-header-dash-length (number)) (kom-text-footer-dash-length (number)) (kom-show-personal-message-date (toggle (on off))) (kom-mercial (string)) (kom-w3-simplify-body (toggle (on off))) (kom-format-html-authors (repeat (cons ((choice ((person nil :tag some-person :lyskom-predicate (pers)) (const (all-others t) :format "%t\n")) :format "%[%v%]") (toggle (yes no) :tag format-html))))) (kom-format-show-images (toggle (on off))) (kom-bury-buffers (toggle (on off))) (kom-ansaphone-replies (ansaphone)) (kom-complete-numbers-before-names (toggle (on off))) (kom-keep-alive-interval (number)) (kom-text-no-prompts (repeat (cons ((command nil :tag command :format "%[%t%]: %v") (toggle (yes no) :tag prompt-for-text-no :format "%[%t%]: %v") )))) (kom-saved-file-name (file)) (kom-follow-attachments (toggle (yes no))) (kom-show-unread-in-frame-title (toggle (yes no))) (kom-unread-mode-line-type (choice ((const (simple-unread-mode-line nil)) (const (explicit-unread-mode-line t))))) (kom-confirm-add-recipients (toggle (yes no))) (kom-trim-buffer-minimum (number)) (kom-dont-check-commented-authors (repeat (person nil :tag name) :indent 4)) (kom-print-relative-dates (toggle (yes no))) (kom-print-seconds-in-time-strings (toggle (yes no))) (kom-extended-status-information (choice ((const (yes t)) (repeat (cons ((choice ((const (extended-conf-info server)) (const (extended-pers-info pers)) (const (extended-server-info server)) (const (extended-read-faq-info read-faq)) (const (extended-statistics-info raw-server-stats)) (const (extended-all-other-info t)) ) :tag extended-info-type :format "%[%t%] %v ") (toggle (yes no) :tag extended-info-show))) :tag specific-extended-info :menu-tag specific-extended-info)))) (kom-edit-hide-add-button (noggle (yes no))) (kom-keyboard-menu-immediate-selection (noggle (yes no))) (kom-url-transformation-rules (repeat (cons ((string nil :tag url-transform-regexp) (string nil :tag url-transform-newtext))))) (kom-text-links (repeat (cons ((choice ((person nil :tag link-specific-rcpt :lyskom-predicate (pers conf)) (const (all-conferences t))) :tag link-pattern-for :format "%[%t%]: %v") (repeat (list ((string nil :tag link-pattern :format "%[%t%]: %v\n") (string nil :tag link-replace :format "%[%t%]: %v\n") (number (0 9) :tag link-highlight-match :format "%[%t%]: %v\n") (toggle (yes no) :tag link-fold-case :format "%[%t%]: %v")) ) :indent 8 :tag "") )) :indent 4)) (kom-url-face (face)) (kom-text-no-face (face)) (kom-active-face (face)) (kom-active-highlight-face (face)) (kom-active-strikethrough-face (face)) (kom-highlight-face (face)) (kom-me-face (face)) (kom-friends-face (face)) (kom-morons-face (face)) (kom-subject-face (face)) (kom-presence-face (face)) (kom-first-line-face (face)) (kom-warning-face (face)) (kom-mark-face (face)) (kom-dim-face (face)) (kom-text-body-face (face t)) (kom-dashed-lines-face (face t)) (kom-async-text-body-face (face t)) (kom-async-dashed-lines-face (face t)) (kom-show-sync-messages (toggle (yes no))) (kom-netscape-variant (choice ((const (default-netscape nil)) (const (new-window-netscape new-window)) (const (new-tab-netscape new-tab))))) (kom-auto-confirm-new-conferences (toggle (yes no))) (kom-text-properties (toggle (yes no))) (kom-fontify-text (toggle (yes no))) )) (defvar lyskom-widget-functions '((toggle . lyskom-toggle-widget) (noggle . lyskom-toggle-widget-inverse) (ding . lyskom-ding-widget) (choice . lyskom-choice-widget) (string . lyskom-string-widget) (number . lyskom-number-widget) (const . lyskom-item-widget) (repeat . lyskom-repeat-widget) (cons . lyskom-cons-widget) (list . lyskom-list-widget) (face . lyskom-face-widget) (nameday . lyskom-nameday-widget) (kbd-macro . lyskom-kbd-macro-widget) (url-viewer . lyskom-url-viewer-widget) (ispell-dictionary . lyskom-ispell-dictionary-widget) (open-window . lyskom-open-window-widget) (command . lyskom-command-widget) (person . lyskom-person-widget) (language-choice . lyskom-language-widget) (file . lyskom-file-widget) (ext-command . lyskom-external-command-widget) (ansaphone . lyskom-ansaphone-reply-widget) (mark-association . lyskom-mark-association-widget) )) (defun lyskom-make-menu-tag (str) "Make a menu tag from the string STR." (if (string-match "\\(.*\\):\\s-*" str) (match-string 1 str) str)) (defun lyskom-create-widget (variable) (let* ((el (assq variable lyskom-custom-variables)) (dummy (or el (error "Unknown variable: %S" variable))) (spec (lyskom-widget-convert-specification (car (cdr el)) variable)) (tag-sym (intern (concat (symbol-name variable) "-tag"))) (doc-sym (intern (concat (symbol-name variable) "-doc"))) (help-sym (intern (concat (symbol-name variable) "-help"))) (value (save-excursion (set-buffer lyskom-buffer) (symbol-value variable))) (storage-widget nil)) (lyskom-ignore value help-sym dummy) ; Are they ever used? (setq storage-widget (prog1 (widget-create 'checkbox ':value (and (not (memq variable kom-dont-read-saved-variables)) (or (memq variable lyskom-elisp-variables) (lyskom-flag-global-variable-from-elisp variable))) ':args (list variable) ':format "%[%v%]" ':help-echo (lyskom-custom-string 'variable-type-help)) (widget-insert " "))) (setq spec (cons (car spec) (append (list ':tag (lyskom-custom-string tag-sym) ':menu-tag (lyskom-make-menu-tag (lyskom-custom-string tag-sym)) ':value (lyskom-custom-get-value variable) ':help-echo (lyskom-format (lyskom-custom-string 'default-help-echo) (symbol-name variable)) ':lyskom-storage-widget storage-widget ) (cdr spec)))) (let ((widget (apply 'widget-create spec))) (condition-case nil (progn (if (string= "" (lyskom-custom-string doc-sym)) (progn (widget-insert (lyskom-format " %#1@(%#2s)" `(face ,kom-dim-face) (symbol-name variable))) (widget-insert "\n")) (widget-insert " ") (widget-create 'lyskom-widget-help ':value (lyskom-default-value 'kom-customize-format) ':help-echo (if (eq (lyskom-default-value 'kom-customize-format) 'long) (lyskom-custom-string 'hide-doc) (lyskom-custom-string 'show-doc)) ':args (list (list 'long "\n%s\n\n" (lyskom-custom-string doc-sym) (lyskom-custom-string 'hide-doc) "-") (list 'short "%s" "" (lyskom-custom-string 'show-doc) "?")) ':format (lyskom-format "%%[[%%T]%%] %[%#1@(%#2s)%]\n%%D" `(face ,kom-dim-face) (symbol-name variable))))) (error (widget-insert "\n"))) widget))) (defun lyskom-widget-convert-specification (spec var) "Convert a LysKOM widget specification to something widget-create accepts" (let ((convertfn (assq (car spec) lyskom-widget-functions))) (if (null convertfn) (error "Unknown widget type: %S" spec)) (nconc (funcall (cdr convertfn) (car spec) (car (cdr spec)) (cdr (cdr spec)) var) (lyskom-widget-convert-props spec)))) (defun lyskom-widget-convert-props (spec) "Convert widget properties to a format that widget-create likes" (let ((propl (nthcdr 2 spec)) (result)) (if (/= 0 (% (length propl) 2)) (error "Widget property list has odd length: %S" spec)) (while propl (setq result (cons (car propl) result)) (setq propl (cdr propl)) (setq result (cons (cond ((symbolp (car propl)) (cond ((eq (car propl) t) t) ((eq (car propl) nil) nil) (t (lyskom-custom-string (car propl))))) ((and (consp (car propl)) (eq 'quote (car (car propl)))) (car (cdr (car propl)))) (t (car propl))) result)) (setq propl (cdr propl))) (nreverse result))) (defun lyskom-build-simple-widget-spec (type defaults propl) (let (new-props) (while defaults (unless (plist-member propl (car defaults)) (setq new-props (cons (car defaults) (cons (car (cdr defaults)) new-props)))) (setq defaults (cdr (cdr defaults)))) (cons type new-props))) (defun lyskom-file-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'file '(:format "%[%t%] %v" :size 0) propl)) (defun lyskom-person-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'lyskom-name nil propl)) (defun lyskom-mark-association-widget (type &optional args propl ar) (lyskom-build-simple-widget-spec 'lyskom-mark-association nil propl)) (defun lyskom-command-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'lyskom-command nil propl)) (defun lyskom-kbd-macro-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'lyskom-kbd-macro (list ':macro-buffer lyskom-buffer) propl)) (defun lyskom-item-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'item (list ':format "%t" ':tag (lyskom-custom-string (elt args 0)) ':value (elt args 1)) propl)) (defun lyskom-language-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':format "%[%t%] %v" ':case-fold t ':tag (lyskom-custom-string 'language) ':args (mapcar (function (lambda (x) (list 'item ':tag (lyskom-language-name (car x)) ':format "%t" ':value (elt x 0)))) lyskom-languages)) propl)) (defun lyskom-nameday-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':format "%[%t%] %v" ':case-fold t ':args (mapcar (lambda (x) (list 'item ':tag (nameday-data->name (cdr x)) ':format "%t" ':value (nameday-data->code (cdr x)))) lyskom-namedays)) propl)) (defun lyskom-ispell-dictionary-widget (type &optional args propl var) (let ((tmp-dictionary-alist nil)) (condition-case nil (progn (require 'ispell) (setq tmp-dictionary-alist ispell-dictionary-alist)) (error (if (null ispell-dictionary-alist) (setq tmp-dictionary-alist '("american" "brasiliano" "british" "castellano" "castellano8" "czech" "dansk" "deutsch" "deutsch8" "english" "esperanto" "esperanto-tex" "francais7" "francais" "francais-tex" "nederlands" "nederlands8" "norsk" "norsk7-tex" "polish" "russian" "svenska"))))) (lyskom-build-simple-widget-spec 'menu-choice (list ':format "%[%t%] %v" ':case-fold nil ':args (cons (list 'item ':tag "ispell-dictionary" ':format "%t" ':value nil) (delq nil (mapcar (function (lambda (x) (and (car x) (list 'item ':tag (car x) ':format "%t" ':value (car x))))) tmp-dictionary-alist)))) propl))) (defun lyskom-face-widget (type &optional args propl var) (let ((wargs (append (mapcar (lambda (f) (list 'item :tag (symbol-name f) :value f :format "%t")) (or (and (listp args) args) (cdr (assq var lyskom-predefined-faces)))) (list (list 'symbol ':size 30 ':tag (lyskom-custom-string 'other-face)))))) (when (eq args t) (setq wargs (append (list (list 'item :tag (lyskom-custom-string 'generated-face) :value nil :format "%t")) wargs))) (if wargs (lyskom-build-simple-widget-spec 'menu-choice (list ':format "%[%t%] %v\n" ':args wargs) propl) (lyskom-build-simple-widget-spec 'symbol (list ':format "%[%t%] %v\n" ':size 30 ':args wargs) propl)))) (defun lyskom-url-viewer-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':format "%[%v%]\n" ':case-fold t ':help-echo (lyskom-custom-string 'select-url-viewer) ':args (list (list 'item ':tag (lyskom-custom-string 'no-viewer) ':format "%t" ':value nil) (list 'item ':tag (lyskom-custom-string 'default-viewer) ':format "%t" ':value "default") (list 'item ':tag (lyskom-custom-string 'windows-viewer) ':format "%t" ':value "windows") (list 'item ':tag (lyskom-custom-string 'netscape-viewer) ':format "%t" ':value "netscape") (list 'item ':tag (lyskom-custom-string 'emacs-w3-viewer) ':format "%t" ':value "w3") (list 'item ':tag (lyskom-custom-string 'emacs-general-viewer) ':format "%t" ':value "emacs") (list 'item ':tag (lyskom-custom-string 'emacs-dired-viewer) ':format "%t" ':value "dired") (list 'item ':tag (lyskom-custom-string 'emacs-mail-viewer) ':format "%t" ':value "mail-mode") (list 'item ':tag (lyskom-custom-string 'emacs-telnet-viewer) ':format "%t" ':value "telnet-mode") (list 'item ':tag (lyskom-custom-string 'mosaic-viewer) ':format "%t" ':value "mosaic") (list 'item ':tag (lyskom-custom-string 'lynx-viewer) ':format "%t" ':value "lynx") (list 'item ':tag (lyskom-custom-string 'galeon-viewer) ':format "%t" ':value "galeon"))) propl)) (defun lyskom-open-window-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':case-fold t ':format "%[%t%] %v" ':args (list (list 'item ':tag (lyskom-custom-string 'other-window) ':format "%t" ':value 'other) (list 'item ':tag (lyskom-custom-string 'other-frame) ':format "%t" ':value 'other-frame) (list 'item ':tag (lyskom-custom-string 'new-frame) ':format "%t" ':value 'new-frame) (list 'item ':tag (lyskom-custom-string 'lyskom-window) ':format "%t" ':value nil) (list 'editable-field ':tag (lyskom-custom-string 'window-on-buffer) ':format "%[%t%]: `%v'" ':value "" ':size 0))) propl)) (defun lyskom-ding-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':case-fold t ':format "%[%t%] %v" ':args (list (list 'item ':tag (lyskom-custom-string 'turned-off) ':value 0 ':format "%t" ':match '(lambda (w v) (eq v 0))) (list 'lyskom-number ':tag (lyskom-custom-string 'number-of-times) ':help-echo (lyskom-custom-string 'select-number) ':value 1 ':format "%[%t%]: (%v)" ':size 0 ':min-value 1 ':max-value 255) (list 'lyskom-string ':tag (lyskom-custom-string 'sound-file) ':help-echo (lyskom-custom-string 'select-audio-file) ':size 0) (list 'editable-list ':format "%[%t%]\n%v%i" ':indent 4 ':tag (lyskom-custom-string 'specific-spec) ':menu-tag (lyskom-custom-string 'specific-spec) ':args `((cons :format "%v" :value (1 0) :args ((menu-choice :case-fold t :format "%[%t%]: %v" :tag ,(lyskom-custom-string 'conf-or-person) :args ((lyskom-name :lyskom-predicate (pers conf) :tag ,(lyskom-custom-string 'conf-or-person)) (item :tag ,(lyskom-custom-string 'other-persons) :value t :format "%t\n"))) (menu-choice :case-fold t :format "%[%t%]: %v\n" :tag ,(lyskom-custom-string 'ding) :args ((item :tag ,(lyskom-custom-string 'turned-off) :value nil :format "%t" :match (lambda (w v) (or (null v) (eq v 0)))) (lyskom-number :tag ,(lyskom-custom-string 'number-of-times) :help-echo ,(lyskom-custom-string 'select-number) :value 1 :format "%[%t%]: (%v)" :size 0 :min-value 1 :max-value 255) (lyskom-string :tag ,(lyskom-custom-string 'sound-file) :help-echo ,(lyskom-custom-string 'select-audio-file) :size 0)))))) ) )) propl)) (defun lyskom-toggle-widget-inverse (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':case-fold t ':format "%[%t%] %v" ':args (list (list 'item ':tag (lyskom-custom-string (elt args 0)) ':value nil ':format "%t") (list 'item ':tag (lyskom-custom-string (elt args 1)) ':value t ':match '(lambda (w v) v) ':format "%t"))) propl)) (defun lyskom-toggle-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':case-fold t ':format "%[%t%] %v" ':args (list (list 'item ':tag (lyskom-custom-string (elt args 0)) ':value t ':format "%t" ':match '(lambda (w v) v)) (list 'item ':tag (lyskom-custom-string (elt args 1)) ':value nil ':format "%t"))) propl)) (defun lyskom-repeat-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'editable-list (list ':format "%[%t%]\n%v%i" ':args (list (lyskom-widget-convert-specification args var))) propl)) (defun lyskom-cons-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'cons (list ':format "%v\n" ':tag "" ':args (list (lyskom-widget-convert-specification (elt args 0) var) (lyskom-widget-convert-specification (elt args 1) var))) propl)) (defun lyskom-list-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'list (list ':format "%v\n" ':tag "" ':args (mapcar (lambda (x) (lyskom-widget-convert-specification x var)) args)) propl)) (defun lyskom-choice-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'menu-choice (list ':case-fold t ':format "%[%t%] %v" ':args (mapcar (lambda (x) (lyskom-widget-convert-specification x var)) args)) propl)) (defun lyskom-string-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'lyskom-string (list ':size 0 ':format "%[%t%] `%v'") propl)) (defun lyskom-number-widget (type &optional args propl var) (if args (lyskom-build-simple-widget-spec 'lyskom-number (list ':min-value (elt args 0) ':max-value (elt args 1) ':value 0 ':size 0) propl) (lyskom-build-simple-widget-spec 'lyskom-number (list ':size 0 ':value 0) propl))) ;;; ;;; The ansaphone reply widget (whew!) (defun lyskom-ansaphone-reply-widget (type &optional args propl var) (lyskom-build-simple-widget-spec 'editable-list (list ':format "%t:\n%v%i\n" ':args `((group :args ((menu-choice :tag ,(lyskom-custom-string 'ar-message-type) :format "%[%t%]: %v" :args ((item :value personal :tag ,(lyskom-custom-string 'ar-personal)) (item :value group :tag ,(lyskom-custom-string 'ar-group)) (item :value common :tag ,(lyskom-custom-string 'ar-alarm)) (item :value nil :tag ,(lyskom-custom-string 'ar-any-type)))) (menu-choice :tag ,(lyskom-custom-string 'ar-sender) :args ((item :value nil :tag ,(lyskom-custom-string 'ar-any-sender)) (editable-list :tag ,(lyskom-custom-string 'ar-specified-sender) :menu-tag ,(lyskom-custom-string 'ar-specified-sender) :format "%t:\n%v%i\n" :indent 14 :args ((lyskom-name :format "%[%t%]: %v" :tag ,(lyskom-custom-string 'ar-person)))))) (menu-choice :tag ,(lyskom-custom-string 'ar-recipient) :args ((item :value nil :tag ,(lyskom-custom-string 'ar-any-recipient)) (editable-list :tag ,(lyskom-custom-string 'ar-specified-recipient) :menu-tag ,(lyskom-custom-string 'ar-specified-recipient) :format "%t:\n%v%i\n" :indent 14 :args ((lyskom-name :tag ,(lyskom-custom-string 'ar-pers-or-conf) :format "%[%t%]: %v" :lyskom-predicate (pers conf)))))) (menu-choice :tag ,(lyskom-custom-string 'ar-message-text) :args ((item :value nil :tag ,(lyskom-custom-string 'ar-any-message)) (lyskom-string :tag ,(lyskom-custom-string 'ar-matching-regexp) :size 0 :format "%[%t%] `%v'\n"))) (menu-choice :tag ,(lyskom-custom-string 'ar-reply) :args ((item :value nil :tag ,(lyskom-custom-string 'ar-no-reply)) (lyskom-string :tag ,(lyskom-custom-string 'ar-reply-text) :size 0 :format "%[%t%] `%v'\n"))))))) propl)) ;;; ====================================================================== ;;; Generic LysKOM widget functions ;;; (defun lyskom-widget-value-get (widget) (widget-get widget ':value)) (defun lyskom-widget-value-delete (widget) (set-marker (widget-get widget ':value-from) nil) (set-marker (widget-get widget ':value-to) nil)) (defun lyskom-widget-value-to-external (widget value) value) (defun lyskom-widget-value-to-internal (widget value) value) (defun lyskom-widget-invalid-value (widget) (widget-put widget ':error (lyskom-format (lyskom-custom-string 'invalid-value) (widget-value widget))) widget) ;;; ;;; The Person Widget ;;; (defun lyskom-widget-name-action (widget &optional event) (widget-value-set widget (save-excursion (set-buffer lyskom-buffer) (lyskom-read-conf-no (lyskom-custom-string (cond ((widget-get widget ':lyskom-prompt) (widget-get widget ':lyskom-prompt)) ((and (memq 'pers (widget-get widget ':lyskom-predicate)) (memq 'conf (widget-get widget ':lyskom-predicate))) 'which-conf-or-person) ((memq 'pers (widget-get widget ':lyskom-predicate)) 'which-person) ((memq 'conf (widget-get widget ':lyskom-predicate)) 'which-conf) (t 'which-name))) (widget-get widget ':lyskom-predicate) nil "" t))) (widget-setup)) (defun lyskom-widget-name-value-create (widget) (let* ((size (widget-get widget ':size)) (value (widget-get widget ':value)) (from (point)) (string (save-excursion (set-buffer lyskom-buffer) (cond ((or (null value) (eq 0 value)) "") (t (or (conf-stat->name (blocking-do 'get-conf-stat value)) (lyskom-format (lyskom-custom-string 'some-person) value))))))) (if (null size) (insert string) (insert string) (if (< (lyskom-string-width value) size) (insert-char ?\ (- size (lyskom-string-width value))))) (widget-put widget ':value-from (copy-marker from)) (widget-put widget ':value-to (copy-marker (point))) (set-marker-insertion-type (widget-get widget ':value-to) nil) (if (null size) (insert ?\n) (insert ?\ )))) (defun lyskom-widget-name-match (widget value) (and (numberp value) (>= value 0))) (defun lyskom-widget-name-validate (widget) (let ((value (widget-value widget))) (if (and (numberp value) (>= value 0)) nil (lyskom-widget-invalid-value widget)))) (define-widget 'lyskom-name 'default "A LysKOM person" ':format "%[[*]%] %v" ':default-help-echo 'change-this-name ':value 0 ':lyskom-predicate '(pers) ':action 'lyskom-widget-name-action ':value-create 'lyskom-widget-name-value-create ':value-delete 'lyskom-widget-value-delete ':value-get 'lyskom-widget-value-get ':value-to-external 'lyskom-widget-value-to-external ':value-to-internal 'lyskom-widget-value-to-internal ':match 'lyskom-widget-name-match ':validate 'lyskom-widget-name-validate ) (define-widget 'lyskom-name-list 'editable-list "A list of LysKOM commands" ':entry-format "%i %d %v" ':args '(lyskom-name)) ;;; ;;; The Command Widget ;;; (defun lyskom-widget-command-action (widget &optional event) (widget-value-set widget (save-excursion (set-buffer lyskom-buffer) (lyskom-read-extended-command nil (concat (widget-get widget ':tag) ": ")))) (widget-setup)) (defun lyskom-widget-command-value-create (widget) (let* ((size (widget-get widget ':size)) (value (widget-get widget ':value)) (from (point)) (string (save-excursion (set-buffer lyskom-buffer) (cond ((null value) "") (t (or (lyskom-try-get-string value 'lyskom-command) (lyskom-format (lyskom-custom-string 'unknown-command) (symbol-name value)))))))) (if (null size) (insert string) (insert string) (if (< (lyskom-string-width value) size) (insert-char ?\ (- size (lyskom-string-width value))))) (widget-put widget ':value-from (copy-marker from)) (widget-put widget ':value-to (copy-marker (point))) (set-marker-insertion-type (widget-get widget ':value-to) nil) (if (null size) (insert ?\n) (insert ?\ )))) (defun lyskom-widget-command-match (widget value) (symbolp value)) (defun lyskom-widget-command-validate (widget) (if (symbolp (widget-value widget)) nil (lyskom-widget-invalid-value widget))) (define-widget 'lyskom-command 'default "A LysKOM command" ':format "%[%t%] %v" ':default-help-echo 'select-command ':value 'kom-display-time ':action 'lyskom-widget-command-action ':value-create 'lyskom-widget-command-value-create ':value-delete 'lyskom-widget-value-delete ':value-get 'lyskom-widget-value-get ':value-to-external 'lyskom-widget-value-to-external ':value-to-internal 'lyskom-widget-value-to-internal ':match 'lyskom-widget-command-match ':validate 'lyskom-widget-command-validate ) (define-widget 'lyskom-command-list 'editable-list "A list of LysKOM commands" ':entry-format "%i %d %v" ':args '(lyskom-command)) ;;; ;;; A new String widget ;;; (defun lyskom-widget-string-action (widget &optional event) (let ((tmp (lyskom-read-from-minibuffer (format "%s " (widget-get widget ':tag)) (widget-value widget)))) (widget-value-set widget tmp) (widget-setup))) (define-widget 'lyskom-string 'editable-field "A string" ':format "%[%t%] %v" ':action 'lyskom-widget-string-action) ;;; ;;; A Number widget ;;; (defun lyskom-widget-number-action (widget &optional event) (let ((min (widget-get widget ':min-value)) (max (widget-get widget ':max-value))) (widget-value-set widget (if (and min max) (lyskom-read-num-range min max (widget-get widget ':tag) t (widget-value widget)) (lyskom-read-number (widget-get widget ':tag) (widget-value widget)))) (widget-setup))) (defun lyskom-widget-number-value-to-external (widget value) (cond ((stringp value) (string-to-int value)) ((numberp value) value) ((null value) 0) (t (error "unable to convert settings value")))) (defun lyskom-widget-number-value-to-internal (widget value) (cond ((stringp value) value) ((numberp value) (format "% 4d" value)) ((null value) "") (t (format "%S" value)))) (defun lyskom-widget-number-validate (widget) (if (numberp (widget-value widget)) nil (lyskom-widget-invalid-value widget))) (defun lyskom-widget-number-match (widget value) (if (and (widget-get widget ':max-value) (widget-get widget ':min-value)) (and (numberp value) (>= value (widget-get widget ':min-value)) (<= value (widget-get widget ':max-value))) (numberp value))) (define-widget 'lyskom-number 'editable-field "A number" ':format "%[%t%] %v" ':action 'lyskom-widget-number-action ':value-to-external 'lyskom-widget-number-value-to-external ':value-to-internal 'lyskom-widget-number-value-to-internal ':match 'lyskom-widget-number-match ':validate 'lyskom-widget-number-validate) ;;; ;;; Keyboard macro widget ;;; (defun lyskom-widget-kbd-macro-match (widget value) (or (stringp value) (vectorp value))) (defun lyskom-widget-kbd-macro-validate (widget) (if (lyskom-widget-kbd-macro-match widget (widget-value widget)) nil (lyskom-widget-invalid-value widget))) (defun lyskom-widget-kbd-macro-value-create (widget) (let* ((size (widget-get widget ':size)) (value (widget-get widget ':value)) (from (point)) (string (mapconcat 'single-key-description (append value nil) " "))) (if (null size) (insert string) (insert string) (if (< (lyskom-string-width string) size) (insert-char ?\ (- size (lyskom-string-width string))))) (widget-put widget ':value-from (copy-marker from)) (widget-put widget ':value-to (copy-marker (point))) (set-marker-insertion-type (widget-get widget ':value-to) nil) (if (null size) (insert ?\n) (insert ?\ )))) ;;; ;;; This is a truly disgusting piece of work. In Gnu Emacs it's not ;;; possible to simply read a keyboard macro in a recursive command ;;; loop and have the command loop end when macro definition time is ;;; up, so we start a macro definition, make the normal end-kbd-macro ;;; keys just exit the recursive command loop, go recursive and when ;;; the recursive loop is over, any which way, we see if a macro was ;;; defined and reset the keyboard bindings. ;;; (defun lyskom-widget-end-kbd-macro () (interactive) (exit-recursive-edit)) (defun lyskom-widget-kbd-macro-action (widget &optional event) (let ((tmp last-kbd-macro) (value nil)) (save-window-excursion (unwind-protect (progn (mapcar (function (lambda (k) (define-key global-map k 'lyskom-widget-end-kbd-macro))) (where-is-internal 'end-kbd-macro)) (if (widget-get widget ':macro-buffer) (pop-to-buffer (widget-get widget ':macro-buffer))) (start-kbd-macro nil) (recursive-edit)) (mapcar (function (lambda (k) (define-key global-map k 'end-kbd-macro))) (where-is-internal 'lyskom-widget-end-kbd-macro)) (condition-case e (end-kbd-macro) (error (setq last-kbd-macro nil))))) (setq value (prog1 last-kbd-macro (setq last-kbd-macro tmp))) (if value (progn (widget-value-set widget value) (widget-setup))))) (define-widget 'lyskom-kbd-macro 'default "A Keyboard Macro" ':action 'lyskom-widget-kbd-macro-action ':value "" ':format "%[%t%] %v" ':validate 'lyskom-widget-kbd-macro-validate ':value-create 'lyskom-widget-kbd-macro-value-create ':value-delete 'lyskom-widget-value-delete ':value-get 'lyskom-widget-value-get ':value-to-external 'lyskom-widget-value-to-external ':value-to-internal 'lyskom-widget-value-to-internal ':match 'lyskom-widget-kbd-macro-match) ;;; ;;; Mark association widget ;;; (defun lyskom-widget-mark-association-action (widget &optional event) (widget-value-set widget (cons (lyskom-read-string (widget-get widget ':mark-key-prompt) (car (widget-value widget))) (lyskom-read-num-range 0 255 (widget-get widget ':mark-value-prompt) t (cdr (widget-value widget))))) (widget-setup)) (defun lyskom-widget-mark-association-match (widget value) (and (consp value) (let ((s (car value)) (i (cdr value))) (and (stringp s) (> (length s) 0) (integerp i) (>= i 0) (<= i 255))))) (defun lyskom-widget-mark-association-validate (widget) (let ((value (widget-value widget))) (if (lyskom-widget-mark-association-match widget value) nil (lyskom-widget-invalid-value widget)))) (defun lyskom-widget-mark-association-value-create (widget) (let ((from (point)) (value (widget-value widget))) (insert (format "%s <--> %s" (car value) (if (and (string= (car value) "...") (= (cdr value) 0)) "..." (cdr value)))) (widget-put widget ':value-from (copy-marker from)) (widget-put widget ':value-to (copy-marker (point))))) (define-widget 'lyskom-mark-association 'default "A mark association." :tag "Mark association" :format "%[%t%] %v\n" :value '("..." . 0) :default-help-echo 'change-this-name :match 'lyskom-widget-mark-association-match :validate 'lyskom-widget-mark-association-validate :action 'lyskom-widget-mark-association-action :value-create 'lyskom-widget-mark-association-value-create :value-delete 'lyskom-widget-value-delete :value-get 'lyskom-widget-value-get :value-to-external 'lyskom-widget-value-to-external :value-to-internal 'lyskom-widget-value-to-internal) ;;; ;;; Help widget ;;; (defun lyskom-widget-help-action (widget &optional event) (let* ((value (widget-get widget ':value)) (spec (assq value (widget-get widget ':args))) (syms (car (cdr (memq spec (widget-get widget ':args)))))) (if (null syms) (setq syms (car (widget-get widget ':args)))) (widget-put widget ':help-echo (elt syms 3)) (widget-value-set widget (car syms)) (widget-setup))) (defun lyskom-widget-help-format-handler (widget escape) (let* ((value (widget-get widget ':value)) (spec (assq value (widget-get widget ':args)))) (cond ((eq escape ?D) (if (widget-get widget ':indent) (insert-char ? (widget-get widget ':indent))) (insert (format (elt spec 1) (elt spec 2)))) ((eq escape ?T) (if (widget-get widget ':indent) (insert-char ? (widget-get widget ':indent))) (insert (elt spec 4))) (t (widget-default-format-handler widget escape))))) (define-widget 'lyskom-widget-help 'push-button "A help widget" ':format "%[[%t]%] %D" ':action 'lyskom-widget-help-action ':format-handler 'lyskom-widget-help-format-handler) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: talkback.el,v 44.4 2002/02/24 20:23:28 joel Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: talkback.el ;;;; ;;;; Functions for handing bug reports ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: talkback.el,v 44.4 2002/02/24 20:23:28 joel Exp $\n")) (defvar kom-bug-report-address "kom@lysator.liu.se") (defvar lyskom-bug-report-special-vars '((lyskom-conf-cache . (lambda (n v) (format "%d items" (length v)))) (lyskom-uconf-cache . (lambda (n v) (format "%d items" (length v)))) (lyskom-text-cache . (lambda (n v) (format "%d items" (length v)))) (lyskom-text-mass-cache . (lambda (n v) (format "%d items" (length v)))) (lyskom-default-password . "********"))) (defun lyskom-save-backtrace (&rest data) "Save the current backtrace" (lyskom-message "Saving debugging information...") (setq lyskom-backtrace-list (cons (list (current-time-string) (let* ((buffer (generate-new-buffer " *Backtrace*")) (standard-output buffer)) (backtrace) (prog1 (save-excursion (set-buffer buffer) (buffer-string)) (kill-buffer buffer))) data) lyskom-backtrace-list)) (lyskom-message "Saving debugging information...done")) (defun lyskom-bug-insert-recent-messages (n) (let ((message-buf (get-buffer (lyskom-xemacs-or-gnu " *Message-Log*" "*Messages*")))) (insert "\n\nRecent messages:\n") (if message-buf (insert-buffer-substring message-buf (save-excursion (set-buffer message-buf) (goto-char (point-max)) (forward-line -10) (point)) (save-excursion (set-buffer message-buf) (point-max)))))) (defun lyskom-insert-bug-report () (insert (save-excursion (set-buffer lyskom-buffer) (let ((v lyskom-server-version-info)) (format "\ This bug report will be sent to the LysKOM development team, not to your local site managers. Please write in english or swedish, because the LysKOM maintainers (if there are any) are too lazy to learn other languages just so they can read your bug reports. Client time: %s Emacs version: %s (%s) Client version: %s (%s) LysKOM server: %s:%S Server version: %s %s %S Current person: %S (%s) Command line: %S Please describe the precise symptoms of the bug and exactly what actions triggered the bug. Be as detailed as possible. Do not try to make any conclusions of your own. " (current-time-string) (emacs-version) (if enable-multibyte-characters "MULE" "no MULE") lyskom-clientversion (if lyskom-mule-compiled "MULE" "no MULE") lyskom-server-name lyskom-server-port (if v (version-info->server-software v) "unknown") (if v (version-info->software-version v) "unknown") (if v (version-info->protocol-version v) "unknown") lyskom-pers-no (condition-case nil (uconf-stat->name (cache-get-uconf-stat lyskom-pers-no)) (error "")) command-line-args )))) (let ((saved-place (point))) (insert "\n\n") (lyskom-bug-insert-recent-messages 20) (insert "\n\nSaved backtraces:\n\n") (mapcar (lambda (el) (insert (elt el 0)) ; Time (insert "\n") (insert (elt el 1)) ; Backtrace (insert "\n") (mapcar (lambda (data) (insert "Data: ") (prin1 data) (insert "\n")) (elt el 2))) lyskom-backtrace-list) (insert "\n\nAll variables:\n\n") (mapatoms (lambda (var) (when (and (save-excursion (set-buffer lyskom-buffer) (boundp var)) (or (string-match "^\\(lys\\)?kom" (symbol-name var)))) (message "Collecting system information...%s" var) (insert (format "(%s " var)) (cond ((assq var lyskom-bug-report-special-vars) (let ((fn (cdr (assq var lyskom-bug-report-special-vars)))) (cond ((functionp fn) (lyskom-bug-report-insert-value (funcall fn var (lyskom-default-value var)))) (t (lyskom-bug-report-insert-value fn))))) (t (lyskom-bug-report-insert-value (lyskom-default-value var)))) (insert ")\n")))) (goto-char saved-place) )) (defun lyskom-bug-report-insert-value (v) (cond ((eq t v) (insert "t")) ((eq nil v) (insert "nil")) ((symbolp v) (insert "'") (princ v)) (t (prin1 v)))) (defun kom-bug-report (topic) "Report a LysKOM bug" (interactive "sBug Subject: ") (let ((buf lyskom-buffer)) (unless buf (error "Switch to a LysKOM buffer to report bugs.")) (when (lyskom-xemacs-or-gnu (progn (compose-mail kom-bug-report-address topic) t) (mail nil kom-bug-report-address topic)) (goto-char (point-min)) (re-search-forward (concat "^" (regexp-quote mail-header-separator) "\n\ ")) (let ((standard-output (current-buffer))) (message "Collecting system information...") (make-local-variable 'lyskom-buffer) (setq lyskom-buffer buf) (lyskom-insert-bug-report) (message "Collecting system information...done"))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: faqs.el,v 44.20 2004/06/26 13:32:32 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: faqs.el ;;;; ;;;; This file contains the code for FAQ handling ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: faqs.el,v 44.20 2004/06/26 13:32:32 byers Exp $\n")) (defun lyskom-register-read-faq (conf-no text-no) (unless conf-no (setq conf-no 0)) (unless (lyskom-faq-is-read conf-no text-no) (setq lyskom-read-faqs (cons (cons conf-no text-no) lyskom-read-faqs)) (initiate-modify-conf-info 'background nil lyskom-pers-no nil (list (lyskom-create-aux-item 0 10000 nil nil (lyskom-create-aux-item-flags nil nil t nil nil nil nil nil) 0 (format "%d %d" conf-no text-no)))))) (defun lyskom-faq-is-read (conf-no text-no) "Return non-nil if lyskom-pers-no has read CONF-NOs FAQ TEXT-NO." (member (cons (or conf-no 0) text-no) lyskom-read-faqs)) (defun lyskom-update-read-faqs () "Update the list of read FAQs from the server." (setq lyskom-read-faqs nil) (let* ((conf-stat (blocking-do 'get-conf-stat lyskom-pers-no)) (aux-list (and conf-stat (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 10000)))) (lyskom-traverse item aux-list (when (string-match "^\\([0-9]+\\) \\([0-9]+\\)" (aux-item->data item)) (setq lyskom-read-faqs (cons (cons (string-to-int (match-string 1 (aux-item->data item))) (string-to-int (match-string 2 (aux-item->data item)))) lyskom-read-faqs)))))) ;;; ====================================================================== ;;; FAQ Management ;;; (def-kom-command kom-add-faq (&optional conf-no text-no) "Make an existing text a FAQ of a conference. To write a new FAQ for a conference that doesn't have one, or change an existing FAQ, use `kom-change-conf-faq'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-conf-no 'conf-to-add-faq '(conf pers) nil nil t) (lyskom-read-text-no-prefix-arg 'text-to-add-as-faq))) (lyskom-add-faq conf-no text-no)) (def-kom-command kom-add-server-faq (&optional text-no) "Make an existing text a FAQ of the server. To write a new FAQ for a conference that doesn't have one, or change an existing FAQ, use `kom-change-server-faq'. This command accepts text number prefix arguments \(see `lyskom-read-text-no-prefix-arg')." (interactive (list (lyskom-read-text-no-prefix-arg 'text-to-add-as-faq))) (lyskom-add-faq nil text-no)) (defun lyskom-add-faq (conf-no text-no) "Add a FAQ to a conference or the server. Add to the server if CONF-NO is nil, otherwise add to conference CONF-NO. The text to add is passed in TEXT-NO" (let ((text (blocking-do 'get-text-stat text-no))) (if (null text) (lyskom-format-insert 'no-such-text-no text-no) (lyskom-format-insert 'adding-faq text-no conf-no) (cache-del-text-stat text-no) (when conf-no (cache-del-conf-stat conf-no)) (let ((aux-item (lyskom-create-aux-item 0 14 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (int-to-string text-no)))) (lyskom-report-command-answer (if conf-no (blocking-do 'modify-conf-info conf-no nil (list aux-item)) (blocking-do 'modify-server-info nil (list aux-item)))))))) (def-kom-command kom-del-server-faq () "Remove a FAQ from the server. You need administrative rights to do this. To add a FAQ, use `kom-add-server-faq'." (interactive) (lyskom-del-faq nil)) (def-kom-command kom-del-faq () "Remove a FAQ from a conference. To add a FAQ, use `kom-add-faq'." (interactive) (let* ((conf-stat (lyskom-read-conf-stat 'conf-to-del-faq '(conf pers) nil nil t))) (lyskom-del-faq conf-stat))) (defun lyskom-del-faq (conf-stat) (let ((faq-list (delq nil (mapcar (lambda (aux) (and (lyskom-string-to-int (aux-item->data aux)) (cons (aux-item->data aux) (aux-item->aux-no aux)))) (lyskom-get-aux-item (if (null conf-stat) (server-info->aux-item-list (blocking-do 'get-server-info)) (conf-stat->aux-items conf-stat)) 14)))) (text-no nil)) (cond ((null faq-list) (lyskom-format-insert 'conf-has-no-faq conf-stat)) (t (setq text-no (if (eq 1 (length faq-list)) (car (car faq-list)) (lyskom-completing-read (lyskom-get-string 'text-to-del-as-faq) (lyskom-maybe-frob-completion-table faq-list) nil t))) (when text-no (lyskom-format-insert 'deleting-faq (string-to-int text-no) conf-stat) (cache-del-text-stat (string-to-int text-no)) (when conf-stat (cache-del-conf-stat (conf-stat->conf-no conf-stat))) (lyskom-report-command-answer (if conf-stat (blocking-do 'modify-conf-info (conf-stat->conf-no conf-stat) (list (cdr (lyskom-string-assoc text-no faq-list))) nil) (blocking-do 'modify-server-info (list (cdr (lyskom-string-assoc text-no faq-list))) nil)))))))) (def-kom-command kom-review-server-faq () "View the FAQs for the server." (interactive) (lyskom-review-faq nil (server-info->aux-item-list (blocking-do 'get-server-info)))) (def-kom-command kom-unread-server-faq () "Mark the FAQs for the server as unread." (interactive) (lyskom-unread-faq nil (server-info->aux-item-list (blocking-do 'get-server-info)))) (def-kom-command kom-review-faq (&optional conf-no) "View the FAQs for a particular conference." (interactive (list (lyskom-read-conf-no 'view-which-faq '(conf pers) t nil t))) (if (zerop conf-no) (lyskom-review-faq nil (server-info->aux-item-list (blocking-do 'get-server-info))) (let ((conf-stat (blocking-do 'get-conf-stat conf-no))) (if conf-stat (lyskom-review-faq conf-stat (conf-stat->aux-items conf-stat)) (lyskom-format-insert 'conf-no-does-not-exist-r conf-no))))) (def-kom-command kom-unread-faq (&optional conf-no) "Marks the FAQs for a particular conference as unread." (interactive (list (lyskom-read-conf-no 'unread-which-faq '(conf pers) t nil t))) (if (zerop conf-no) (lyskom-unread-faq nil (server-info->aux-item-list (blocking-do 'get-server-info))) (let ((conf-stat (blocking-do 'get-conf-stat conf-no))) (if conf-stat (lyskom-unread-faq conf-stat (conf-stat->aux-items conf-stat)) (lyskom-format-insert 'conf-no-does-not-exist-r conf-no))))) (defun lyskom-unread-faq (conf-stat aux-list) (let ((faq-list (delq nil (mapcar (lambda (aux) (lyskom-string-to-int (aux-item->data aux))) (lyskom-get-aux-item aux-list 14))))) (if (null faq-list) (lyskom-format-insert 'conf-has-no-faq conf-stat) (lyskom-traverse text-no faq-list (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no)))))) (defun lyskom-review-faq (conf-stat aux-list) (let ((faq-list (delq nil (mapcar (lambda (aux) (lyskom-string-to-int (aux-item->data aux))) (lyskom-get-aux-item aux-list 14))))) (cond ((null faq-list) (lyskom-format-insert 'conf-has-no-faq conf-stat)) ((eq 1 (length faq-list)) (lyskom-format-insert 'review-faq-for-r conf-stat) (lyskom-view-text (car faq-list) nil ;mark-as-read nil ;follow-comments nil ;conf-stat nil ;priority nil ;build-review-tree t ;flat-review )) (t (lyskom-format-insert 'review-faq-for-r conf-stat) (lyskom-do-review-faq faq-list) )))) (defun lyskom-do-review-faq (faq-list &optional review-tree) (read-list-enter-read-info (lyskom-create-read-info (if review-tree 'REVIEW-FAQ-TREE 'REVIEW-FAQ) nil (lyskom-review-get-priority) (lyskom-create-text-list faq-list) nil t) lyskom-reading-list t)) (def-kom-command kom-change-server-faq () "Change a FAQ for the server. If the server doesn't have a FAQ, create a new one. You need administrative rights to do this." (interactive) (lyskom-change-faq nil (lyskom-get-aux-item (server-info->aux-item-list (blocking-do 'get-server-info)) 14))) (def-kom-command kom-change-conf-faq () "Change a FAQ fo a conference. If the conference doesn't have a FAQ, create a new FAQ." (interactive) (let* ((conf-no (lyskom-read-conf-no 'what-to-change-faq-you '(conf pers) nil nil t)) (conf-stat (when conf-no ; Need this to make sure the conf-stat is up-to-date! (cache-del-conf-stat conf-no) (blocking-do 'get-conf-stat conf-no)))) (if conf-stat (lyskom-change-faq conf-stat (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 14)) (lyskom-insert (lyskom-get-string 'conf-does-not-exist))))) (defun lyskom-change-faq (conf-stat aux-list) "Change a FAQ for a conference." ;; Get a list of FAQ texts and corresponding aux-item-numbers ;; Get the FAQ to change (let* ((faq-list (delq nil (mapcar (lambda (x) (and (lyskom-string-to-int (aux-item->data x)) (cons (aux-item->data x) (aux-item->aux-no x)))) aux-list))) (text-no-aux (cond ((= (length faq-list) 1) (car faq-list)) ((null faq-list) nil) (t (lyskom-string-assoc (lyskom-completing-read (lyskom-get-string 'text-to-change-as-faq) (lyskom-maybe-frob-completion-table faq-list) nil t) faq-list)))) (text-no (and text-no-aux (string-to-int (car text-no-aux)))) (aux-no (and text-no-aux (cdr text-no-aux)))) (cond ;; If conf-stat is null we are changing the FAQ for the server. ;; Don't do this unless we are running enabled and have the right ;; privileges. ((and (null conf-stat) (or (not lyskom-is-administrator) (not (privs->admin (pers-stat->privileges (blocking-do 'get-pers-stat lyskom-pers-no)))))) (lyskom-format-insert 'not-supervisor-for-server)) ;; If we have a conf-stat and are not administrator and not ;; supervisor for the conf, then we are not allowed to change ;; the FAQ. ((and conf-stat (not lyskom-is-administrator) (not (lyskom-is-supervisor (conf-stat->conf-no conf-stat) lyskom-pers-no))) (lyskom-format-insert 'not-supervisor-for conf-stat)) ;; OK, it looks like we are allowed to change the FAQ. (t (let ((text-stat nil) (text-mass nil)) ;; Get the old text (if there is one) (blocking-do-multiple ((ts (get-text-stat text-no)) (tm (get-text text-no))) (setq text-stat ts text-mass tm)) (let* ((str (and text-mass (text->decoded-text-mass text-mass text-stat))) (subject (if (and str (string-match "\n" str)) (substring str 0 (match-beginning 0)) "" )) (body (if (and str (string-match "\n" str)) (substring str (match-end 0)) (or str "")))) (lyskom-dispatch-edit-text lyskom-proc (apply 'lyskom-create-misc-list (if (and text-stat text-mass) (append (lyskom-get-recipients-from-misc-list (text-stat->misc-info-list text-stat)) (list 'COMM-TO (text-stat->text-no text-stat))) (list 'RECPT (conf-stat->conf-no conf-stat)))) subject body 'lyskom-change-faq-2 conf-stat (and text-stat (text-stat->text-no text-stat)) aux-no))))))) (defun lyskom-change-faq-2 (text-no conf-stat old-text-no old-aux-no) (let ((aux-item (lyskom-create-aux-item 0 14 0 0 (lyskom-create-aux-item-flags nil nil nil nil nil nil nil nil) 0 (int-to-string text-no)))) (if conf-stat (progn (cache-del-conf-stat (conf-stat->conf-no conf-stat)) (initiate-modify-conf-info 'background 'lyskom-change-faq-3 (conf-stat->conf-no conf-stat) (when old-aux-no (list old-aux-no)) (list aux-item) conf-stat old-text-no text-no)) (initiate-modify-server-info 'background 'lyskom-change-faq-3 (when old-aux-no (list old-aux-no)) (list aux-item) conf-stat old-text-no text-no)))) (defun lyskom-change-faq-3 (retval conf-stat old-text-no text-no) (cache-del-text-stat text-no) (if retval (lyskom-format-insert-before-prompt (if old-text-no 'changed-faq-for-conf-done 'set-faq-for-conf-done) conf-stat old-text-no text-no) (lyskom-format-insert-before-prompt (if old-text-no 'changed-faq-for-conf-failed 'set-faq-for-conf-failed) conf-stat old-text-no text-no (lyskom-current-error)))) ;;; ================================================================ ;;; Special have-you-read-the-FAQ-checking stuff (defun lyskom-startup-check-faqs () (let ((faq-list (lyskom-get-unread-faqs nil))) (when faq-list (lyskom-format-insert 'server-has-new-faq (length faq-list)) (lyskom-present-unread-faqs nil faq-list)))) (defun lyskom-get-unread-faqs (conf-stat) "Return a list of unread FAQs for conf CONF-STAT." (let* ((conf-no (if conf-stat (conf-stat->conf-no conf-stat) 0)) (aux-list (if conf-stat (conf-stat->aux-items conf-stat) (server-info->aux-item-list lyskom-server-info))) (faq-list (filter-list (lambda (faq) (not (lyskom-faq-is-read conf-no faq))) (delq nil (mapcar (lambda (aux) (lyskom-string-to-int (aux-item->data aux))) (lyskom-get-aux-item aux-list 14)))))) ;; Filter out FAQs that don't exist (let ((collector (make-collector))) (lyskom-traverse faq faq-list (initiate-get-text-stat 'background (lambda (text-stat faq conf-no collector) (if text-stat (collector-push faq collector) (lyskom-register-read-faq conf-no faq))) faq faq conf-no collector)) (lyskom-wait-queue 'background) (setq faq-list (nreverse (collector->value collector)))) faq-list)) (defun lyskom-present-unread-faqs (conf-stat faq-list) "Present a list of unread FAQs in an appropriate manner." (when faq-list (when kom-auto-list-faqs (lyskom-format-insert 'unread-faqs-header (length faq-list) (and conf-stat (conf-stat->conf-no conf-stat))) (lyskom-list-text-summary faq-list nil)) (when kom-auto-review-faqs (lyskom-do-review-faq faq-list t)))) (def-kom-command kom-list-faqs (conf-stat) "List all FAQs for a conference." (interactive (list (lyskom-read-conf-stat 'conf-to-list-faqs '(conf) nil nil t))) (lyskom-do-list-faqs conf-stat (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 14))) (def-kom-command kom-list-server-faqs () "List all FAQs for the server." (interactive) (lyskom-do-list-faqs nil (lyskom-get-aux-item (server-info->aux-item-list (blocking-do 'get-server-info)) 14))) (defun lyskom-do-list-faqs (conf-stat faq-list) (setq faq-list (delq nil (mapcar (lambda (aux) (lyskom-string-to-int (aux-item->data aux))) faq-list))) (cond (faq-list (lyskom-format-insert 'all-faqs-header (and conf-stat (conf-stat->conf-no conf-stat))) (lyskom-list-text-summary faq-list nil)) (t (lyskom-format-insert 'conf-has-no-faq conf-stat)))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: user-hooks.el,v 44.3 2003/03/16 15:57:33 byers Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: user-hooks.el ;;;; ;;;; This file contains hook functions that users might be interested in. ;;;; (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: user-hooks.el,v 44.3 2003/03/16 15:57:33 byers Exp $\n")) (def-kom-var kom-list-summary-hook-conf-list nil "*This variable controls the behavior of kom-list-summary-hook. When kom-list-summary-hook is used in kom-after-change-conf-hook, this variable specifies which conferences to automatically to list summary for. It is a list of conference numbers" server) (def-kom-var kom-read-last-text-hook-conf-list nil "*This variable controls the behavior of kom-read-last-text-hook. When kom-read-last-text-hook is used in kom-change-conf-hook, this variable specifies which conferences the hook applies to. Each element is either a conference number of a cons cell consisting of a conference number and an integer. If a conference number appears in the list alone, the most recent text in that conference will be marked as unread upon entering the conference. If a cons cell (CONF-NO . NUMBER) is in the list, the NUMBER most recent texts (approximately) will be marked as unread on entering conference CONF-NO." server) (defun kom-list-summary-hook (from-conf to-conf) "Automatically list text summary when entering a conference. This function can be added to kom-after-change-conf-hook. Which conferences to list subjects in is controlled by kom-list-summary-hook-conf-list" (when (or (eq kom-list-summary-hook-conf-list t) (memq to-conf kom-list-summary-hook-conf-list)) (lyskom-list-summary to-conf))) (defun kom-read-last-text-hook (from-conf to-conf) "Automatically read only the most recent N texts in a conference. This function can be added to kom-change-conf-hook. Which conferences to perform this in is controlled by kom-read-last-text-hook-conf-list. Not that even unread texts may be read again when usign this function." (let* ((spec (or (and (memq to-conf kom-read-last-text-hook-conf-list) t) (assq to-conf kom-read-last-text-hook-conf-list))) (arg (and spec (if (consp spec) (cdr spec) 1)))) (when (and arg (blocking-do 'set-unread to-conf arg)) (let ((membership (blocking-do 'query-read-texts lyskom-pers-no to-conf t 0)) (read-info nil)) (lyskom-replace-membership membership) (read-list-delete-read-info to-conf lyskom-to-do-list) (read-list-delete-read-info to-conf lyskom-reading-list) (setq read-info (lyskom-create-read-info 'CONF (blocking-do 'get-conf-stat to-conf) (lyskom-get-current-priority) (listify-vector (map->text-nos (blocking-do 'get-map to-conf (membership->last-text-read membership) lyskom-max-int))))) (read-list-enter-first read-info lyskom-to-do-list) (read-list-enter-first read-info lyskom-reading-list))))) ;;;;; -*-coding: iso-8859-1;-*- ;;;;; ;;;;; $Id: lyskom-rest.el,v 44.253 2005/01/19 13:41:27 _cvs_pont_lyskomelisp Exp $ ;;;;; Copyright (C) 1991-2002 Lysator Academic Computer Association. ;;;;; ;;;;; This file is part of the LysKOM Emacs LISP client. ;;;;; ;;;;; LysKOM is free software; you can redistribute it and/or modify it ;;;;; under the terms of the GNU General Public License as published by ;;;;; the Free Software Foundation; either version 2, or (at your option) ;;;;; any later version. ;;;;; ;;;;; LysKOM is distributed in the hope that it will be useful, but WITHOUT ;;;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;;;;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ;;;;; for more details. ;;;;; ;;;;; You should have received a copy of the GNU General Public License ;;;;; along with LysKOM; see the file COPYING. If not, write to ;;;;; Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, ;;;;; or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, ;;;;; MA 02139, USA. ;;;;; ;;;;; Please mail bug reports to bug-lyskom@lysator.liu.se. ;;;;; ;;;; ================================================================ ;;;; ================================================================ ;;;; ;;;; File: lyskom-rest.el ;;;; ;;;; This is the rest of what was once the entire source code of the ;;;; client. Now most of the source resides in other files. Eventually ;;;; the functions in here will be distributed out to other files. ;;;; Below follows the original header of the LysKOM elisp client: ;;;; ;;;; ================================================================ ;;;; ;;;; Simple LysKOM elisp client. ;;;; ;;;; Originally written by Per Cederqvist. ;;;; ;;;; Heavily hacked by: ;;;; Thomas Bellman ;;;; Linus Tolke ;;;; Inge Wallin ;;;; David K}gedal ;;;; David Byers ;;;; and others. ;;;; ;;;; Some ideas stolen from lpmud.el written by Lars Willf|r and Thomas Bellman ;;;; ;;;; Conventions: ;;;; ;;;; All functions, variables etc follow one of these conventions: ;;;; lyskom- general functions. ;;;; cache- cache-routines. ;;;; initiate- call a service. (Might look up in cache) ;;;; kom- user kommands. ;;;; lyskom-parse- parse (part of) a reply from the server. ;;;; these are found in parse.el ;;;; lyskom-edit- Things related to the editing of texts. ;;;; {lyskom,kom}-edit-options- ;;;; things related to editing options ;;;; (found in flags.el) ;;;; {lyskom,kom}-prioritize- ;;;; things related to the prioritize ;;;; buffer. The file is prioritize.el ;;;; {lyskom,kom}-{completing-read,completing,complete}- ;;;; things related to ;;;; lyskom-completing-read. Found in ;;;; completing-read.el ;;;; lyskom-*-hook hooks. ;;;; ;;;; Three plus-signs (+++) in the code marks a place where more ;;;; work is needed. ;;;; (eval-when-compile (require 'lyskom-command "command") (require 'lyskom-menus "menus") (require 'lyskom-clienttypes "clienttypes.el")) (setq lyskom-clientversion-long (concat lyskom-clientversion-long "$Id: lyskom-rest.el,v 44.253 2005/01/19 13:41:27 _cvs_pont_lyskomelisp Exp $\n")) ;;;; ================================================================ ;;;; New errors. (put 'lyskom-protocol-error 'error-conditions '(error lyskom-error lyskom-protocol-error)) (put 'lyskom-protocol-error 'error-message "LysKOM protocol error") (put 'lyskom-internal-error 'error-conditions '(error lyskom-error lyskom-internal-error)) (put 'lyskom-internal-error 'error-message "Internal LysKOM error") (put 'lyskom-format-error 'error-conditions '(error lyskom-error lyskom-format-error)) (put 'lyskom-internal-error 'error-message "Internal LysKOM format error") (put 'lyskom-error 'error-conditions '(error)) (put 'lyskom-error 'error-message "LysKOM error") ;;; ================================================================ ;;; Global variables ;;; (defvar lyskom-unread-mode-line nil) (defvar lyskom-unread-title-format nil) ;;; ================================================================ ;;; Error reporting from a number of commands. ;;; ;;; Author: Inge Wallin (defun lyskom-get-error-text (errno &optional error-descriptions) "Get a string which is the error ERRNO in plain text." (let ((custom-error (or (cdr (assq errno error-descriptions)) (cdr (assq (car (rassq errno lyskom-error-codes)) error-descriptions))))) (if custom-error (lyskom-get-string custom-error) (or (lyskom-try-get-string (intern (concat "error-" (number-to-string errno))) 'lyskom-error-texts) (lyskom-format 'error-not-found errno))))) (defun lyskom-report-command-answer (answer &optional errno error-descriptions) "Handles a void return from call to the server." (if answer (lyskom-insert-string 'done) (lyskom-insert-string 'nope) (lyskom-insert-error errno nil error-descriptions)) answer) (defun lyskom-insert-error (&optional errno err-stat error-descriptions) "Insert an error message describing ERRNO and ERR-STAT. If ERRNO and ERR-STAT are not supplied, use lyskom-errno and lyskom-err-stat instead. If only ERRNO is supplied, use the empty string for ERR-STAT. If ERROR-DESCRIPTIONS is supplied, it should be an alist with error numbers as the cars and error descriptions (symbols) as the cdr. The symbol will be used to get a description of the corresponding error." (lyskom-format-insert 'error-code (lyskom-get-error-text (or errno lyskom-errno) error-descriptions) (or errno lyskom-errno) (or err-stat (if errno "" lyskom-err-stat)))) (defun lyskom-current-error () "Return a string describing the current error" (lyskom-format 'error-code (lyskom-get-error-text lyskom-errno) lyskom-errno lyskom-err-stat)) ;;; ---------------------------------------------------------------- ;;; Author: Aronsson (defun lyskom-tell-internat (key) "Same as lyskom-tell-server, but use a key to a list of phrases." ;; The server at Lysator produces a lot of network traffic. The ;; solution should to be less verbose. This is very interesting ;; anymore, anyway. (lyskom-tell-server (lyskom-tell-string key))) ;;; Resume operation after a crash. (defun kom-recover (&optional refetch) "Try to recover from an error. If the optional argument REFETCH is non-nil or the funcion is called interactively, all caches are cleared and the membership is re-read." (interactive (list t)) (lyskom-init-parse lyskom-buffer) (setq lyskom-call-data nil) (setq lyskom-pending-calls nil) (setq lyskom-output-queues (make-vector 10 nil)) (let ((i 0)) (while (< i 10) (aset lyskom-output-queues i (lyskom-queue-create)) (++ i))) (setq lyskom-number-of-pending-calls 0) (setq lyskom-is-parsing nil) (when refetch (clear-all-caches) (lyskom-refetch)) (lyskom-tell-internat 'kom-tell-recover) (lyskom-end-of-command)) ;;; ================================================================ ;;; Run default command. ;;; Author: Tommy Persson (defun kom-page-next-command () "Scroll the bottom to the top and run the next command if it should be run" (interactive) (if (pos-visible-in-window-p (point-max)) (progn (goto-char (point-max)) (recenter 0) (sit-for 0) ; FIXME: emacs-21.0.94 workaround (lyskom-next-command)) (recenter 0) (sit-for 0) ; FIXME: emacs-21.0.94 workaround (move-to-window-line -1) (lyskom-set-last-viewed))) ;;; Author: Lars Willf|r (defun kom-next-command () "Run next command or scroll one page." (interactive) (if (pos-visible-in-window-p (point-max)) (lyskom-next-command) (move-to-window-line -1) (lyskom-set-last-viewed) (lyskom-scroll) (if (< (window-start) lyskom-last-viewed) (lyskom-xemacs-or-gnu (let ((overlay (make-extent lyskom-last-viewed (save-excursion (goto-char lyskom-last-viewed) (end-of-line) (forward-char 1) (point))))) (set-extent-priority overlay 1000) (set-extent-face overlay kom-mark-face) (add-timeout 2 'delete-extent overlay)) (let ((overlay (make-overlay lyskom-last-viewed (save-excursion (goto-char lyskom-last-viewed) (end-of-line) (forward-char 1) (point))))) (overlay-put overlay 'face kom-mark-face) (overlay-put overlay 'priority 1000) (run-at-time 2 nil 'delete-overlay overlay)))))) (defun kom-line-next-command () "Run next command or scroll one line." (interactive) (if (pos-visible-in-window-p (point-max)) (lyskom-next-command) (move-to-window-line 1) (lyskom-set-last-viewed) (lyskom-scroll))) ;;; Author: Per Cederqvist (defun lyskom-next-command () "Run next command." (let ((saved-buffer (current-buffer))) (unwind-protect (progn (setq lyskom-doing-default-command t) (cond ((eq lyskom-command-to-do 'next-pri-text) (lyskom-view-priority-text)) ((eq lyskom-command-to-do 'next-text) (kom-view-next-text)) ((eq lyskom-command-to-do 'reedit-text) (kom-re-edit-next-text)) ((eq lyskom-command-to-do 'next-pri-session) (kom-go-to-pri-session)) ((eq lyskom-command-to-do 'next-conf) (kom-go-to-next-conf)) ((eq lyskom-command-to-do 'next-pri-conf) (lyskom-go-to-pri-conf)) ((eq lyskom-command-to-do 'when-done) (let ((command (lyskom-what-to-do-when-done))) (cond ((or (stringp command) (vectorp command)) (execute-kbd-macro command)) ((commandp command) (call-interactively command)) (t (lyskom-start-of-command nil) (lyskom-end-of-command))))) ((eq lyskom-command-to-do 'unknown) (lyskom-insert (lyskom-get-string 'wait-for-server))) (t (signal 'lyskom-internal-error '(kom-next-command))))) (condition-case nil (save-excursion (set-buffer saved-buffer) (setq lyskom-doing-default-command nil)) (error nil))))) ;;; ================================================================ ;;; View text. (defun kom-initial-digit-view () (interactive) (setq unread-command-events (cons last-command-event unread-command-events)) (call-interactively 'kom-view nil)) (defun kom-view (text-no) "View text number TEXT-NO." (interactive "P") (unwind-protect (progn (let ((kom-page-before-command nil)) (lyskom-start-of-command 'kom-view) (lyskom-tell-internat 'kom-tell-review)) (unless (and (null current-prefix-arg) (lyskom-plusp text-no)) (let ((current-prefix-arg text-no)) (setq text-no (lyskom-read-text-no-prefix-arg 'review-text-q)))) (cond (text-no (when (or (not (listp kom-page-before-command)) (memq 'kom-view kom-page-before-command)) (recenter 1) (sit-for 0) ; FIXME: emacs-21.0.94 workaround ) (lyskom-tell-internat 'kom-tell-review) (lyskom-format-insert 'review-text-no text-no) (unless kom-review-uses-cache (cache-del-text-stat text-no)) (lyskom-view-text text-no)) (t (lyskom-insert 'confusion-what-to-view)))) (lyskom-end-of-command))) (defun kom-initial-digit-unread () (interactive) (setq unread-command-events (cons last-command-event unread-command-events)) (call-interactively 'kom-mark-unread nil)) (def-kom-command kom-mark-unread (text-no) "Make a single text unread. This command is functional only on servers that support making texts unread." (interactive (list (lyskom-read-text-no-prefix-arg 'unread-text-q))) (lyskom-format-insert 'marking-text-unread text-no) (lyskom-report-command-answer (lyskom-mark-unread text-no))) (defun lyskom-mark-unread (text-no) "Mark text TEXT-NO in all conferences. Returns non-nil if successful." (let ((text-stat (blocking-do 'get-text-stat text-no)) (marked-unread nil)) (and text-stat (let ((result (lyskom-traverse misc-info (text-stat->misc-info-list text-stat) (when (memq (misc-info->type misc-info) lyskom-recpt-types-list) (let* ((mship (lyskom-get-membership (misc-info->recipient-no misc-info))) (recipient (and mship (blocking-do 'get-conf-stat (misc-info->recipient-no misc-info))))) (when (and mship recipient) (if (not (blocking-do 'mark-as-unread (misc-info->recipient-no misc-info) (misc-info->local-no misc-info))) (lyskom-traverse-break 'error) (when (lyskom-visible-membership mship) (setq marked-unread t) (unless (read-list-enter-text text-no recipient lyskom-to-do-list) (let ((info (lyskom-create-read-info 'CONF recipient (membership->priority mship) (lyskom-create-text-list (list text-no))))) (read-list-enter-read-info info lyskom-to-do-list) (if (= lyskom-current-conf (conf-stat->conf-no recipient)) (read-list-enter-read-info info lyskom-reading-list)))))))))))) (cond (result nil) (marked-unread t) (t (setq lyskom-errno -1) nil)))))) ;;;; ================================================================ ;;;; Re-edit text (def-kom-command kom-re-edit-next-text () "Display a buffer containing a failed text submission. This pseudo command is only invoked from the prompt after submission of a text failed." (interactive) (let ((el (read-list->first lyskom-reading-list))) (set-read-list-del-first lyskom-reading-list) (if (buffer-live-p (read-info->misc el)) (lyskom-display-buffer (read-info->misc el)) (lyskom-format-insert 'text-buffer-missing)))) ;;;; ================================================================ ;;;; Go to pri session (def-kom-command kom-go-to-pri-session () "Go to a prioritized session with unreads. This pseudo command is generally invoked frmo the prompt when there is a session with unread texts that has a higher priority than the current session. See `kom-server-priority' and `kom-server-priority-breaks' for settings to control session priorities." (interactive) (let ((session (lyskom-get-prioritized-session))) (if (or (null session) (eq session (current-buffer)) (not (buffer-live-p session))) (lyskom-insert 'no-such-kom-session) (lyskom-switch-to-kom-buffer session)))) ;;;; ================================================================ ;;;; View next text. (defun kom-view-next-new-text () "Display next new text (putting all review constructs at the end of this conf)." (interactive) (let ((len (read-list-length lyskom-reading-list)) (finished nil)) (while (and (not finished) (> len 1)) (let ((type (read-info->type (read-list->first lyskom-reading-list)))) (cond ((memq type lyskom-review-types-list) (read-list-rotate lyskom-reading-list)) ((memq type lyskom-comment-types-list) (set-read-list-del-first lyskom-reading-list)) (t (setq finished t)))) (-- len))) (kom-view-next-text)) ;;; Modified to handle filters (def-kom-command kom-view-next-text () "Display the next unread text. This is the most common default command." (interactive) (lyskom-tell-internat 'kom-tell-read) (let ((action 'next-text)) (while (eq action 'next-text) (if (read-list-isempty lyskom-reading-list) (progn (if (/= 0 lyskom-current-conf) (lyskom-insert-string 'completely-read-conf) (lyskom-insert-string 'not-in-any-conf)) (setq action nil)) (progn (let* ((tri (read-list->first lyskom-reading-list)) (text-no (car (text-list->texts (read-info->text-list tri)))) (type (read-info->type tri)) (priority (read-info->priority (read-list->first lyskom-reading-list))) (is-review-tree (memq type '(REVIEW-TREE))) (is-review (or (memq type '(REVIEW REVIEW-MARK REVIEW-FAQ)) is-review-tree)) (mark-as-read (not is-review))) (when (or is-review (eq type 'REVIEW-FAQ-TREE)) (set-text-list->texts (read-info->text-list tri) (delq text-no (text-list->texts (read-info->text-list tri)))) ;First entry only (unless kom-review-uses-cache (cache-del-text-stat text-no))) (setq action (lyskom-view-text text-no mark-as-read (and kom-read-depth-first (not is-review)) (read-info->conf-stat (read-list->first lyskom-reading-list)) priority is-review-tree (not is-review) (memq type '(REVIEW REVIEW-MARK)))) (if mark-as-read (lyskom-is-read text-no) (read-list-delete-text nil lyskom-reading-list) (read-list-delete-text nil lyskom-to-do-list)))))))) ;;; Modified to handle filters ;; This is horribly ugly. It acts like a user command, but it isn't. (defun lyskom-view-priority-text () "Display the first text from the next conference on the lyskom-to-do-list. Cannot be called from a callback." (lyskom-start-of-command 'kom-view-next-text) (unwind-protect (progn (lyskom-tell-internat 'kom-tell-read) (let* ((tri (read-list->first lyskom-to-do-list)) (priority (read-info->priority (read-list->first lyskom-reading-list))) (text-no (car (text-list->texts (read-info->text-list tri))))) (lyskom-is-read text-no) (lyskom-view-text text-no t nil (read-info->conf-stat tri) priority nil t)) (lyskom-wait-queue 'main)) (lyskom-end-of-command))) (defun lyskom-is-read (text-no) "Remove TEXT-NO from the list of texts to read. Deletes TEXT-NO from lyskom-reading-list and lyskom-to-do-list. Adds info in lyskom-membership. This function only modifies the internal state of the client. It does not mark the text as read in the server. That function is performed by lyskom-mark-as-read." (read-list-delete-text text-no lyskom-reading-list) (read-list-delete-text text-no lyskom-to-do-list) (initiate-get-text-stat 'main 'lyskom-is-read-handler text-no) (setq lyskom-normally-read-texts (cons text-no lyskom-normally-read-texts))) (defun lyskom-is-read-handler (text-stat) "Update lyskom-membership for all recipients to TEXT-STAT." (lyskom-traverse misc (text-stat->misc-info-list text-stat) (if (memq (misc-info->type misc) '(RECPT BCC-RECPT CC-RECPT)) (let ((membership (lyskom-try-get-membership (misc-info->recipient-no misc)))) (when membership (set-membership->read-texts membership (vconcat (vector (misc-info->local-no misc)) (membership->read-texts membership)))))))) ;;; ================================================================ ;;; Go to next conf. (def-kom-command kom-go-to-next-conf (&optional num) "Go to next conference with unread texts. The current conference is moved to the end of the list of conferences with unread texts. A numeric prefix argument is interpreted similar to in `kom-list-news': with a positive argument go to the next conference with at least that many unread. With a negative number, go to a conference with at most that many unread texts." (interactive "P") (let ((conf-stat nil) (num-arg (cond ((numberp num) num) ((and (listp num) (numberp (car num))) (car num)) (t nil)))) (when num-arg (let ((read-list (cdr (lyskom-list-news))) (msgs-conf nil) (unreads nil) (at-least (if (< num-arg 0) 1 num-arg)) (at-most (and (< num-arg 0) (- num-arg)))) (while (and read-list (null conf-stat)) (setq msgs-conf (car read-list)) (setq read-list (cdr read-list)) (setq unreads (car msgs-conf)) (when (and (>= unreads at-least) ; unreads within lower bound (or (not at-most) (<= unreads at-most))) ; unreads within upper bound (setq conf-stat (cdr msgs-conf)))))) (if (and num-arg (null conf-stat)) (lyskom-insert-string 'no-unreads-shown) (when (lyskom-check-go-to-conf conf-stat) (lyskom-maybe-move-unread t) (if conf-stat (lyskom-go-to-conf conf-stat) (lyskom-go-to-next-conf)))))) (defun lyskom-go-to-pri-conf () "Go to the conf with higher priority. This differs from kom-go-to-next-conf only in the place where the yet unread in the current conf is placed." (lyskom-start-of-command 'kom-go-to-next-conf) (when (lyskom-check-go-to-conf) (lyskom-maybe-move-unread nil) (lyskom-go-to-next-conf) (lyskom-end-of-command))) (defun lyskom-go-to-next-conf () "Actually go to the next conference on the lyskom-to-do-list" ;; Copy first element on lyskom-to-do-list to lyskom-reading-list. (if (not (read-list-isempty lyskom-to-do-list)) (let ((conf-stat (read-info->conf-stat (read-list->first lyskom-to-do-list)))) (if conf-stat (progn (lyskom-set-mode-line conf-stat) (read-list-enter-first (read-list->first lyskom-to-do-list) lyskom-reading-list) (lyskom-enter-conf conf-stat (read-list->first lyskom-to-do-list))) (read-list-enter-first (read-list->first lyskom-to-do-list) lyskom-reading-list))) (lyskom-insert-string 'all-conf-unread-r) (lyskom-set-mode-line (lyskom-get-string 'all-conf-unread-s)))) (defun lyskom-maybe-move-unread (bury) "Empty the reading list. If the argument BURY is non-nil and there are unread articles left in the reading list then the conf is inserted last in the to do list." (if (not (read-list-isempty lyskom-reading-list)) (progn (if bury (let ((conf-no nil) (r 0)) (while (and (not conf-no) (< r (read-list-length lyskom-reading-list))) (if (eq (read-info->type (read-list->nth lyskom-reading-list r)) 'CONF) (setq conf-no (conf-stat->conf-no (read-info->conf-stat (read-list->nth lyskom-reading-list r)))) (++ r))) (if conf-no (progn (read-list-delete-read-info conf-no lyskom-to-do-list) (read-list-enter-first (read-list->nth lyskom-reading-list r) lyskom-to-do-list) (read-list-rotate lyskom-to-do-list))))) (set-read-list-empty lyskom-reading-list)))) (defun lyskom-check-go-to-conf (&optional conf) "Check if it is OK to go to conf CONF (a conf-stat). It is assumed that lyskom-pers-no is a member of the conference. This function interacts with the buffer and the user. If CONF is nil, check the first conf on the to-do list." (let* ((conf-stat (or conf (read-info->conf-stat (read-list->first lyskom-to-do-list)))) (mship (and conf-stat (lyskom-get-membership (conf-stat->conf-no conf-stat) t))) (type nil) (continue t)) (when (and conf-stat mship) (setq type (membership->type mship)) (when (membership-type->invitation type) ;;; State the invitation,give the user a chance to accept it ;;; Leave the conf if the user does not want it (lyskom-format-insert 'your-invited conf-stat (membership->created-by mship)) (if (lyskom-j-or-n-p (lyskom-get-string 'accept-invitation)) (setq continue (lyskom-add-member (blocking-do 'get-conf-stat lyskom-pers-no) conf-stat)) (let ((kom-unsubscribe-makes-passive nil)) (lyskom-sub-member (blocking-do 'get-conf-stat lyskom-pers-no) conf-stat) (setq continue nil)))) (when (and continue (membership-type->secret type)) (lyskom-format-insert-before-prompt 'bug-secret-mship conf-stat)) (when (and continue (membership-type->passive type)) ;;; Offer the user a chance to become an active member ;;; If the offer is refused, boot the user off the conference (lyskom-format-insert 'enter-passive conf-stat) (setq continue nil) (if (lyskom-j-or-n-p (lyskom-format 'convert-passive conf-stat)) (setq continue (lyskom-add-member (blocking-do 'get-conf-stat lyskom-pers-no) conf-stat)) (setq continue nil))) ) ;;; Return the result continue)) (defun lyskom-reject-recommendation (conf-no) "Record that we have rejected an invitation to CONF-NO by PERS-NO" (unless (lyskom-recommendation-already-rejected conf-no) (setq lyskom-rejected-recommendations (cons conf-no lyskom-rejected-recommendations)) (initiate-modify-conf-info 'background nil lyskom-pers-no nil (list (lyskom-create-aux-item 0 10001 nil nil (lyskom-create-aux-item-flags nil nil t nil nil nil nil nil) 0 (format "%d" conf-no)))))) (defun lyskom-recommendation-already-rejected (conf-no) "Return non-nil if we have rejected recommendation for CONF-NO" (member conf-no lyskom-rejected-recommendations)) (defun lyskom-update-rejected-recommendations () "Update the list of rejected recommendations" (setq lyskom-rejected-recommendations nil) (let* ((conf-stat (blocking-do 'get-conf-stat lyskom-pers-no)) (aux-list (and conf-stat (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 10001)))) (lyskom-traverse item aux-list (when (string-match "^\\([0-9]+\\)" (aux-item->data item)) (setq lyskom-rejected-recommendations (cons (string-to-int (match-string 1 (aux-item->data item))) lyskom-rejected-recommendations)))))) (defun lyskom-startup-check-recommended-memberships () "Create invitations for new membership recommendations" (let ((recommendations (filter-list (lambda (rec) (not (lyskom-recommendation-already-rejected (car rec)))) (mapcar (lambda (aux) (when (string-match "^\\([0-9]+\\)\\( [0-9]+\\)?\\( [01]+\\)?" (aux-item->data aux)) (let* ((conf-no (string-to-int (match-string 1 (aux-item->data aux)))) (priority (and conf-no (match-string 2) (string-to-int (match-string 2 (aux-item->data aux))))) (mship-type (and priority (match-string 3) (match-string 3 (aux-item->data aux))))) (list conf-no priority mship-type (aux-item->creator aux))))) (lyskom-get-aux-item (server-info->aux-item-list lyskom-server-info) 29)))) (collector (make-collector))) ;; At this point RECOMMENDATIONS contains a list with one element ;; per previously not rejected conference membership recommendations ;; (including the ones we are actually members of). (lyskom-traverse rec recommendations (initiate-query-read-texts 'main 'collector-push lyskom-pers-no (car rec) nil 0 collector)) (lyskom-wait-queue 'main) ;; Now delete recommendations that we are already members of (lyskom-traverse mship (collector->value collector) (when mship (setq recommendations (delq (assq (membership->conf-no mship) recommendations) recommendations)))) ;; At this point recommendations contains only the conferences ;; that we have not rejected and that we are not already members ;; of. (let ((pers-conf-stat (blocking-do 'get-conf-stat lyskom-pers-no))) (lyskom-traverse rec recommendations (let ((conf-stat (blocking-do 'get-conf-stat (elt rec 0)))) (when conf-stat (lyskom-format-insert 'has-recommended-conf (elt rec 3) (elt rec 0)) (if (lyskom-j-or-n-p (lyskom-format 'accept-recommendation (elt rec 0))) (lyskom-add-member pers-conf-stat conf-stat nil nil (and (elt rec 1) (list (elt rec 1))) nil) (lyskom-reject-recommendation (elt rec 0))))))))) (defun lyskom-clean-read-faqs (pers-no) "Remove all read-faq aux-items from PERS-NO that correspond to texts that are no longer FAQs or are missing." (let ((conf-stat (blocking-do 'get-conf-stat pers-no))) (when conf-stat (lyskom-traverse item (lyskom-get-aux-item (conf-stat->aux-items conf-stat) 10000) (when (string-match "^\\([0-9]+\\) \\([0-9]+\\)" (aux-item->data item)) (let ((conf-no (string-to-int (match-string 1 (aux-item->data item)))) (text-no (string-to-int (match-string 2 (aux-item->data item))))) (initiate-get-text-stat 'background 'lyskom-clean-read-faqs-1 text-no pers-no conf-no item))))))) (defun lyskom-clean-read-faqs-1 (text-stat pers-no conf-no item) "Callback for lyskom-clean-read-faqs" (let ((cmp (int-to-string conf-no))) (when (or (null text-stat) (not (lyskom-traverse aux (lyskom-get-aux-item (text-stat->aux-items text-stat) 28) (when (string= cmp (aux-item->data aux)) (lyskom-traverse-break t))))) (initiate-modify-conf-info 'background nil pers-no (list (aux-item->aux-no item)) nil) ))) (defun lyskom-enter-conf (conf-stat read-info) "Tell server which conf the user is reading. Prints the name and amount of unread in the conference we just went to according to the value of kom-print-number-of-unread-on-entrance. Args: CONF-STAT READ-INFO" (let ((from-conf lyskom-current-conf) (to-conf (conf-stat->conf-no conf-stat))) (lyskom-run-hook-with-args 'lyskom-change-conf-hook from-conf to-conf) (lyskom-run-hook-with-args 'kom-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat)) (unless lyskom-is-anonymous (initiate-pepsi 'main nil to-conf)) (setq lyskom-current-conf to-conf) (lp--update-buffer from-conf) (lp--update-buffer to-conf) (let ((num-unread (text-list->length (read-info->text-list read-info)))) (lyskom-enter-conf-print-unread conf-stat num-unread) (lyskom-run-hook-with-args 'lyskom-after-change-conf-hook from-conf to-conf) (lyskom-run-hook-with-args 'kom-after-change-conf-hook lyskom-current-conf (conf-stat->conf-no conf-stat))))) (defun lyskom-enter-conf-print-unread (conf num) "Print information about unread (if requested) when entering a conf. CONF is the conference and NUM is the number of unread in the conference." (let ((faq-list (lyskom-get-unread-faqs conf))) (lyskom-format-insert "%#1M" conf) (when (or (eq num 0) kom-print-number-of-unread-on-entrance faq-list) (lyskom-insert " - ")) (cond ((eq num 0) (lyskom-format-insert 'conf-all-read conf)) (kom-print-number-of-unread-on-entrance (lyskom-format-insert 'enter-conf-unread num))) (when faq-list (when (or (eq num 0) kom-print-number-of-unread-on-entrance) (lyskom-insert ", ")) (lyskom-format-insert 'enter-conf-unread-faq (length faq-list))) (lyskom-insert (lyskom-conf-type-marker conf)) (lyskom-format-insert ".\n") (lyskom-present-unread-faqs conf faq-list))) (defun lyskom-leave-current-conf () "Leave the current conference without going to another one." (let ((from-conf lyskom-current-conf)) (set-read-list-empty lyskom-reading-list) (lyskom-run-hook-with-args 'lyskom-change-conf-hook from-conf 0) (setq lyskom-current-conf 0) (initiate-pepsi 'main nil 0) (lyskom-run-hook-with-args 'lyskom-after-change-conf-hook from-conf 0) )) ;;;================================================================ (defun lyskom-set-mode-line (&optional conf) "Sets mode-line-conf-name to the name of the optional argument conf CONF. CONF can be a a conf-stat or a string." (let ((name (cond ((null conf) (if (zerop lyskom-current-conf) (lyskom-get-string 'not-present-anywhere) (initiate-get-conf-stat 'modeline 'lyskom-set-mode-line lyskom-current-conf) nil)) ((stringp conf) conf) ((lyskom-conf-stat-p conf) (conf-stat->name conf)) (t ""))) (conf-no (if (lyskom-conf-stat-p conf) (conf-stat->conf-no conf) 0)) (unread -1) (total-unread 0) (letters 0) (len 0) (read-info-list nil)) ;; Set unread to the number of unread texts in CONF. (setq read-info-list (read-list->all-entries lyskom-to-do-list)) ;; This was weird. Someone had begun to write an if, but ;; this was all there was: (if (while read-info-list (if (read-info->conf-stat (car read-info-list)) (progn (setq len (text-list->length (read-info->text-list (car read-info-list)))) (if (= conf-no (conf-stat->conf-no (read-info->conf-stat (car read-info-list)))) (setq unread len)) (if (= lyskom-pers-no (conf-stat->conf-no (read-info->conf-stat (car read-info-list)))) (setq letters len)) (setq total-unread (+ total-unread len)))) (setq read-info-list (cdr read-info-list))) (if (= unread -1) (setq unread 0)) (if (null name) nil (setq mode-line-conf-name (substring (concat (if (lyskom-conf-stat-p conf) (if (not (eq lyskom-session-priority kom-default-session-priority)) (format "(%d/%d:%d) " unread total-unread lyskom-session-priority) (format "(%d/%d) " unread total-unread)) "") name (make-string 27 ? )) 0 27))) (if (zerop total-unread) (lyskom-remove-unread-buffer lyskom-buffer) (lyskom-add-unread-buffer lyskom-buffer)) (if (zerop letters) (lyskom-remove-unread-buffer lyskom-buffer t) (lyskom-add-unread-buffer lyskom-buffer t)) (lyskom-mode-name-from-host) (force-mode-line-update))) ;;;; ================================================================ ;;;; Scrolling and text insertion. (defvar lyskom-trim-buffer-delete-to) (defun lyskom-trim-buffer () "Trim the size of a lyskom buffer to lyskom-max-buffer-size returns t if it trimmed the buffer, nil otherwise." (when (and kom-max-buffer-size (> (- (buffer-size) kom-trim-buffer-minimum) kom-max-buffer-size)) (lyskom-save-excursion (let ((lyskom-trim-buffer-delete-to (- (buffer-size) kom-max-buffer-size)) (inhibit-read-only t)) (goto-char (point-min)) (while (< (point) lyskom-trim-buffer-delete-to) (forward-line 1)) (setq lyskom-trim-buffer-delete-to (point)) (run-hooks 'lyskom-trim-buffer-hook) (delete-region (point-min) lyskom-trim-buffer-delete-to))) t)) ;;USER-HOOK: lyskom-garb-lyskom-buffer-to-file (defun lyskom-garb-lyskom-buffer-to-file () "Appends the deleted initial portions of the buffer to a file. Put this function in your lyskom-trim-buffer-hook and set kom-max-buffer-size to something clever, and the trimmed text will automagically flow into your lyskom log file." (append-to-file 1 lyskom-trim-buffer-delete-to (expand-file-name (concat "~/" (buffer-name) "-history")))) (defun lyskom-scroll () "Scroll screen if necessary. The position lyskom-last-viewed will always remain visible." ;; Find a window to scroll. Scroll the selected window if that shows LysKOM. ;; Otherwise scroll any window currently showing LysKOM. (let ((win (cond ((eq (window-buffer (selected-window)) (current-buffer)) (selected-window)) (t nil)))) (when (and win (not (pos-visible-in-window-p (point-max)))) (goto-char (point-max)) (recenter -1) (unless (pos-visible-in-window-p lyskom-last-viewed) (set-window-start win lyskom-last-viewed) (move-to-window-line -1) (vertical-motion 1) (when (not (pos-visible-in-window-p)) (forward-char -1) (when (> (current-column) (window-width)) (backward-char (+ (- (current-column) (window-width)) 6))) ))))) (defun lyskom-next-property-bounds (from to sym) "Sort of like next-text-property-bounds, but limited at the front and back, and works even if from has the property." (let ((result (cond ((get-text-property from sym) (cons from (next-single-property-change from sym))) ((next-single-property-change from sym) (let ((start (next-single-property-change from sym))) (cons start (next-single-property-change start sym))))))) (when result (cond ((null (cdr result)) (setcdr result (or to (point-max)))) ((and from (< (car result) from)) (setcar result from)) ((and to (> (cdr result) to)) (setcar result to)))) result)) (defun lyskom-do-special-inserts (start end sym) (condition-case var (let ((bounds (lyskom-next-property-bounds start end sym)) (next (make-marker)) (fn nil)) (while bounds (set-marker next (cdr bounds)) (setq fn (get-text-property (car bounds) sym)) (remove-text-properties (car bounds) (cdr bounds) (list sym)) (condition-case val (funcall (if (listp fn) (car fn) fn) (car bounds) (cdr bounds) (if (listp fn) (cdr fn) nil)) (error (apply 'message "%S" val))) (setq start next) (setq bounds (lyskom-next-property-bounds (1- start) (point-max) sym)))) (error (lyskom-ignore var)))) (defun lyskom-do-insert (string) (let ((start (point))) (insert string) (lyskom-do-special-inserts start (point) 'lyskom-fill) (lyskom-do-special-inserts start (point) 'lyskom-overlay) (lyskom-do-special-inserts start (point) 'special-insert) )) (defun lyskom-insert (string) "Insert STRING last in current buffer. Leaves the point at the end of the buffer if possible without scrolling past lyskom-last-viewed (generally the most recent prompt.) Leaves the point at the end of the window if not possible. If buffer is not on screen then doesn't move point." (when (symbolp string) (setq string (lyskom-get-string string))) (let ((was-at-max (= (save-excursion (end-of-line) (point)) (point-max)))) (save-excursion (goto-char (point-max)) (let ((inhibit-read-only t)) (lyskom-do-insert string)) (lyskom-trim-buffer)) (let ((window (get-buffer-window (current-buffer)))) (if (and window was-at-max) (if (pos-visible-in-window-p (point-max) window) (goto-char (point-max)) (and kom-continuous-scrolling (lyskom-scroll))))))) (defun lyskom-insert-at-point (string) "Insert STRING in the current buffer at point." (let ((inhibit-read-only t)) (lyskom-do-insert string)) (lyskom-trim-buffer)) (defun lyskom-insert-before-prompt (string) "Insert STRING just before the prompt of if no prompt then just buffers. If prompt on screen then do the scroll if necessary. The strings buffered are printed before the prompt by lyskom-update-prompt." ;; ;; This is the policy for moving point: ;; ;; old-point-max is the point-max before the text is inserted ;; new-point-max is the point-max after the text is inserted ;; ;; If point /= old-point-max, leave the point where it is, and don't ;; scroll the window. ;; ;; If point = old-point-max, set it to new-point-max, and if the ;; buffer is in a window, make sure that point is visible. ;; (cond ((and lyskom-executing-command (not (eq lyskom-is-waiting t))) ;; Don't insert the string until the current command is finished. (if (null lyskom-to-be-printed-before-prompt) (setq lyskom-to-be-printed-before-prompt (lyskom-queue-create))) (lyskom-queue-enter lyskom-to-be-printed-before-prompt (list string))) (t ;; For some reaseon save-excursion doesn't work as expected (let ((oldpoint (point-marker))) (goto-char (point-max)) (beginning-of-line) (let ((inhibit-read-only t)) ;; Some (all?) xemacsen adds the text-properties on the prompt ;; to text inserted before it. We don't want this, so insert a ;; blank and remove all text-properties from it, insert the ;; text before the blank and finally remove the blank. (insert " ") (backward-char) (remove-text-properties (point) (+ (point) 1) (text-properties-at (point))) (lyskom-do-insert string) (delete-char 1)) (goto-char oldpoint)) (let ((window (get-buffer-window (current-buffer)))) (if (and window (not (pos-visible-in-window-p (point) window))) ;; This mease that the prompt has been pushed off the bottom (save-selected-window (select-window window) (recenter -1))))))) (defun lyskom-message (format-string &rest args) "Like message, but converts iso-8859/1 texts to swascii if necessary. Args: FORMAT-STRING &rest ARGS" (let ((str (apply 'format format-string args))) (message "%s" str))) (defun lyskom-error (format-string &rest args) "Like error, but converts iso-8859/1 texts to swascii if necessary. Args: FORMAT-STRING &rest ARGS" (let ((str (apply 'format format-string args))) (error "%s" str))) (defun lyskom-set-last-viewed () (save-excursion (vertical-motion 0) (setq lyskom-last-viewed (point-marker)))) ;;; ================================================================ ;;; Extended string formatting ;;; Author: David Byers ;;; Original code: Inge Wallin (defvar lyskom-format-format "%\\(=\\|<\\|>\\)?\\(-?[0-9]+\\|-?[0-9]+\\.[0-9]+\\|-?[0-9]+\\.[0-9]+\\.[0-9]+\\)?\\(\\.\\.\\.\\)?\\(:.\\)?\\(#\\([0-9]+\\)\\)?\\(_\\)?\\(:\\)?\\(&\\)?\\([][$@MmPpnrtsdoxlcfgCSDF%?]\\)" "regexp matching format string parts.") (defun lyskom-insert-string (atom) "Find the string corresponding to ATOM and insert it into the LysKOM buffer." (if (stringp atom) (lyskom-insert atom) (lyskom-insert (lyskom-get-string atom)))) (defun lyskom-format-transform-result (state) "Convert a format-state to a string." (let ((result (format-state->result state))) (lyskom-traverse overlay (format-state->delayed-overlays state) (add-text-properties (aref overlay 0) (aref overlay 1) (list 'lyskom-overlay (cons 'lyskom-special-insert-overlay (aref overlay 2))) result)) result)) (defun lyskom-limited-make-overlay (start end) (let ((val (lyskom-xemacs-or-gnu (make-extent start end) (make-overlay start end)))) (when (lyskom-plusp kom-max-overlays) (let ((old (nthcdr (1- kom-max-overlays) lyskom-overlay-pool))) ; (setq lyskom-overlay-pool (lyskom-nbutlast lyskom-overlay-pool (- (length lyskom-overlay-pool) kom-max-overlays))) (mapcar (lambda (o) (lyskom-xemacs-or-gnu (delete-extent o) (delete-overlay o))) old)) (setq lyskom-overlay-pool (cons val lyskom-overlay-pool))) val)) (defun lyskom-special-insert-overlay (start end args) (lyskom-xemacs-or-gnu (let ((overlay (lyskom-limited-make-overlay start end))) (while args (set-extent-property overlay (car args) (car (cdr args))) (setq args (nthcdr 2 args))) (set-extent-priority overlay 1000)) (let ((overlay (lyskom-limited-make-overlay start end))) (while args (overlay-put overlay (car args) (car (cdr args))) (setq args (nthcdr 2 args)))))) (defun lyskom-format (format-string &rest argl) (lyskom-format-transform-result (lyskom-do-format format-string argl))) (defun lyskom-format-insert (format-string &rest argl) "Format and insert a string according to FORMAT-STRING. The string is inserted at the end of the buffer with `lyskom-insert'." (let* ((state (lyskom-do-format format-string argl t)) ;; We have to use a marker, because lyskom-insert may trim ;; the buffer size. (start (point-max-marker)) (deferred (format-state->delayed-content state))) (lyskom-insert (lyskom-format-transform-result state)) (while deferred (let ((defer-info (car deferred)) (m (make-marker))) (set-marker m (+ start (defer-info->pos defer-info))) (set-defer-info->pos defer-info m) (lyskom-defer-insertion defer-info) (setq deferred (cdr deferred)))) (set-marker start nil))) (defun lyskom-format-insert-at-point (format-string &rest argl) "Format and insert a string according to FORMAT-STRING. The string is inserted at point." (let* ((state (lyskom-do-format format-string argl t)) (start (point)) (deferred (format-state->delayed-content state))) (lyskom-insert-at-point (lyskom-format-transform-result state)) (while deferred (let ((defer-info (car deferred)) (m (make-marker))) (set-marker m (+ start (defer-info->pos defer-info))) (set-defer-info->pos defer-info m) (lyskom-defer-insertion defer-info) (setq deferred (cdr deferred)))))) (defun lyskom-format-insert-before-prompt (format-string &rest argl) "Format and insert a string according to FORMAT-STRING. The string is inserted just before the prompt, and if the prompt is not currently visible the text is queued to be inserted when the prompt reappears. Deferred insertions are not supported." (lyskom-insert-before-prompt (lyskom-format-transform-result (lyskom-do-format format-string argl)))) (defun lyskom-do-format (format-string &optional argl allow-defer) "Do the actual formatting and return the resulting format-state." (let ((fmt (cond ((stringp format-string) format-string) ((symbolp format-string) (lyskom-get-string format-string)))) (state nil)) (if (null fmt) (signal 'lyskom-internal-error (list 'lyskom-format-insert ": bad format string")) (save-excursion (if (and (boundp 'lyskom-buffer) lyskom-buffer) (set-buffer lyskom-buffer)) (condition-case error (setq state (lyskom-format-aux (lyskom-create-format-state fmt 0 argl (length argl) "" nil nil nil 0) allow-defer)) (lyskom-format-error (error "LysKOM internal error formatting %s: %s%s (arg %S, got %S)" format-string (nth 1 error) (nth 2 error) (nth 3 error) (nth 4 error)))))) state)) ;;; ;;; If you add a format letter, for goodness' sake, don't forget to ;;; att it to the regexp above too! ;;; (defun lyskom-format-aux (format-state allow-defer) (set-format-state->depth format-state (1+ (format-state->depth format-state))) (let ((format-length (length (format-state->format-string format-state))) (arg-no nil) (pad-length nil) (frac-min nil) (frac-max nil) (pad-string nil) (format-letter nil) (colon-flag nil) (equals-flag nil) (downcase-flag nil) (face-flag nil) (trailer nil) (abort-format nil)) ;; ;; Eat the format string bit by bit ;; (while (and (not abort-format) (< (format-state->start format-state) format-length)) ;; ;; Look for a format letter. If there is none, finish up, ;; otherwise handle each letter separately ;; (if (null (string-match lyskom-format-format (format-state->format-string format-state) (format-state->start format-state))) (progn (set-format-state->result format-state (concat (format-state->result format-state) (substring (format-state->format-string format-state) (format-state->start format-state)))) (set-format-state->start format-state (length (format-state->format-string format-state)))) ;; ;; A format letter has been found ;; (set-format-state->result format-state (concat (format-state->result format-state) (substring (format-state->format-string format-state) (format-state->start format-state) (match-beginning 0)))) (set-format-state->start format-state (match-end 0)) (if (match-beginning 2) (save-match-data (let* ((s (match-string 2 (format-state->format-string format-state)))) (cond ((or (string-match "\\(-?[0-9]+\\)\\.\\([0-9]+\\)\\.\\([0-9]+\\)" s) (string-match "\\(-?[0-9]+\\)\\.\\([0-9]+\\)" s)) (setq pad-length (string-to-int (match-string 1 s))) (setq frac-min (string-to-int (match-string 2 s))) (setq frac-max (string-to-int (or (match-string 3 s) (match-string 2 s))))) (t (setq pad-length (string-to-int s)))))) (setq pad-length nil)) (setq equals-flag (and (match-beginning 1) (aref (match-string 1 (format-state->format-string format-state)) 0)) arg-no (if (match-beginning 6) (string-to-int (match-string 6 (format-state->format-string format-state))) nil) downcase-flag (match-beginning 7) colon-flag (match-beginning 8) face-flag (match-beginning 9) trailer (match-beginning 3) pad-string (and (match-beginning 4) (substring (format-state->format-string format-state) (1+ (match-beginning 4)) (match-end 4))) format-letter (if (match-beginning 10) (aref (format-state->format-string format-state) (match-beginning 10)) (signal 'lyskom-internal-error (list 'lyskom-format-aux (format-state->format-string format-state))))) ;; ;; If the format letter is an end-of-group letter, abort ;; formatting and return to the caller. ;; (if (= ?\] format-letter) (progn (setq abort-format t) (set-format-state->start format-state (match-end 0))) (setq format-state (lyskom-format-aux-help format-state pad-length frac-min frac-max arg-no format-letter equals-flag trailer colon-flag face-flag downcase-flag (or (elt pad-string 0) (if (and (match-beginning 2) (eq (aref (format-state->format-string format-state) (match-beginning 2)) ?0)) ?0 ?\ )) allow-defer)))))) (lyskom-tweak-format-state format-state) (set-format-state->depth format-state (1- (format-state->depth format-state))) format-state) (defun lyskom-format-aux-help (format-state pad-length frac-min frac-max arg-no format-letter equals-flag trailer colon-flag face-flag downcase-flag pad-letter allow-defer) (let ((arg nil) (result nil) (propl nil) (prop-adjust-start 0) (prop-adjust-end 0) (oldpos (length (format-state->result format-state))) (abs-length (cond ((null pad-length) nil) ((< pad-length 0) (- 0 pad-length)) (t pad-length)))) (if (and arg-no (not (eq format-letter ?\?)) (< (format-state->length format-state) arg-no)) (signal 'lyskom-format-error (list 'lyskom-format ": too few arguments"))) (if arg-no (setq arg (nth (1- arg-no) (format-state->argl format-state)))) (cond ;; ;; Format a string or symbol by simply inserting it into the ;; result list ;; ((= format-letter ?l) (setq result (cond ((or (integerp arg) (lyskom-characterp arg)) (make-string pad-length arg)) ((stringp arg) (let ((count (/ pad-length (length arg)))) (apply 'concat (nreverse (cons (substring arg 0 (- pad-length (* (length arg) count))) (make-list count arg)))))) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected char or string)" arg-no arg)))))) ((= format-letter ?s) (setq result (cond ((stringp arg) arg) ((symbolp arg) (symbol-name arg)) (t (signal 'lyskom-format-error (list 'lyskom-format ": argument error (expected string)" arg-no arg))))) (when downcase-flag (setq result (downcase result)))) ;; ;; Format a number by conferting it to a string and inserting ;; it into the result list ;; ((or (= format-letter ?d) (= format-letter ?o) (= format-letter ?x)) (setq result (cond ((integerp arg) (format (format "%%%c" format-letter) arg)) ((and (floatp arg) (= format-letter ?d)) (format "%0.0f" arg)) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected int)" arg-no arg)))))) ((or (= format-letter ?g) (= format-letter ?f) (= format-letter ?e)) (setq result (cond ((numberp arg) (format (if frac-max (format "%%.%d%c" frac-max format-letter) (format "%%%c" format-letter)) arg)) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected number)" arg-no arg))))) (save-match-data (when (and (string-match "\\." result) (string-match "\\.?0+$" result)) (setq result (substring result 0 (match-beginning 0)))) (when (and frac-min (> frac-min 0)) (if (string-match "\\.\\([0-9]*\\)$" result) (setq result (concat result (make-string (max 0 (- frac-min (length (match-string 1 result)))) ?0))) (setq result (concat result "." (make-string frac-min ?0))))))) ((= format-letter ?f) (setq result (cond ((numberp arg) (format "%f" arg)) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected number)" arg-no arg)))))) ;; ;; Format a character by converting it to a string and inserting ;; it into the result list ;; ((= format-letter ?c) (setq result (cond ((integerp arg) (char-to-string (lyskom-int-to-char arg))) ((lyskom-characterp arg) (char-to-string arg)) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected char)" arg-no arg)))))) ;; ;; Format a literal percent character by inserting a string ;; containing it into the result list ;; ((= format-letter ?%) (setq result "%")) ;; ;; Format a command name somewhat specially ;; ((= format-letter ?C) (setq result (cond ((stringp arg) arg) ((vectorp arg) (mapconcat 'single-key-description (append arg nil) " ")) ((and arg (symbolp arg)) (if (memq arg lyskom-commands) (lyskom-command-name arg) (prin1-to-string arg t))) (t (format "(%S)" arg))))) ;; ;; Format a sexp by princing it. Sort of. ;; ((= format-letter ?S) (setq result (format "%S" arg)) (when downcase-flag (setq result (downcase result)))) ;; ;; Format a text property array indicator by retrieving the ;; properties from the argument list and adding a start of ;; new properties to the format state ;; ((= format-letter ?@) (set-format-state->delayed-propl format-state (cons (vector (length (format-state->result format-state)) arg (format-state->depth format-state)) (format-state->delayed-propl format-state)))) ;; ;; Format an overlay ;; ((= format-letter ?$) (when arg (set-format-state->delayed-overlays format-state (cons (vector (length (format-state->result format-state)) nil arg (format-state->depth format-state)) (format-state->delayed-overlays format-state))))) ;; ;; Format a subformat list by recursively formatting the contents ;; of the list, augmenting the result and format state ;; ;; Idea: If this code used lyskom-do-format instead, we could ;; use it to truncate a complex format by using a format string ;; such as: "%17[ %#1s will be truncated %]" ;; ;; This could be useful for faster response when deferring ;; printing. But this function would become more complex and ;; slower. ;; ((= format-letter ?\[) (setq format-state (lyskom-format-aux format-state allow-defer) result nil)) ;; A predicate ;; Get the predicate type and then parse the format string ;; accordingly ((= format-letter ?\?) (unless (string-match "[dbz+]" (format-state->format-string format-state) (format-state->start format-state)) (lyskom-error "Unknown predicate in format string %s (%d)" (format-state->format-string format-state) (format-state->start format-state))) (set-format-state->start format-state (match-end 0)) (let ((predicate-type (elt (match-string 0 (format-state->format-string format-state)) 0))) (cond ;; Plural/singular predicate ;; arg is an integer. Use the first subformat if it is one ;; and the second if it is other than one. ((= predicate-type ?d) (setq format-state (lyskom-format-do-binary-predicate (= arg 1) format-state allow-defer) result nil)) ;; True/false predicate ((= predicate-type ?b) (setq format-state (lyskom-format-do-binary-predicate arg format-state allow-defer) result nil)) ;; Zero/nonzero predicate ((= predicate-type ?z) (setq format-state (lyskom-format-do-binary-predicate (not (zerop arg)) format-state allow-defer) result nil)) ;; Non-negative predicate ((= predicate-type ?+) (setq format-state (lyskom-format-do-binary-predicate (not (lyskom-minusp arg)) format-state allow-defer) result nil)) ))) ((= format-letter ?F) (set-format-state->delayed-propl format-state (cons (vector (length (format-state->result format-state)) `(lyskom-fill ((lambda (start end width) (let ((fill-column (or width (- (window-width 8))))) (fill-region start end))) . ,arg)) (format-state->depth format-state)) (format-state->delayed-propl format-state)))) ;; ;; Format a conference or person name by retrieving information ;; about the conference or person and inserting it as a button ;; (unless the colon flag is set) ;; ((or (= format-letter ?M) (= format-letter ?P)) (setq result (cond ;; The string is already supplied ((stringp arg) arg) ;; Conference 0 does not exist, and person 0 means anonymous ((and (integerp arg) (zerop arg)) (setq colon-flag t) (lyskom-format (cond ((= format-letter ?P) (or lyskom-default-pers-string 'person-is-anonymous)) ((= format-letter ?M) (or lyskom-default-conf-string 'conference-does-not-exist))) arg) ) ;; Delay the printing ((and allow-defer kom-deferred-printing (integerp arg)) (let ((tmp (cache-get-uconf-stat arg))) (if (null tmp) (let* ((format-element (concat "%#2@%" (if equals-flag (make-string 1 equals-flag) "") (if pad-length (int-to-string pad-length)) "#1" (if colon-flag ":" "") (char-to-string format-letter))) (defer-info (lyskom-create-defer-info 'get-uconf-stat arg 'lyskom-deferred-insert-conf oldpos (if pad-length (cond ((eq equals-flag ?=) abs-length) ((eq equals-flag ?<) (min (length lyskom-defer-indicator) abs-length)) (t (max (length lyskom-defer-indicator) abs-length))) (length lyskom-defer-indicator)) format-element lyskom-default-conf-string))) (set-format-state->delayed-content format-state (cons defer-info (format-state->delayed-content format-state))) lyskom-defer-indicator) ;; The conf-stat was in the cache (setq arg tmp) (uconf-stat->name arg) ))) ;; The argument is an integer and we do not permit ;; deferred printing ((integerp arg) (let ((conf-stat (blocking-do 'get-uconf-stat arg))) (if (null conf-stat) (lyskom-format (if (= format-letter ?P) 'person-does-not-exist 'conference-does-not-exist) arg) (uconf-stat->name conf-stat)))) ;; We got a conf-stat, and can use it directly ((lyskom-conf-stat-p arg) (if face-flag (let ((face (conf-stat-find-aux arg 9))) (lyskom-maybe-add-face-to-string face (conf-stat->name arg))) (conf-stat->name arg))) ;; Argument is a conf-z-info ((lyskom-conf-z-info-p arg) (conf-z-info->name arg)) ;; We have an uconf-stat ((lyskom-uconf-stat-p arg) (uconf-stat->name arg)) ;; Something went wrong (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected conf)" arg-no arg))))) (if (and (not colon-flag) (or (lyskom-conf-stat-p arg) (lyskom-uconf-stat-p arg) (lyskom-conf-z-info-p arg) (numberp arg))) (setq propl (append (lyskom-default-button (if (= format-letter ?P) 'pers 'conf) arg) propl)))) ;; ;; Format a conference or person number the same way as names, ;; but insert the number rather than the name ;; ((or (= format-letter ?m) (= format-letter ?p)) (setq result (cond ((integerp arg) (int-to-string arg)) ((lyskom-conf-z-info-p arg) (int-to-string (conf-z-info->conf-no arg))) ((lyskom-conf-stat-p arg) (int-to-string (conf-stat->conf-no arg))) ((lyskom-uconf-stat-p arg) (int-to-string (uconf-stat->conf-no arg))) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected conf)" arg-no arg))))) (if (not colon-flag) (setq propl (append (lyskom-default-button (if (= format-letter ?p) 'pers 'conf) arg) propl)))) ;; ;; Format an integer or text-stat as a text number by adding the ;; by inserting a button (unless the colon flag is set) ;; ((= format-letter ?n) (setq result (cond ((integerp arg) (int-to-string arg)) ((numberp arg) (setq colon-flag t) (format "%.0f" arg)) ((lyskom-text-stat-p arg) (int-to-string (text-stat->text-no arg))) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected text-no)" arg-no arg))))) (if (not colon-flag) (setq propl (append (lyskom-default-button 'text arg) propl)))) ;; ;; Format a subject line by adding the subject face to the text ;; properties and the subject to the result list ;; ((= format-letter ?r) (setq result (cond ((stringp arg) (lyskom-format-plaintext-fonts arg) (lyskom-button-transform-text arg)) ((consp arg) (lyskom-format-plaintext-fonts (cdr arg)) (lyskom-button-transform-text (cdr arg) (car arg))) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected subject)" arg-no arg))))) (if (and (not colon-flag) (not (lyskom-face-default-p kom-subject-face))) (setq propl (append (list 'face kom-subject-face) propl)))) ;; ;; Format a LysKOM text body. Currently this does nothing. It ;; should parse the text for buttons ;; ((= format-letter ?t) ;; +++ One would want to do this before or after, but then ;; buttons will not be visible and other highlighting will ;; disappear. ;; (if (not colon-flag) ;; (setq propl (append (list 'face kom-text-face) propl))) (setq result (cond ((stringp arg) (lyskom-format-text-body arg)) ((and (consp arg) (lyskom-text-stat-p (car arg))) (lyskom-format-text-body (cdr arg) (car arg))) (t (signal 'lyskom-internal-error (list 'lyskom-format ": argument error (expected text)" arg-no arg)))))) ;; ;; Insert some deferred text ;; ((= format-letter ?D) (setq result (cond ((stringp arg) arg) (t (let ((format-element (concat "%" (if equals-flag (make-string 1 equals-flag) "") (if pad-length (int-to-string pad-length)) "#1" (if colon-flag ":" "") "s"))) (set-defer-info->pos arg oldpos) ;; Note: length is right below. string-width is wrong. (set-defer-info->del-chars arg (if pad-length (cond ((eq equals-flag ?=) abs-length) ((eq equals-flag ?<) (min (length lyskom-defer-indicator) abs-length)) (t (max (length lyskom-defer-indicator) abs-length))) (length lyskom-defer-indicator))) (set-defer-info->format arg format-element)) (set-format-state->delayed-content format-state (cons arg (format-state->delayed-content format-state))) lyskom-defer-indicator)))) ;; ;; The format letter was unknown ;; (t (signal 'lyskom-internal-error (list 'lyskom-format-help format-letter)))) ;; ;; Pad the result to the appropriate length ;; Fix flags so text props go in the right places anyway ;; (cond ((or (null pad-length) (null result)) nil) ((and (eq equals-flag ?<) (> abs-length (lyskom-string-width result))) nil) ((> abs-length (lyskom-string-width result)) (let ((padstring (make-string (- abs-length (lyskom-string-width result)) pad-letter))) (if (< pad-length 0) ; LEFT justify (progn (setq prop-adjust-end (- (- abs-length (lyskom-string-width result)))) (setq result (concat result padstring))) (progn (setq prop-adjust-start (- abs-length (lyskom-string-width result))) (setq result (concat padstring result)))))) ((and (memq equals-flag '(?= ?<)) (< abs-length (lyskom-string-width result))) (setq result (lyskom-truncate-string-to-width result abs-length (and trailer "..."))))) (if result (progn (set-format-state->result format-state (concat (format-state->result format-state) result)))) (if (and propl kom-text-properties) (add-text-properties (+ oldpos prop-adjust-start) (+ (length (format-state->result format-state)) prop-adjust-end) propl (format-state->result format-state)))) format-state) (defun lyskom-format-do-binary-predicate (option format-state allow-defer) (cond (option (setq format-state (lyskom-format-enter-subformat format-state allow-defer)) (lyskom-format-skip-subformat format-state)) (t (lyskom-format-skip-subformat format-state) (setq format-state (lyskom-format-enter-subformat format-state allow-defer)) )) format-state) (defun lyskom-format-enter-subformat (format-state allow-defer) "The format string should be just before a subformat. Enter it." (unless (string-match "%\\[" (format-state->format-string format-state) (format-state->start format-state)) (lyskom-error "Predicate syntax error in format string %s (%d)" (format-state->format-string format-state) (format-state->start format-state))) (set-format-state->start format-state (match-end 0)) (lyskom-format-aux format-state allow-defer)) (defun lyskom-format-skip-subformat (format-state) "Skip the subformat specification at the start of format-state" ;; Check that it looks like a subformat in the first place (unless (string-match "%\\[" (format-state->format-string format-state) (format-state->start format-state)) (lyskom-error "Predicate syntax error in format string %s (%d)" (format-state->format-string format-state) (format-state->start format-state))) (set-format-state->start format-state (match-end 0)) ;; We are now inside the start of the subformat (let ((level 1)) (while (> level 0) (if (null (string-match "\\(%\\[\\|%\\]\\)" (format-state->format-string format-state) (format-state->start format-state))) (lyskom-error "Bad nesting in format string %s (%d)" (format-state->format-string format-state) (format-state->start format-state)) (let ((ch (elt (match-string 1 (format-state->format-string format-state)) 1))) (cond ((= ?\[ ch) (setq level (1+ level))) (t (setq level (1- level)))) (set-format-state->start format-state (match-end 0))))))) (defun lyskom-tweak-format-state (format-state) (let ((dp (format-state->delayed-propl format-state))) (while dp (when (eq (format-state->depth format-state) (aref (car dp) 2)) (add-text-properties (aref (car dp) 0) (length (format-state->result format-state)) (aref (car dp) 1) (format-state->result format-state)) (set-format-state->delayed-propl format-state (delq (car dp) (format-state->delayed-propl format-state)))) (setq dp (cdr dp)))) (lyskom-traverse overlay-spec (format-state->delayed-overlays format-state) (unless (or (aref overlay-spec 1) (not (eq (format-state->depth format-state) (aref overlay-spec 3)))) (aset overlay-spec 1 (length (format-state->result format-state))))) format-state) ;;; ================================================================ ;;; Text body formatting (lyskom-try-require 'latin-unity) (lyskom-with-external-functions (smiley-region latin-unity-remap-region) (defun lyskom-format-text-body (text &optional text-stat) "Format a text for insertion. Does parsing of special markers in the text." (let* ((ct-item (and text-stat (car (text-stat-find-aux text-stat 1)))) (content-type (or (cond (ct-item (aux-item->data ct-item)) ((and (string-match "\\`\\(\\S-+\\):\\s-*$" text) (match-beginning 1)) (match-string 1 text)) (t nil)) "text/x-kom-basic")) (fn (and content-type (cdr (let ((case-fold-search t)) (lyskom-traverse el lyskom-format-special (when (eq 0 (string-match (if (stringp (car el)) (car el) (symbol-name (car el))) content-type)) (lyskom-traverse-break el))))))) (formatted (cond ((null fn) nil) ((listp fn) (lyskom-traverse el fn (let ((a (funcall el text text-stat))) (when a (lyskom-traverse-break a))))) ((functionp fn) (funcall fn text text-stat)) (t nil)))) (or formatted text))) (defun lyskom-format-plaintext (text text-stat) (lyskom-format-plaintext-fonts text) (let ((tmp (if kom-text-properties (lyskom-button-transform-text (lyskom-fill-message text) text-stat) (lyskom-fill-message text)))) (when (and kom-smileys (fboundp 'smiley-region)) (add-text-properties 0 (length tmp) '(special-insert lyskom-postprocess-text) tmp)) (when (fboundp 'latin-unity-remap-region) (add-text-properties 0 (length tmp) '(special-insert lyskom-unity-text) tmp)) tmp)) (defun lyskom-postprocess-text (start end &rest args) (condition-case nil (smiley-region start (min (point-max) (1+ end))) (error nil))) (defvar latin-unity-preferred-coding-system-list) (defvar latin-unity-iso-8859-1-aliases) (defvar latin-unity-cset-codesys-alist) (defun lyskom-unity-text (start end &rest args) (condition-case nil (let ((codesys (car latin-unity-preferred-coding-system-list))) (when (memq codesys latin-unity-iso-8859-1-aliases) (setq codesys 'iso-8859-1)) (let ((gr (or (car (rassq codesys latin-unity-cset-codesys-alist)) (and codesys (eq (lyskom-coding-system-type codesys) 'iso2022) (lyskom-coding-system-property codesys 'charset-g1))))) (when gr (latin-unity-remap-region start (min (point-max) (1+ end)) gr nil t)))) (error nil)))) (defmacro lyskom-format-plaintext-fonts-body () "Internal macro for lyskom-format-plaintext-fonts" (let* ((re-x 0) (re-1 "[^\]\|\}\) ^\n\r\t%s]") (re-2 "[^^\|<>=%%$\r\n%s]") (re-3 '(("_" (prefix . "") (suffix . "") (face . italic)) ("*" (prefix . "") (suffix . "") (face . bold)) ("/" (prefix . "\\s-") (suffix . "[\].,;:-_!\"#$%&\(\)\[\{\}=+?' \t\r\n]") (face . italic)))) (re (mapconcat (lambda (el) (let ((x (regexp-quote (car el)))) (format "%s\\(%s%s\\(%s*%s\\)?%s\\)%s" (cdr (assq 'prefix (cdr el))) x (format re-1 x) (format re-2 x) (format re-1 x) x (cdr (assq 'suffix (cdr el))) ))) re-3 "\\|"))) `(let ((start 0)) (while (string-match ,re text start) (cond ,@(mapcar (lambda (el) (prog1 `((match-beginning ,(+ 1 (* re-x 2))) (add-text-properties (1+ (match-beginning ,(+ 1 (* re-x 2)))) (1- (match-end ,(+ 1 (* re-x 2)))) '(face ,(cdr (assq 'face (elt re-3 re-x)))) text)) (setq re-x (1+ re-x)))) re-3)) (setq start (1- (match-end 0))))))) (defun lyskom-format-plaintext-fonts (text) (when kom-fontify-text (lyskom-format-plaintext-fonts-body))) (defun lyskom-signal-reformatted-text (how) "Signal that the last text was reformatted HOW, which should be a string in lyskom-messages." (or (memq how lyskom-last-text-format-flags) (setq lyskom-last-text-format-flags (cons how lyskom-last-text-format-flags)))) (lyskom-with-external-functions (w3m-region) (defun lyskom-w3m-region (start end &rest args) (lyskom-render-html-region start end 'w3m-region))) (lyskom-with-external-functions (w3-region) (defun lyskom-w3-region (start end &rest args) (lyskom-render-html-region start end 'w3-region))) (defun lyskom-render-html-region (start end fun) (unwind-protect (condition-case var (save-restriction (let ((buffer-read-only nil)) (setq start (set-marker (make-marker) start)) (setq end (set-marker (make-marker) end)) (narrow-to-region start end) (when kom-w3-simplify-body (save-excursion (let ((case-fold-search t)) (goto-char start) (while (re-search-forward "]*>" end t) (replace-match ""))))) (funcall fun start end) (add-text-properties (point-min) (point-max) '(end-closed nil)))) (error (lyskom-ignore var))))) (defun lyskom-format-html-plaintext (text text-stat) (lyskom-button-transform-text text text-stat)) (defun lyskom-format-html (text text-stat package function) ;; Find settings for this author (let ((author-setting (and text-stat (or (assq (text-stat->author text-stat) kom-format-html-authors) (assq t kom-format-html-authors))))) (when (and (cdr author-setting) (condition-case e (progn (require package) t) (error nil))) (add-text-properties 0 (length text) `(special-insert ,function) text) (lyskom-signal-reformatted-text 'reformat-html) (if (string-match "^html:" text) (substring text 5) text)))) (defun lyskom-format-html-w3 (text text-stat) (lyskom-format-html text text-stat 'w3 'lyskom-w3-region)) (defun lyskom-format-html-w3m (text text-stat) (lyskom-format-html text text-stat 'w3m 'lyskom-w3m-region)) (defun lyskom-format-image (text text-stat) (if kom-format-show-images (let* ((cti (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)) (content-type (and cti (aux-item->data (car cti)))) (msg "") (imagetype (intern ; FIXME: Can the media type contain more than letters and -? (string-replace-match "^.*/\\([-a-zA-Z]*\\)\\(.\\|\n\\)*" content-type "\\1"))) (imagedata text)) (condition-case nil (lyskom-xemacs-or-gnu (set-extent-end-glyph ; XEmacs (make-extent (point) (point-max)) (make-glyph (make-image-instance (vector imagetype :data imagedata)))) ; GNU Emacs (unless (and (lyskom-display-images-p) (lyskom-put-image (lyskom-create-image imagedata imagetype t) (point-max))) (setq msg (lyskom-get-string 'image-no-show)))) ; Errors just marks it as a no show (error (setq msg (lyskom-get-string 'image-no-show)))) (lyskom-signal-reformatted-text 'reformat-image) msg))) (defun lyskom-format-enriched (text text-stat) (if (not (fboundp 'format-decode-buffer)) nil (let ((tmpbuf (lyskom-generate-new-buffer "lyskom-enriched"))) (unwind-protect (save-excursion (set-buffer tmpbuf) (insert (substring text 10)) (format-decode-buffer) (lyskom-signal-reformatted-text 'reformat-enriched) (lyskom-button-transform-text (buffer-string) text-stat) ;; (substring (buffer-string) 0 -1) ; Remove the \n ) (kill-buffer tmpbuf))))) (defun lyskom-format-ö (text text-stat) (cond ((string= text "") "") (t (save-excursion (set-buffer (lyskom-get-buffer-create 'lyskom-text " lyskom-text" t)) (erase-buffer) (insert text) (goto-char (point-min)) (while (not (looking-at "\\'")) (save-restriction (narrow-to-region (point) (save-excursion (end-of-line) (point))) (lyskom-fill-region (point-min) (point-max)) (goto-char (point-max))) (forward-line 1)) (lyskom-signal-reformatted-text 'reformat-filled) (if kom-text-properties (lyskom-button-transform-text (buffer-string) text-stat) (buffer-substring (point-min) (1- (point-max)))))))) (defun lyskom-get-holerith-list (text &optional no-coding) "Assume that TEXT is a list of holerith strings. Return those strings." (let (result tmp) (while (string-match "\\S-" text) (setq tmp (lyskom-get-holerith text no-coding)) (setq result (cons (car tmp) result) text (cdr tmp))) (nreverse result))) (defun lyskom-get-holerith-assoc (text &optional no-coding) "Assume that TEXT is a list of holerith strings. Return those strings." (let (result tmp key value) (while (string-match "\\S-" text) (setq tmp (lyskom-get-holerith text no-coding)) (setq key (car tmp) text (cdr tmp)) (setq tmp (lyskom-get-holerith text no-coding)) (setq value (car tmp) text (cdr tmp)) (setq result (cons (cons key value) result))) (nreverse result))) (defun lyskom-split-user-area (text) "Return the user area split into components." (let ((tmp (lyskom-get-holerith text t))) (lyskom-mapcar2 'cons (lyskom-get-holerith-list (car tmp) t) (lyskom-get-holerith-list (cdr tmp) t)))) (defun lyskom-format-x-kom/user-area-data (data) (let* ((values (lyskom-get-holerith-assoc data t)) (maxlen (apply 'max (mapcar (lambda (el) (length (car el))) values))) (fs (format "%%-%ds%%s" (+ maxlen 2)))) (mapconcat (lambda (el) (format fs (concat (car el) ": ") (cdr el))) values "\n"))) (defun lyskom-format-x-kom/user-area (text text-stat) ; (condition-case nil (let ((result "") (user-area (lyskom-split-user-area text))) (while user-area (let ((key (car (car user-area))) (data (cdr (car user-area)))) (setq user-area (cdr user-area)) (setq result (concat result key "\n" (make-string (length key) ?=) "\n\n" (cond ((equal key "common") (lyskom-format-x-kom/user-area-data data)) ((equal key "elisp") (lyskom-format-x-kom/user-area-data data)) (t data)) (if user-area "\n\n\n" ""))))) result) ; (error (concat "Unable to parse user area\n\n" text))) ) ;;; ============================================================ ;;; lyskom-fill-message ;;; Author: David Byers ;;; ;;; Wrap the lines of a message with long lines so they're a little easier ;;; to read. Try to ignore what looks like preformatted text. ;;; ;;; Scan the text line by line, and decide whether to fill or not on a ;;; paragraph by paragraph basis. ;;; ;;; An empty line ends the current paragraph. ;;; ;;; An indented line followed by an unindented line ends the current ;;; paragraph and starts a new one. An indented line followed by the ;;; end of the buffer is also considered a paragraph if we have ;;; started a new paragraph based on indentation at least once before. ;;; ;;; A line that starts with a minus or plus starts a new paragraph. ;;; ;;; An indented line followed by another line indented the same way ;;; starts a new paragraph if we're not already scanning a paragraph. ;;; ;;; Any text seen when not scanning a paragraph starts a new ;;; paragraph. ;;; ;;; When a paragraph is started, filling may be enabled or disabled or ;;; set in a "maybe" state. ;;; ;;; A line that does not look like it belongs to the current paragraph ;;; because it is inndented incorrectly or because it starts with a ;;; strange character disables filling for the entire paragraph. ;;; ;;; A line that is wider than the window enables filling for the ;;; paragraph, unless filling has been disabled earlier. ;;; ;;; Any line containing three whitespace characters in a row, a space ;;; followed by a tab, or a tab followed by a space, or two tabs in a ;;; row, or the beginning or end of a C comment or four hyphens ;;; disables filling for the entire paragraph. ;;; ;;; A paragraph is not filled if filling has been disabled, or if the ;;; difference in line lengths from paragraph to paragraph is ;;; constant. ;;; (defconst lyskom-minimum-triangle-size 3 "Minimum number of lines in a triangle or suchlike.") (defconst lyskom-minimum-brick-size 2 "Minimum number of lines in a brick.") (defun lyskom-fill-message-initial-wrap (current-line-length pos) (cond ((and (< (lyskom-char-to-int (char-after pos)) (length lyskom-line-start-chars)) (not (aref lyskom-line-start-chars (lyskom-char-to-int (char-after pos))))) nil) ((> current-line-length fill-column) t) (t 'maybe))) (defsubst lyskom-fill-message-colon-line () "Return non-nil if the current line starts with a colon-like thing." (save-match-data (looking-at "\\S-+\\s-*:"))) (defun lyskom-fill-region (start end &optional justify nosqueeze to-eop) "Fill a region of text, compensating for bugs in Emacs." (save-match-data (let ((fill-column (if nosqueeze (1- fill-column) fill-column))) (when nosqueeze (condition-case nil (save-excursion (goto-char (match-beginning 0)) (backward-char 1) (delete-horizontal-space)) (error nil))) (condition-case nil (fill-region start (min end (point-max)) justify nosqueeze to-eop) (error nil))))) (defun lyskom-fill-message (text) "Try to reformat a message." (cond ((null kom-autowrap) text) ((and (numberp kom-autowrap) (> (length text) kom-autowrap)) text) (t (save-excursion (set-buffer (lyskom-get-buffer-create 'lyskom-text " lyskom-text" t)) (erase-buffer) (insert text) (goto-char (point-min)) (let* ((start (point)) (in-paragraph nil) (wrap-paragraph 'maybe) (length-difference nil) (constant-length nil) (all-lines-colons t) (current-line-length nil) (last-line-length nil) (paragraph-length 0) (eol-point nil) (have-indented-paragraphs nil) (cancel (cons nil nil)) (timer (and kom-autowrap-timeout (run-at-time kom-autowrap-timeout nil (lambda (obj) (setcdr obj t)) cancel))) (fill-column (cond ((not (integerp fill-column)) (- (window-width) 5)) ((> fill-column (- (window-width) 5)) (- (window-width) 5)) (t fill-column))) (fill-prefix nil) (single-line-regexp "\\(\\S-\\)")) (lyskom-ignore timer) ;; ;; Scan each line ;; (condition-case nil (while (not (eobp)) (setq current-line-length (lyskom-fill-message-line-length)) ;; ;; Do some work on checking for constant differences ;; (cond ((null length-difference) (when (and current-line-length last-line-length) (setq length-difference (- current-line-length last-line-length)))) ((eq constant-length 'maybe-not) (setq constant-length nil)) (constant-length (unless (= (- current-line-length last-line-length) length-difference) (setq constant-length 'maybe-not)))) (cond ;; ;; An empty line signifies a new paragraph. If we were scanning ;; a paragraph and it was to be filled, fill it. ;; ((looking-at "^\\s-*$") (when (and in-paragraph (not all-lines-colons) (eq wrap-paragraph t) (or (null constant-length) (and (eq 0 length-difference) (< paragraph-length lyskom-minimum-brick-size)) (and (not (eq 0 length-difference)) (< paragraph-length lyskom-minimum-triangle-size)))) (lyskom-fill-region start (1- (match-beginning 0)) nil t) (lyskom-signal-reformatted-text 'reformat-filled)) (setq start (match-end 0) in-paragraph nil all-lines-colons t wrap-paragraph 'maybe)) ;; ;; We're in a paragraph, but wait! This looks like ;; a LysKOM text! ;; ((looking-at (concat "^" (regexp-quote (lyskom-get-string 'subject)) ".*\n----")) (setq wrap-paragraph nil)) ;; ;; We're in a paragraph, but we see indentation, a dash or ;; something that looks like the end of a LysKOM text. ;; This has to mean something... ;; ((and in-paragraph (looking-at "^\\s-+\\([^\n]*\\)\\(\n\\S-\\|\\'\\)") (or (not (eq (point-max) (match-beginning 2))) have-indented-paragraphs)) (setq have-indented-paragraphs t) (when (and (eq wrap-paragraph t) (not all-lines-colons) (or (and (eq 0 length-difference) (< paragraph-length lyskom-minimum-brick-size)) (and (not (eq 0 length-difference)) (< paragraph-length lyskom-minimum-triangle-size)) (null constant-length))) (lyskom-fill-region start (match-beginning 0) nil t) (lyskom-signal-reformatted-text 'reformat-filled)) (setq start (match-beginning 0) in-paragraph t paragraph-length 0 constant-length t length-difference nil last-line-length nil all-lines-colons (lyskom-fill-message-colon-line) single-line-regexp "\\(\\S-\\)" fill-prefix nil start (match-beginning 0) wrap-paragraph (lyskom-fill-message-initial-wrap current-line-length (match-beginning 1)))) ((and in-paragraph (looking-at "^\\s-*\\(-+\\|\\++\\)\\s-*\\S-")) (when (and (eq wrap-paragraph t) (not all-lines-colons) (or (and (eq 0 length-difference) (< paragraph-length lyskom-minimum-brick-size)) (and (not (eq 0 length-difference)) (< paragraph-length lyskom-minimum-triangle-size)) (null constant-length))) (lyskom-fill-region start (match-beginning 0) nil t) (lyskom-signal-reformatted-text 'reformat-filled)) (setq start (match-beginning 0) in-paragraph t paragraph-length 0 constant-length t length-difference nil all-lines-colons (lyskom-fill-message-colon-line) last-line-length nil single-line-regexp "\\(\\S-\\)" fill-prefix nil start (match-beginning 0) wrap-paragraph (lyskom-fill-message-initial-wrap current-line-length (match-beginning 1)))) ;; ;; Here's a tricky one... We're not in a paragraph, and we ;; see what looks like an indented paragraph. Take care with ;; this one! ;; ((and (not in-paragraph) (looking-at "\\(\\s-+\\)\\S-") (looking-at (concat "\\(\\s-+\\)[^\n]*\n" (match-string 1) "\\(\\S-\\)"))) (setq in-paragraph t paragraph-length 0 constant-length 0 length-difference nil last-line-length nil all-lines-colons (lyskom-fill-message-colon-line) start (match-beginning 0) fill-prefix (match-string 1) single-line-regexp (concat (match-string 1) "\\(\\S-\\)") wrap-paragraph (lyskom-fill-message-initial-wrap current-line-length (match-beginning 2)))) ;; ;; Not in a paragraph, but here comes some text. Let's start ;; a paragraph, shall we? ;; ((and (not in-paragraph) (looking-at "\\s-*\\(\\S-\\)")) (setq in-paragraph t paragraph-length 0 all-lines-colons (lyskom-fill-message-colon-line) constant-length t length-difference nil last-line-length nil start (match-beginning 0) fill-prefix nil single-line-regexp "\\(\\S-\\)" wrap-paragraph (lyskom-fill-message-initial-wrap current-line-length (match-beginning 1)))) ;; ;; We're in a paragraph, but the line looks kind of strange ;; ((and in-paragraph (or (not (looking-at single-line-regexp)) (and (< (lyskom-char-to-int (char-after (match-beginning 1))) (length lyskom-line-start-chars)) (not (aref lyskom-line-start-chars (lyskom-char-to-int (char-after (match-beginning 1)))))))) (setq wrap-paragraph nil)) ;; ;; We're in a paragraph, the line looks OK, but is long. That ;; means we should probably be filling the paragraph later ;; ((and in-paragraph wrap-paragraph (> current-line-length fill-column)) (setq wrap-paragraph t)) ) ;; ;; Check if the line starts with Foo: ;; (when (and in-paragraph all-lines-colons (not (lyskom-fill-message-colon-line))) (setq all-lines-colons nil)) ;; ;; Certain things are guaranteed to disqualify the ;; current paragraph from wrapping, no matter what. ;; This is where we look for those. ;; (when (and in-paragraph wrap-paragraph) (setq eol-point (save-excursion (end-of-line) (point))) (when (re-search-forward "\ \\(\\S-[ \t][ \t][ \t]+\\S-\ \\|\\S-[ \t]* \t[ \t]*\\S-\ \\|[ \t]*\t [ \t]*\ \\|\\S-\\s-*\t\t\\s-*\\S-\ \\|----\ \\|/\\*\ \\|\\*/\ \\|[^:]//\ \\)" eol-point t) (setq wrap-paragraph nil))) (setq last-line-length current-line-length) (end-of-line) (setq paragraph-length (1+ paragraph-length)) (unless (eobp) (forward-line 1) (beginning-of-line) (when kom-autowrap-timeout (sit-for 0) (and (cdr cancel) (error "Out of time"))))) (quit (goto-char (point-max)) (setq in-paragraph nil)) (error (goto-char (point-max)) (setq in-paragraph nil))) ;; ;; We've seen the end of buffer. Fill any unfilled junk. ;; (when (and in-paragraph (not all-lines-colons) (eq wrap-paragraph t) (or (and (eq 0 length-difference) (< paragraph-length lyskom-minimum-brick-size)) (and (not (eq 0 length-difference)) (< paragraph-length lyskom-minimum-triangle-size)) (not (eq constant-length t)))) (lyskom-fill-region start (point) nil t) (lyskom-signal-reformatted-text 'reformat-filled))) ;; ;; Kill off unwanted whitespace at the end of the message ;; (let* ((pos (1- (point-max)))) (while (and (> pos 0) (progn (goto-char pos) (looking-at "[ \t\n\r]"))) (setq pos (1- pos))) (buffer-substring (point-min) (1+ pos))))))) (defun lyskom-fill-message-line-length () (- (save-excursion (end-of-line) (skip-chars-backward " \t") (current-column)) (current-column))) ;;; ============================================================ ;;; Beeping and feeping ;;; Faces and colors ;;; (defun lyskom-beep (arg &optional optarg) "Beep. ARG is how to beep. Optional OPTARG is a modifier. nil means don't beep. t means beep once. A number means beep that number of times (.1 second delay between beeps). A string means start the command kom-audio-player with the string as argument. A symbol other than t means call it as a function. A list of pairs means OPTARG will be used as a key to look up the real value of ARG. The special key t is used when OPTARG is not found." (setq optarg (cond ((lyskom-conf-stat-p optarg) (conf-stat->conf-no optarg)) ((lyskom-uconf-stat-p optarg) (uconf-stat->conf-no optarg)) (t optarg))) (cond ((null arg)) ((eq t arg) (ding t)) ((numberp arg) (while (> arg 0) (ding t) (sit-for kom-ding-pause-amount) (setq arg (1- arg)))) ((stringp arg) (condition-case nil (start-process "audio" nil kom-audio-player arg) (error nil))) ((and (symbolp arg) (fboundp arg)) (condition-case nil (funcall arg) (error (message "Error in beep function") (beep)))) ((and (listp arg) (or (assq optarg arg) (assq t arg))) (lyskom-beep (cdr (or (assq optarg arg) (assq t arg))) optarg)) (t (beep)))) (defun lyskom-face-default-p (f1) "Return t if f1 is undefined or the default face." (lyskom-xemacs-or-gnu (or (not (lyskom-find-face f1)) (face-equal (lyskom-find-face f1) (lyskom-find-face 'default))) (or (not (facep f1)) (face-equal f1 'default)))) ;;;; ================================================================ ;;;; Running in buffer ;;; Author: Linus (defun lyskom-text-at-point () "Return the text that point is in, or nil it is impossible to determine." (save-excursion (lyskom-prev-area 1 'lyskom-text-start) (get-text-property (point) 'lyskom-text-start))) (defun kom-next-prompt (num) "Move the cursor to the next prompt in the LysKOM buffer" (interactive "p") (lyskom-next-area num 'lyskom-prompt)) (defun kom-prev-prompt (num) "Move the cursor to the previous prompt in the LysKOM buffer" (interactive "p") (beginning-of-line) (lyskom-prev-area num 'lyskom-prompt)) (defun backward-text (&optional arg) "Searches backwards for a text start and recenters with that text at the top." (interactive "p") (lyskom-prev-area (or arg 1) 'lyskom-text-start t) (beginning-of-line)) (defun forward-text (&optional arg) "Searches forward for a text start and recenters with that text at the top." (interactive "p") (lyskom-next-area (or arg 1) 'lyskom-text-start t)) (def-kom-command kom-save-text-body (text-no &optional filename) "Save the body of the selected text to a file. This command saves the contents of the text, without LysKOM information around it to a file, overwriting any previous contents. See `kom-save-text' for an alternative command." (interactive (list (lyskom-read-text-no-prefix-arg 'what-save-no) nil)) (cond (text-no (blocking-do-multiple ((text-stat (get-text-stat text-no)) (text (get-text text-no))) (if (or (null text-stat) (null text)) (lyskom-format-insert 'no-such-text-no text-no) (let* ((mx-filename (lyskom-get-aux-item (text-stat->aux-items text-stat) 10104)) (filename nil)) (while (null filename) (setq filename (read-file-name (lyskom-format 'save-text-to-file-q text-no) (and mx-filename (file-name-directory (aux-item->data (car mx-filename)))) nil nil (and mx-filename (aux-item->data (car mx-filename))))) (if (file-directory-p filename) (setq filename nil) (if (or (not (file-exists-p filename)) (prog1 (lyskom-j-or-n-p (lyskom-format 'save-text-confirm filename)) (lyskom-message ""))) (let ((buf (lyskom-get-buffer-create 'temp " *kom*-text" t)) (str (text->decoded-text-mass text text-stat))) (condition-case nil (progn (lyskom-format-insert 'saving-text text-no filename) (when (string-match "\n" str) (setq str (substring str (match-end 0)))) (save-excursion (set-buffer buf) (erase-buffer) (insert str) (let* ((cti (lyskom-get-aux-item (text-stat->aux-items text-stat) 1)) (content-type (and cti (aux-item->data (car cti)))) (charset (cdr (assoc 'charset (cdr (lyskom-mime-decode-content-type content-type))))) (coding-system-for-write (or charset lyskom-server-coding-system))) (write-region (point-min) (point-max) filename))) (lyskom-insert (lyskom-get-string 'done))) (quit (lyskom-insert (lyskom-get-string 'cancelled))) (error (lyskom-insert (lyskom-get-string 'nope)))))))))))) (t (lyskom-insert 'confusion-what-to-save)))) (def-kom-command kom-save-text (arg &optional list-of-texts filename) "Append the selected texts to a file. The texts to save are determined by searching backwards in the buffer. A numeric prefix argument specifies the number of texts to save. Headers are included in the file. The file name to save to is read using the minibuffer, and the default is taken from kom-saved-file-name the first time. Subsequent calls use the most recently specified file name. See `kom-save-text-body' for an alternative to this command." (interactive "p") (let ((name nil)) (save-excursion (while (and arg (> arg 0)) (backward-text 1) (if (looking-at "\\([0-9]+\\)\\s-") (setq list-of-texts (cons (string-to-int (match-string 1)) list-of-texts) arg (1- arg)) (setq arg 0))) (setq name (expand-file-name (or filename (read-file-name (if (eq 1 (length list-of-texts)) (lyskom-format 'save-one-on-file-q (car list-of-texts)) (lyskom-format 'save-many-on-file-q (length list-of-texts))) (file-name-directory (or lyskom-saved-file-name kom-saved-file-name)) nil nil (file-name-nondirectory (or lyskom-saved-file-name kom-saved-file-name)))))) (cond ((file-directory-p name) (lyskom-format-insert 'cant-save-to-directory name)) (t (set-buffer lyskom-buffer) (if (eq 1 (length list-of-texts)) (lyskom-format-insert-before-prompt 'saving-one-on-file (car list-of-texts) name) (lyskom-format-insert-before-prompt 'saving-many-on-file (length list-of-texts) name)) (mapcar (lambda (n) (blocking-do-multiple ((text-stat (get-text-stat n)) (text (get-text n))) (lyskom-save-text text-stat text name))) list-of-texts) (setq lyskom-saved-file-name name)) )))) (defun lyskom-save-text (text-stat text filename) "Save text in TEXT-STAT and TEXT to FILENAME." (let* ((kom-print-relative-dates nil) (kom-deferred-printing nil) ;; This has to come last (buf (lyskom-get-buffer-create 'temp "*kom*-text" t))) (save-excursion (set-buffer buf) (erase-buffer) (lyskom-view-text (text-stat->text-no text-stat)) (append-to-file (point-min) (point-max) filename)))) ;;; ================================================================ ;;; To-do (defvar lyskom-recursive-prompt-update nil) (defun lyskom-update-all-prompts (&optional force-prompt-update) "Update the prompts in all buffers" (unless lyskom-recursive-prompt-update (let ((lyskom-recursive-prompt-update t)) (save-excursion (lyskom-traverse buffer lyskom-buffer-list (set-buffer buffer) (lyskom-update-prompt force-prompt-update)) (lyskom-set-default 'lyskom-need-prompt-update nil))))) (defun lyskom-update-prompt (&optional force-prompt-update) "Print prompt if the client knows which command will be default. Set lyskom-current-prompt accordingly. Tell server what I am doing." (let ((was-at-max (eq (point) (point-max))) (saved-suffix (if lyskom-slow-mode (save-excursion (lyskom-get-entered-slow-command)) nil))) (if (or lyskom-executing-command (and lyskom-current-prompt lyskom-dont-change-prompt)) nil (let ((to-do (lyskom-what-to-do)) (prompt nil) (prompt-args nil)) (setq lyskom-command-to-do to-do) (cond ((eq to-do 'next-pri-conf) (setq prompt (cond ((eq lyskom-pers-no (conf-stat->conf-no (read-info->conf-stat (read-list->first lyskom-to-do-list)))) 'go-to-pri-mailbox-prompt) (t 'go-to-pri-conf-prompt))) (or (eq lyskom-current-prompt prompt) (lyskom-beep kom-ding-on-priority-break))) ((eq to-do 'reedit-text) (setq prompt 're-edit-text-prompt)) ((and (eq to-do 'next-pri-session) (lyskom-get-prioritized-session)) (if (and (read-list-isempty lyskom-reading-list) (read-list-isempty lyskom-to-do-list)) (setq prompt 'next-unread-session-prompt) (setq prompt 'next-pri-session-prompt)) (setq prompt-args (save-excursion (set-buffer (lyskom-get-prioritized-session)) (list (lyskom-session-nickname))))) ((eq to-do 'next-pri-text) (setq prompt (cond ((eq (conf-stat->conf-no (read-info->conf-stat (read-list->first lyskom-to-do-list))) lyskom-pers-no) 'read-pri-letter-prompt) (t 'read-pri-text-conf))) (or (eq lyskom-current-prompt prompt) (lyskom-beep kom-ding-on-priority-break))) ((eq to-do 'next-text) (setq prompt (let ((read-info (read-list->first lyskom-reading-list))) (cond ((eq 'REVIEW (read-info->type read-info)) 'review-next-text-prompt) ((eq 'REVIEW-TREE (read-info->type read-info)) 'review-next-comment-prompt) ((eq 'REVIEW-MARK (read-info->type read-info)) 'review-next-marked-prompt) ((or (eq 'REVIEW-FAQ (read-info->type read-info)) (eq 'REVIEW-FAQ-TREE (read-info->type read-info))) 'review-next-faq-prompt) ;; The following is not really correct. The text to be ;; read might be in another conference. ((= lyskom-current-conf lyskom-pers-no) 'read-next-letter-prompt) ((lyskom-get-aux-item (text-stat->aux-items (cache-get-text-stat (car-safe (text-list->texts (read-info->text-list read-info))))) 10100) 'read-next-attachment-prompt) ((eq 'FOOTN-IN (read-info->type read-info)) 'read-next-footnote-prompt) ((eq 'COMM-IN (read-info->type read-info)) 'read-next-comment-prompt) (t 'read-next-text-prompt))))) ((eq to-do 'next-conf) (setq prompt (cond ((eq 'REVIEW-MARK (read-info->type (read-list->first lyskom-to-do-list))) 'go-to-conf-of-marked-prompt) ((eq 'REVIEW (read-info->type (read-list->first lyskom-to-do-list))) 'go-to-conf-of-review-prompt) ((eq 'REVIEW-FAQ (read-info->type (read-list->first lyskom-to-do-list))) 'go-to-conf-of-review-faq-prompt) ((eq 'REVIEW-FAQ-TREE (read-info->type (read-list->first lyskom-to-do-list))) 'go-to-conf-of-review-faq-prompt) ((eq 'REVIEW-TREE (read-info->type (read-list->first lyskom-to-do-list))) 'go-to-conf-of-review-tree-prompt) ((/= lyskom-pers-no (conf-stat->conf-no (read-info->conf-stat (read-list->first lyskom-to-do-list)))) 'go-to-next-conf-prompt) (t 'go-to-your-mailbox-prompt)))) ((eq to-do 'when-done) (if (not lyskom-is-writing) (lyskom-tell-server kom-mercial)) (setq prompt (let ((command (lyskom-what-to-do-when-done t))) (cond ((lyskom-command-name command lyskom-language)) ((and (stringp command) (lyskom-command-name (key-binding command) lyskom-language))) (t (lyskom-format 'the-command command)))))) ((eq to-do 'unknown) ;Pending replies from server. (setq prompt nil)) (t (message "%s" to-do) (setq prompt "???"))) (when (or force-prompt-update (not (equal prompt lyskom-current-prompt))) (let ((inhibit-read-only t) (prompt-text (if prompt (lyskom-modify-prompt (apply 'lyskom-format (cond ((symbolp prompt) (lyskom-get-string prompt)) (t prompt)) prompt-args)) ""))) (save-excursion ;; Insert the new prompt (goto-char (point-max)) (beginning-of-line) (lyskom-xemacs-or-gnu (let ((extent (make-extent 0 (length prompt-text) prompt-text))) (set-extent-property extent 'read-only t) (set-extent-property extent 'rear-nonsticky t) (set-extent-property extent 'duplicable nil)) (add-text-properties 0 (length prompt-text) '(read-only t rear-nonsticky t) prompt-text)) (insert prompt-text) ;; Delete the old prompt (when lyskom-current-prompt (if (and lyskom-slow-mode (looking-at (regexp-quote lyskom-current-prompt-text))) (delete-region (point) (match-end 0)) (delete-region (point) (point-max)) (if saved-suffix (insert saved-suffix))))) (when was-at-max (goto-char (point-max))) (setq lyskom-current-prompt prompt) (setq lyskom-current-prompt-args prompt-args) (setq lyskom-current-prompt-text prompt-text)))) (lyskom-set-mode-line)))) (defun lyskom-modify-prompt (s &optional executing) (let ((text (lyskom-format-prompt (cond (lyskom-is-administrator (if executing kom-enabled-prompt-format-executing kom-enabled-prompt-format)) (lyskom-is-anonymous (if executing kom-anonymous-prompt-format-executing kom-anonymous-prompt-format)) (t (if executing kom-user-prompt-format-executing kom-user-prompt-format))) s))) (add-text-properties 0 (length text) (append (lyskom-default-button 'timestamp lyskom-current-prompt-timestamp (list 'timestamp-popup-title (let ((kom-print-relative-dates nil)) (lyskom-format-time 'date-and-time lyskom-current-prompt-timestamp)))) '(lyskom-prompt t)) text) (when executing (setq lyskom-current-prompt-timestamp (lyskom-current-client-time))) text)) (defun lyskom-format-prompt (fmt command) (let ((start 0) (len (length fmt)) (result nil) (tmp nil) (format-letter nil) (messages (length lyskom-ansaphone-messages))) (while (< start len) (setq tmp (string-match "%[][cm Sswp#aA]" fmt start)) (if tmp (progn (if (> tmp start) (setq result (cons (substring fmt start tmp) result))) (setq format-letter (elt fmt (1- (match-end 0)))) (setq start (match-end 0)) (setq result (cons (cond ((eq format-letter ?\[) (if kom-ansaphone-on "[" "")) ((eq format-letter ?\]) (if kom-ansaphone-on "]" "")) ((eq format-letter ?c) command) ((eq format-letter ?w) (or (conf-stat->name (cache-get-conf-stat lyskom-current-conf)) (lyskom-format 'conference-no lyskom-current-conf))) ((eq format-letter ?S) lyskom-server-name) ((eq format-letter ?s) (lyskom-session-nickname)) ((eq format-letter ?p) (or (conf-stat->name (cache-get-conf-stat lyskom-pers-no)) (lyskom-format 'person-no lyskom-pers-no))) ((eq format-letter ?#) (number-to-string lyskom-session-no)) ((eq format-letter ?a) (lyskom-get-string 'anonymous)) ((eq format-letter ?A) (lyskom-get-string 'Anonymous)) ((eq format-letter ?m) (cond ((< messages 1) "") ((= messages 1) (format (lyskom-get-string 'prompt-single-message) messages)) ((> messages 1) (format (lyskom-get-string 'prompt-several-messages) messages)))) ((eq format-letter ?%) "%") ((eq format-letter ?\ ) 'SPC)) result))) (progn (setq result (cons (substring fmt start) result)) (setq start len)))) (lyskom-build-prompt (nreverse result)))) (defun lyskom-build-prompt (data) (let ((result "") (separate nil)) (while data (cond ((stringp (car data)) (cond ((and separate (string-match "\\S-$" result) (string-match "^\\S-" (car data))) (setq result (concat result " " (car data)))) (t (setq result (concat result (car data))))) (setq separate nil)) ((eq (car data) 'SPC) (setq separate t))) (setq data (cdr data))) result)) (defun lyskom-get-prioritized-session () "Get the session to go to if we are doing an auto-goto-session" (let ((session-list (if (memq kom-server-priority-breaks '(express-letters letters after-conf-letters)) lyskom-sessions-with-unread-letters lyskom-sessions-with-unread)) (session nil) (saved-priority nil)) (while session-list (condition-case nil (save-excursion (set-buffer (car session-list)) (when (or (null saved-priority) (> kom-server-priority saved-priority)) (setq session (car session-list) saved-priority kom-server-priority))) (error nil)) (setq session-list (cdr session-list))) session)) (defun lyskom-what-to-do () "Check what is to be done. Return an atom as follows: next-pri-text There is a text with higher priority to be read. next-pri-conf There is a conference with higher priority to be read. next-text There are texts on lyskom-reading-list. next-conf There are texts on lyskom-to-do-list. reedit-text There is an edit buffer with an error. when-done There are no unread texts. next-pri-session There is a session with unreads. unknown There are pending replies." (cond ;; If session breaks are one ... and ... ;; there is a session with higher priority ... and ... ;; it's not the current session ... and ... ;; we either have express breaks or we're at the end of a comment chain ;; the priority of the other session is higher than what we're reading ((let* ((pri-session (lyskom-get-prioritized-session)) (type (unless (read-list-isempty lyskom-reading-list) (read-info->type (read-list->first lyskom-reading-list)))) (pri (unless (read-list-isempty lyskom-reading-list) (read-info->priority (read-list->first lyskom-reading-list)))) (pri-session-pri (save-excursion (when (and pri-session pri) (set-buffer pri-session) kom-server-priority)))) (and (not (eq pri-session (current-buffer))) (or (and (memq kom-server-priority-breaks '(express express-letters)) pri-session (or (null pri) (> pri-session-pri pri))) (and (eq kom-server-priority-breaks 'when-done) pri-session (read-list-isempty lyskom-reading-list) (read-list-isempty lyskom-to-do-list)) (and (memq kom-server-priority-breaks '(t letters)) pri-session (or (null type) (eq type 'CONF) (eq type 'REVIEW) (eq type 'REVIEW-FAQ) (eq type 'REVIEW-MARK)) (or (null pri) (> pri-session-pri pri))) (and (memq kom-server-priority-breaks '(after-conf after-conf-letters)) pri-session (read-list-isempty lyskom-reading-list) (or (null pri) (> pri-session-pri pri))) ))) 'next-pri-session) ((and kom-higher-priority-breaks (not (read-list-isempty lyskom-reading-list)) (not (read-list-isempty lyskom-to-do-list)) (let ((type (read-info->type (read-list->first lyskom-reading-list)))) (or (eq kom-higher-priority-breaks 'express) (memq type '(CONF REVIEW REVIEW-MARK REVIEW-FAQ)))) (> (read-info->priority (read-list->first lyskom-to-do-list)) (read-info->priority (read-list->first lyskom-reading-list)))) (if (> (text-list->length (read-info->text-list (read-list->first lyskom-to-do-list))) 1) 'next-pri-conf 'next-pri-text)) ((and (not (read-list-isempty lyskom-reading-list)) (eq (read-info->type (read-list->first lyskom-reading-list)) 'RE-EDIT-TEXT)) 'reedit-text) ((not (read-list-isempty lyskom-reading-list)) 'next-text) ((not (read-list-isempty lyskom-to-do-list)) 'next-conf) ;; This is not really true. The prefetch may still be fetching the ;; membership. One possible way is to test for a non-numeric, ;; non-nil value. Or even better, introduce a test function to ;; isolate the test. (lyskom-membership-is-read 'when-done) (t 'unknown))) (defun lyskom-what-to-do-when-done (&optional nochange) "Returns a command, the next command to do from the kom-do-when-done. If optional argument NOCHANGE is non-nil then the list wont be altered." (condition-case nil (let* ((now (cdr lyskom-do-when-done)) (all (car lyskom-do-when-done)) (next (cond ((and now (eq now all) (cdr all)) (cdr all)) (t all))) (command (cond ((commandp (car now)) (car now)) ((and (car next) (listp (car next)) (not (eq (car (car next)) 'lambda))) (car (setq now (car next)))) (t (or (car (setq now next)) 'kom-display-time))))) (if nochange nil (setq lyskom-do-when-done (cons next (cdr now)))) command) (error (lyskom-insert-before-prompt (lyskom-get-string 'error-in-kom-do-when-done)) (lyskom-beep t) (setq lyskom-do-when-done '((kom-customize kom-display-time) . (kom-edit-options kom-display-time))) 'kom-display-time))) (defun lyskom-prefetch-and-print-prompt () "Prefetch info if needed. Print prompt if not already printed." (when (and lyskom-is-waiting (listp lyskom-is-waiting) (eval lyskom-is-waiting)) (setq lyskom-is-waiting nil)) (lyskom-update-prompt)) (defun lyskom-known-texts () "Count how many unread texts the user have, that the client knows about." (apply '+ (mapcar '(lambda (x) (text-list->length (read-info->text-list x))) (read-list->all-entries lyskom-to-do-list)))) (defun lyskom-wait-for-membership () "Give a message and wait for it to be prefetched. If the full membership hase been read do nothing." (let ((total (pers-stat->no-of-confs (blocking-do 'get-pers-stat lyskom-pers-no)))) (while (and (not (lyskom-membership-is-read)) (numberp lyskom-membership-is-read)) (lyskom-message (lyskom-get-string 'waiting-for-membership) lyskom-membership-is-read total) (sit-for 0) (accept-process-output lyskom-proc 1)))) (defun lyskom-prefetch-all-confs () "Gets all conferences using prefetch." (lyskom-wait-for-membership)) ;; FIXME: Here we can handle both maps and mappings, but in ;; FIXME: reality this should *never* get called with a map ;; FIXME: anymore (defun lyskom-list-unread (map membership) "Args: MAP MEMBERSHIP. Return a list of unread texts. The list consists of text-nos." (if (lyskom-text-mapping-p map) (lyskom-list-unread-mapping map membership) (let ((read (membership->read-texts membership)) (first (map->first-local map)) (i (length (map->text-nos map))) (the-map (map->text-nos map))) (when (not (null read)) (while (> i 0) (-- i) ;; The server always send the read texts in sorted order. This ;; means that we can use binary search to look for read texts. ;; It might be a good idea to check for zero, and not do a ;; sarch in that case, but it depends on how big holes there ;; are in the map. In general the extra test is probably a ;; slowdow, but when reading the initial part of the I]M map ;; it would most likely help a lot. (when (lyskom-binsearch (+ i first) read) (aset the-map i 0)))) (delq 0 (listify-vector the-map))))) (defun lyskom-list-unread-mapping (map membership) "Args: MAP MEMBERSHIP. Return a list of unread texts. The list consists of text-nos." (let ((read (membership->read-texts membership)) (iter (text-mapping->iterator map)) (el nil)) (when (not (null read)) (while (setq el (text-mapping-iterator->next iter)) (when (lyskom-binsearch (text-pair->local-number el) read) (text-mapping->remove-local map (text-pair->local-number el))))) (text-mapping->global-numbers map))) ;;;; ================================================================ (defun lyskom-vmemq (elt vector) "Return t if ELT is a member of (present in) VECTOR." (let ((found nil) (i (length vector))) (while (and (> i 0) (not found)) (-- i) (if (eq elt (aref vector i)) (setq found t))) found)) (defun lyskom-binsearch (el sequence &optional first last+1 fn) "Return the index if EL is a member of (present in) SEQUENCE. SEQUENCE has to be sorted with regard to the comparison function. Optional arguments FIRST and LAST+1 should only be used if you know what they are for. Optional argument FN is the function to use for comparison. It should take arguments A and B and return non-nil if A is less than B. If not supplied, FN defaults to <." (lyskom-binsearch-internal el sequence (or first 0) (or last+1 (length sequence)) (or fn '<))) (defun lyskom-binsearch-internal (num vector first last+1 less-than) "Return the index if ELT is a member of the sorted vector VECTOR." (let* ((split (/ (+ first last+1) 2)) (splitval (elt vector split))) (cond ;; Only one element ((= (- last+1 first) 1) (if (not (or (funcall less-than num splitval) (funcall less-than splitval num))) split nil)) ;; Search the left subtree ((funcall less-than num splitval) (lyskom-binsearch-internal num vector first split less-than)) ;; Search the left subtree ((funcall less-than splitval num) (lyskom-binsearch-internal num vector split last+1 less-than)) ;; Found (t split)))) (defvar lyskom-verified-read-predicate nil) (defun lyskom-verified-read-enter () (interactive) (let* ((val (lyskom-minibuffer-contents)) (err (funcall lyskom-verified-read-predicate val))) (if err (lyskom-minibuffer-message (format " [%s]" err)) (exit-minibuffer)))) (defvar lyskom-verified-read-map nil) (if lyskom-verified-read-map nil (setq lyskom-verified-read-map (copy-keymap minibuffer-local-map)) (define-key lyskom-verified-read-map (kbd "RET") 'lyskom-verified-read-enter) (define-key lyskom-verified-read-map (kbd "C-j") 'lyskom-verified-read-enter) (define-key lyskom-verified-read-map (kbd "C-m") 'lyskom-verified-read-enter) ) (defun lyskom-verified-read-from-minibuffer (prompt initial pred) "Read something from minibuffer, verifying that it is valid. PROMPT is the prompt and INITIAL the initial contents of the minibuffer. PRED is a predicate to check entered data. It should return nil or a string. If it returns a string, the data is not valid and the string is used as an error message." (let ((lyskom-verified-read-predicate pred)) (lyskom-read-from-minibuffer prompt initial lyskom-verified-read-map))) (defun lyskom-read-num-range-or-date (low high prompt &optional initial empty default) "Read a number or a date from the minibuffer. Args: LOW HIGH PROMPT. The result will be a number or a list of (YEAR MONTH DATE)." (let ((result nil) (break nil) (val (and initial (number-to-string initial))) (prompt (concat (if (symbolp prompt) (lyskom-get-string prompt) prompt) (format "(%d-%d %s) " low high (lyskom-get-string 'or-date))))) (while (and (null result) (null break)) (setq val (lyskom-verified-read-from-minibuffer prompt (and val (cons val 0)) (lambda (val) (cond ((string-match "^\\s-*[0-9]+\\s-*$" val) (let ((num (string-to-int val))) (unless (and (>= num low) (<= num high)) (lyskom-get-string 'number-out-of-range)))) ((and empty (string-match "^\\s-*$" val)) nil) (t (condition-case nil (progn (lyskom-parse-date val) nil) (lyskom-error (lyskom-get-string 'invalid-date-entry)))))))) (cond ((string-match "^\\s-*[0-9]+\\s-*$" val) (let ((num (string-to-int val))) (when (and (>= num low) (<= num high)) (setq result num)))) ((and empty (string-match "^\\s-*$" val)) (setq break t result default)) (t (condition-case nil (setq result (lyskom-parse-date val) ) (lyskom-error nil))))) result)) (defun lyskom-read-num-range (low high &optional prompt show-range default history nildefault) "Read a number from the minibuffer. Args: LOW HIGH &optional PROMPT SHOW-RANGE with default value DEFAULT. The read number must be within the range [LOW HIGH]. If SHOW-RANGE is non-nil, the prompt will include the range for information to the user. HISTORY is the history list to use. If NILDEFAULT is non-nil, return nil if the user enters an empty string" (let ((number (1- low))) (while (and (not (and nildefault (null number))) (or (< number low) (> number high))) (setq number (lyskom-read-number (concat (cond ((null prompt) (lyskom-get-string 'give-a-number)) ((symbolp prompt) (lyskom-get-string prompt)) (t prompt)) (if show-range (format "(%d-%d) " low high) "")) default history nildefault))) number)) (defun lyskom-read-number (&optional prompt default history nildefault completions) "Read a number from the minibuffer. Optional arguments: PROMPT DEFAULT If DEFAULT is non-nil, it is written within parenthesis after the prompt. DEFAULT could also be of the type which (interactive P) generates. If NILDEFAULT is non-null then typing return will cause the function to return nil." (let* ((numdefault (cond ((null default) nil) ((integerp default) default) ((listp default) (car default)) (t nil))) (prompt (concat (cond ((null prompt) (lyskom-get-string 'give-a-number)) ((symbolp prompt) (lyskom-get-string prompt)) (t prompt)) (if numdefault (format " (%d) " numdefault) " "))) (number nil) (numstr nil) (done nil)) (while (not done) (setq numstr (prog1 (if completions (lyskom-completing-read prompt (mapcar (lambda (x) (list (number-to-string x) x)) completions) nil t nil history (when default (number-to-string default))) (lyskom-read-string prompt nil history)))) (cond ((and (string= numstr "") numdefault) (setq number numdefault done t)) ((and (string= numstr "") nildefault) (setq number nil done t)) ((and (string-match "\\`\\s-*[0-9]+\\s-*\\'" numstr) (lyskom-string-to-int numstr)) (setq number (lyskom-string-to-int numstr)) (setq done number)) (t (beep)))) number)) (defun lyskom-read-string (prompt &optional initial history) "Read a string from the minibuffer. Arguments: PROMPT INITIAL" (read-string prompt initial history)) (defun ja-or-nej-p (prompt &optional initial-input) "Same as yes-or-no-p but language-dependent. Uses lyskom-message, lyskom-read-string to do interaction and lyskom-get-string to retrieve regexps for answer and string for repeated query." (let ((answer "") (nagging nil)) (while (not (or (string-match (lyskom-get-string 'yes-regexp) answer) (string-match (lyskom-get-string 'no-regexp) answer))) (if nagging (progn (lyskom-message "%s" (lyskom-get-string 'yes-or-no-nag)) (sit-for 2))) (setq answer (lyskom-read-string (concat prompt (lyskom-get-string 'yes-or-no)) initial-input t)) (setq nagging t)) (not (string-match (lyskom-get-string 'no-regexp) answer)))) ;;; ;;; j-or-n-p is similar to y-or-n-p. ;;; (defun j-or-n-p (prompt) "Same as y-or-n-p but language-dependent. Uses lyskom-message, lyskom-read-string to do interaction and lyskom-get-string to retrieve regexps for answer and string for repeated query." (when (symbolp prompt) (setq prompt (lyskom-get-string prompt))) (let ((input-char 0) (cursor-in-echo-area t) (lyskom-inhibit-minibuffer-messages t) (nagging nil)) (while (and (not (char-in-string input-char (lyskom-get-string 'y-or-n-instring))) (not (or (eq input-char ?\C-g) (eq 'keyboard-quit (lyskom-lookup-key (current-local-map) input-char t))))) (lyskom-message "%s" (concat (if nagging (lyskom-get-string 'j-or-n-nag) "") prompt (lyskom-get-string 'j-or-n))) (if nagging (beep)) ;; ;; Workaround for Emacs whose read-char does not accept C-g ;; (setq input-char (let ((inhibit-quit t)) (prog1 (read-char-exclusive) (setq quit-flag nil)))) ;; ;; Redisplay prompt on C-l ;; (if (or (eq input-char ?\C-l) (eq 'recenter (lyskom-lookup-key (current-local-map) input-char t))) (setq nagging nil) (setq nagging t))) (when (or (eq input-char ?\C-g) (eq 'keyboard-quit (lyskom-lookup-key (current-local-map) input-char t))) (signal 'quit nil)) (lyskom-message "%s" (concat prompt (lyskom-get-string 'j-or-n) (if (char-in-string input-char (lyskom-get-string 'y-instring)) (lyskom-get-string 'yes-string) (lyskom-get-string 'no-string)))) (char-in-string input-char (lyskom-get-string 'y-instring)))) ;;; lyskom-j-or-n-p, lyskom-ja-or-no-p ;;; These versions no longer perform lyskom-end-of-command ;; Author: Linus Tolke (defun lyskom-j-or-n-p (prompt) "Same as j-or-n-p but performs lyskom-end-of-command if quit." (condition-case nil (j-or-n-p prompt) (quit (signal 'quit nil)))) (defun lyskom-ja-or-nej-p (prompt &optional initial-input) "Same as ja-or-nej-p but performs lyskom-end-of-command if quit." (condition-case nil (ja-or-nej-p prompt initial-input) (quit (signal 'quit nil)))) (defun lyskom-a-or-b-or-c-p (prompt alternatives &optional default) "Like y-or-n-p but choose among several options. Display PROMPT and ask user to choose among ALTERNATIVES. ALTERNATIVES are symbols. Each alternative must be found as a string in lyskom-messages. The first character of the string is the character to enter to select the alternative and is not displayed. If non-nil DEFAULT is the default alternative and is selected when the user types RET. Returns the selected alternative (a symbol)" (when (symbolp prompt) (setq prompt (lyskom-get-string prompt))) (let* ((input-char 0) (cursor-in-echo-area t) (lyskom-inhibit-minibuffer-messages t) (alts (mapcar (lambda (alt) (let ((string (lyskom-get-string alt))) (list (elt string 0) (substring string 1) alt))) alternatives)) (alts-string (format "(%s) " (mapconcat (lambda (c) (lyskom-format "%#3@%#1c:%#2s" (elt c 0) (elt c 1) (and (eq (elt c 2) default) '(face bold)) )) alts ", "))) (nagging nil)) (while (and (not (assq input-char alts)) (not (or (eq input-char ?\C-g) (eq 'keyboard-quit (lyskom-lookup-key (current-local-map) input-char t)))) (not (and default (eq input-char ?\C-m)))) (lyskom-message "%s" (concat (if nagging (lyskom-get-string 'a-or-b-or-c-nag) "") prompt alts-string)) (if nagging (beep)) ;; ;; Workaround for Emacs whose read-char does not accept C-g ;; (setq input-char (let ((inhibit-quit t)) (prog1 (read-char-exclusive) (setq quit-flag nil)))) ;; ;; Redisplay prompt on C-l ;; (if (or (eq input-char ?\C-l) (eq 'recenter (lyskom-lookup-key (current-local-map) input-char t))) (setq nagging nil) (setq nagging t))) (when (or (eq input-char ?\C-g) (eq 'keyboard-quit (lyskom-lookup-key (current-local-map) input-char t))) (signal 'quit nil)) (setq alts (cons (list ?\C-m (lyskom-traverse alt alts (when (eq default (elt alt 2)) (lyskom-traverse-break (elt alt 1)))) default) alts)) (lyskom-message "%s" (concat prompt (elt (assq input-char alts) 1))) (if (eq input-char ?\C-m) default (elt (assq input-char alts) 2)))) (defun impl () (error "Not implemented")) ;;; Priority filtering (defun lyskom-visible-membership (membership) "Is this conference visible? Return t is MEMBERSHIPs priority is higher than or equal to lyskom-session-priority and nil otherwise. If MEMBERSHIPs prioriy is 0, it always returns nil." (let ((priority (membership->priority membership))) (and (not (membership-type->passive (membership->type membership))) (>= priority lyskom-session-priority)))) ;;; The filter. (defun lyskom-filter (proc output) "Receive replies from LysKOM server." ; (sit-for 0) ; Why? [Doesn't work in XEmacs 19.14] ; (setq lyskom-apo-timeout-log ; (cons (cons (current-time-string) lyskom-apo-timeout) lyskom-apo-timeout-log)) (lyskom-reset-apo-timeout) ; Reset accept-process-output timeout (let ((old-match-data (match-data)) ;; lyskom-filter-old-buffer is also changed when starting to edit ;; in function lyskom-edit-text. (lyskom-filter-old-buffer (current-buffer))) (unwind-protect (condition-case nil (progn (setq lyskom-quit-flag nil) (if lyskom-debug-communications-to-buffer (save-excursion (set-buffer (get-buffer-create "*kom*-replies")) (goto-char (point-max)) (princ (lyskom-string-as-unibyte output) (current-buffer)) (lyskom-debug-limit-buffer))) (if lyskom-debug-communications-to-buffer (if (not lyskom-debug-what-i-am-doing) (if (not (and (eq ?: (elt output 0)) (eq ?5 (elt output 1)))) (lyskom-debug-insert proc "From " output)) (lyskom-debug-insert proc "From " output))) (set-buffer (process-buffer proc)) (princ (lyskom-string-as-unibyte output) lyskom-unparsed-marker) ;;+++lyskom-string-skip-whitespace (if quit-flag ; We are allowed to break here. (setq inhibit-quit nil)) ; This will break ; instantly. ;; Keep inhibit-quit set to t (cond ((and (> lyskom-string-bytes-missing 0) (< (length output) lyskom-string-bytes-missing)) (setq lyskom-string-bytes-missing (- lyskom-string-bytes-missing (length output)))) ;; This test makes e.g. startup a lot faster. At least ;; it does when the maps are read in one chunk, which ;; they usually aren't anymore. ((not (string-match "\n" output))) ((null lyskom-is-parsing) ;Parse one reply at a time. (let ((lyskom-is-parsing t)) (unwind-protect (condition-case nil (lyskom-parse-unparsed) ;; Incomplete answers are normal. (lyskom-parse-incomplete)) ;; In case it was changed by the handler. (set-buffer (process-buffer proc))))))) ;; condition-case handler (quit (setq lyskom-quit-flag t)) ;; (lyskom-protocol-error ;; (lyskom-message "%s" (lyskom-get-string 'protocol-error) err)) ) ;; (unwind-protect ;; (save-excursion (set-buffer (process-buffer proc)) ;; (lyskom-check-mship-lists))) (setq lyskom-quit-flag (or lyskom-quit-flag quit-flag)) (setq quit-flag nil) (when lyskom-need-prompt-update (lyskom-update-all-prompts)) ;; Restore selected buffer and match data. (store-match-data old-match-data) (when (buffer-live-p lyskom-filter-old-buffer) (set-buffer lyskom-filter-old-buffer))) (sit-for 0))) ;;; The sentinel (defun lyskom-sentinel (proc sentinel) "Handles changes in the lyskom-process." (lyskom-remove-unread-buffer proc) (set-buffer (process-buffer proc)) (lyskom-start-of-command (lyskom-get-string 'process-signal) t t) (lyskom-format-insert 'closed-connection sentinel (lyskom-format-time 'timeformat-day-yyyy-mm-dd-hh-mm-ss)) (setq mode-line-process (lyskom-get-string 'mode-line-down)) (beep) (lyskom-scroll)) ;;; ================================================================ ;;; Debug buffer (defun lyskom-debug-limit-buffer () (when (and (numberp lyskom-debug-communications-limit) (> (point-max) lyskom-debug-communications-limit)) (delete-region (point-min) (- (point-max) lyskom-debug-communications-limit)))) (defun lyskom-debug-insert (proc prefix string) (let* ((buf (get-buffer-create lyskom-debug-communications-to-buffer-buffer)) (win (get-buffer-window buf 'visible))) (if win (save-excursion (save-selected-window (select-window win) (set-buffer buf) (let ((move (eobp))) (save-excursion (goto-char (point-max)) (insert "\n" prefix (format "%s" proc) ": " string)) (lyskom-debug-limit-buffer) (if move (goto-char (point-max)))))) (save-excursion (set-buffer buf) (goto-char (point-max)) (insert "\n" prefix (format "%s" proc) ": " string) (lyskom-debug-limit-buffer))))) ;;; For serious bugs (defun lyskom-really-serious-bug () (let ((debug-on-error t)) (error "Congratulations! You found a serious bug in lyskom.el. Press q to leave this buffer, and please run M-x kom-bug-report afterwards."))) ;;; ================================================================ ;;; Formatting functions for different data types (defun lyskom-format-objects (&rest args) "Arguments: (&rest ARGS). Format ARGS to correct format to send to server. Strings are converted to Hollerith strings. Other objects are converted correctly." (concat " " (mapconcat 'lyskom-format-object args " "))) (defun lyskom-format-object (object) (cond ((stringp object) (lyskom-prot-a-format-string object)) ((integerp object) (int-to-string object)) ((null object) "0") ((listp object) (cond ((eq (car object) 'MISC-LIST) (lyskom-prot-a-format-misc-list (cdr object))) ((eq (car object) 'AUX-ITEM) (lyskom-prot-a-format-aux-item object)) ((eq (car object) 'AUX-ITEM-FLAGS) (lyskom-prot-a-format-aux-item-flags object)) ((eq (car object) 'CONF-TYPE) (lyskom-prot-a-format-conf-type object)) ((eq (car object) 'PRIVS) (lyskom-prot-a-format-privs object)) ((eq (car object) 'FLAGS) (lyskom-prot-a-format-flags object)) ((eq (car object) 'MEMBERSHIP-TYPE) (lyskom-prot-a-format-membership-type object)) ((eq (car object) 'LIST) (lyskom-prot-a-format-simple-list (cdr object))) ((eq (car object) 'TIME) (lyskom-prot-a-format-time (cdr object))) ((eq (car object) 'STRING) (lyskom-prot-a-format-raw-string (cdr object))) (t (signal 'lyskom-internal-error (list 'lyskom-format-object ": no support for object " object))))) ((eq object t) "1") (t (signal 'lyskom-internal-error (list 'lyskom-format-object ": no support for object " object))))) (defun lyskom-prot-a-format-time (time) "Format a TIME for output to the server." (mapconcat 'int-to-string time " ")) (defun lyskom-prot-a-format-flags (flags) "Format personal flags for the server." (concat (lyskom-prot-a-format-bool (flags->unread_is_secret flags)) (lyskom-prot-a-format-bool (flags->flg2 flags)) (lyskom-prot-a-format-bool (flags->flg3 flags)) (lyskom-prot-a-format-bool (flags->flg4 flags)) (lyskom-prot-a-format-bool (flags->flg5 flags)) (lyskom-prot-a-format-bool (flags->flg6 flags)) (lyskom-prot-a-format-bool (flags->flg7 flags)) (lyskom-prot-a-format-bool (flags->flg8 flags)))) (defun lyskom-prot-a-format-membership-type (membership-type) "Format a MEMBERSHIP-TYPE for output to the server." (concat (lyskom-prot-a-format-bool (membership-type->invitation membership-type)) (lyskom-prot-a-format-bool (membership-type->passive membership-type)) (lyskom-prot-a-format-bool (membership-type->secret membership-type)) (lyskom-prot-a-format-bool (eq (membership-type->message-flag membership-type) (membership-type->passive membership-type))) (lyskom-prot-a-format-bool (membership-type->rsv2 membership-type)) (lyskom-prot-a-format-bool (membership-type->rsv3 membership-type)) (lyskom-prot-a-format-bool (membership-type->rsv4 membership-type)) (lyskom-prot-a-format-bool (membership-type->rsv5 membership-type)))) (defun lyskom-prot-a-format-conf-type (conf-type) "Format a CONF-TYPE for output to the server." (concat (lyskom-prot-a-format-bool (conf-type->rd_prot conf-type)) (lyskom-prot-a-format-bool (conf-type->original conf-type)) (lyskom-prot-a-format-bool (conf-type->secret conf-type)) (lyskom-prot-a-format-bool (conf-type->letterbox conf-type)) (if (lyskom-have-feature long-conf-types) (concat (lyskom-prot-a-format-bool (conf-type->anarchy conf-type)) (lyskom-prot-a-format-bool (conf-type->forbid-secret conf-type)) (lyskom-prot-a-format-bool (conf-type->rsv2 conf-type)) (lyskom-prot-a-format-bool (conf-type->rsv3 conf-type))) ""))) (defun lyskom-prot-a-format-aux-item (item) "Format an AUX-ITEM for output to the server." (concat (int-to-string (aux-item->tag item)) " " (lyskom-prot-a-format-aux-item-flags (aux-item->flags item)) " " (int-to-string (aux-item->inherit-limit item)) " " (lyskom-prot-a-format-raw-string (cons 'raw-text (lyskom-aux-item-output-data item))))) (defun lyskom-prot-a-format-aux-item-flags (flags) "Format AUX-ITEM-FLAGS for output to the server." (concat (lyskom-prot-a-format-bool (aux-item-flags->deleted flags)) (lyskom-prot-a-format-bool (aux-item-flags->inherit flags)) (lyskom-prot-a-format-bool (aux-item-flags->secret flags)) (lyskom-prot-a-format-bool (aux-item-flags->anonymous flags)) (lyskom-prot-a-format-bool (aux-item-flags->dont-garb flags)) (lyskom-prot-a-format-bool (aux-item-flags->reserved2 flags)) (lyskom-prot-a-format-bool (aux-item-flags->reserved3 flags)) (lyskom-prot-a-format-bool (aux-item-flags->reserved4 flags)))) (defun lyskom-prot-a-format-privs (privs) "Format PRIVS for output to the server." (concat (lyskom-prot-a-format-bool (privs->wheel privs)) (lyskom-prot-a-format-bool (privs->admin privs)) (lyskom-prot-a-format-bool (privs->statistic privs)) (lyskom-prot-a-format-bool (privs->create_pers privs)) (lyskom-prot-a-format-bool (privs->create_conf privs)) (lyskom-prot-a-format-bool (privs->change_name privs)) (lyskom-prot-a-format-bool (privs->flg7 privs)) (lyskom-prot-a-format-bool (privs->flg8 privs)) (lyskom-prot-a-format-bool (privs->flg9 privs)) (lyskom-prot-a-format-bool (privs->flg10 privs)) (lyskom-prot-a-format-bool (privs->flg11 privs)) (lyskom-prot-a-format-bool (privs->flg12 privs)) (lyskom-prot-a-format-bool (privs->flg13 privs)) (lyskom-prot-a-format-bool (privs->flg14 privs)) (lyskom-prot-a-format-bool (privs->flg15 privs)) (lyskom-prot-a-format-bool (privs->flg16 privs)))) (defun lyskom-prot-a-format-bool (bool) "Format a BOOL for output to the server." (if bool "1" "0")) (defun lyskom-prot-a-format-misc-list (misc-list) "Format a misc-list for output to the server." (let ((result (format "%d {" (length misc-list)))) (while (not (null misc-list)) (setq result (concat result " " (lyskom-prot-a-format-misc-item (car misc-list)))) (setq misc-list (cdr misc-list))) (setq result (concat result " }")))) (defun lyskom-prot-a-format-misc-item (misc-item) "Format a misc-item for output to the server." (format "%d %d" (cond ((eq (car misc-item) 'RECPT) 0) ((eq (car misc-item) 'CC-RECPT) 1) ((eq (car misc-item) 'COMM-TO) 2) ((eq (car misc-item) 'FOOTN-TO) 4) ((eq (car misc-item) 'BCC-RECPT) (if (lyskom-have-feature bcc-misc) 15 1))) (cdr misc-item))) (defun lyskom-prot-a-format-simple-list (list) "Format some kind of list to send to server." (apply 'concat (list (format "%d {" (length list)) (apply 'lyskom-format-objects list) " }"))) (defun lyskom-prot-a-format-string (string) (let ((tmp (lyskom-encode-coding-string string lyskom-server-coding-system))) (lyskom-string-as-unibyte (format "%dH%s" (lyskom-string-bytes tmp) tmp)))) (defun lyskom-prot-a-format-raw-string (string) (lyskom-string-as-unibyte (format "%dH%s" (lyskom-string-bytes (cdr string)) (cdr string)))) ;;;; ================================================================ ;;;; Utility routines. ;;; silent-read was ;; Written by Lars Willf|r ;; Copyright and copyleft Lars Willf|r. ;; Last modified jun 93 by Linus Tolke (defun silent-read (prompt-str) "Read a string in the minibuffer without echoing. One parameter - the prompt string." (interactive "sPrompt string: ") (lyskom-message "%s" prompt-str) (let ((input-string "") (input-char) (cursor-in-echo-area t)) (while (not (or (eq (setq input-char (condition-case err (read-char-exclusive) (error (if (string= "Non-character input-event" (car (cdr err))) ?\r (signal (car err) (cdr err)))))) ?\r) (eq input-char ?\n))) (progn (lyskom-message "%s" prompt-str) (setq input-string (cond ((eq input-char ?\C-?) (if (equal (length input-string) 0) "" (substring input-string 0 -1))) ((eq input-char ?\C-u) "") (t (concat input-string (char-to-string input-char))))))) (message "") input-string)) (defun lyskom-session-nickname (&optional in-modeline) "Return the nickname to use for this LysKOM session." (if kom-session-nickname kom-session-nickname (let ((server (process-name (get-buffer-process (current-buffer))))) (or (cdr (assoc server (append kom-server-aliases kom-builtin-server-aliases))) (if in-modeline (format "LysKOM(%s)" server) server))))) ;;; This really is a strange thing to do but... ;; (defun lyskom-mode-name-from-host () "Calculate what to identify the buffer with." (setq mode-line-server-name (lyskom-session-nickname t))) (defvar lyskom-modeline-keymap nil) (if lyskom-modeline-keymap nil (setq lyskom-modeline-keymap (make-sparse-keymap)) (lyskom-xemacs-or-gnu (progn (define-key lyskom-modeline-keymap (kbd (lyskom-keys 'button2up)) 'kom-modeline-next-unread-kom) (define-key lyskom-modeline-keymap (kbd (lyskom-keys 'button3)) 'kom-modeline-select-unread-kom)) (progn (define-key lyskom-modeline-keymap [mode-line mouse-2] 'kom-modeline-next-unread-kom) (define-key lyskom-modeline-keymap [mode-line mouse-3] 'kom-modeline-select-unread-kom)))) (defun lyskom-make-alternate-unread-mode-line () (save-excursion (let ((mline ()) (current nil) (upcased nil)) (lyskom-traverse session lyskom-sessions-with-unread (set-buffer session) (setq current (lyskom-session-nickname)) (when (memq session lyskom-sessions-with-unread-letters) (setq upcased (upcase current)) (setq current (if (string= upcased current) (concat "*" current "*") upcased))) (setq mline (append mline (list (concat current " "))))) (setq mline (sort mline 'string<)) mline))) (defun lyskom-make-lyskom-unread-mode-line () (if kom-unread-mode-line-type (lyskom-make-alternate-unread-mode-line) (lyskom-xemacs-or-gnu (list (list 'lyskom-sessions-with-unread (lyskom-get-string 'mode-line-unread)) (list 'lyskom-sessions-with-unread-letters (lyskom-get-string 'mode-line-letters)) " ") `((lyskom-sessions-with-unread ,(lyskom-format "%#1@%#2s" (list 'local-map lyskom-modeline-keymap) (lyskom-get-string 'mode-line-unread))) (lyskom-sessions-with-unread-letters ,(lyskom-format "%#1@%#2s" (list 'local-map lyskom-modeline-keymap) (lyskom-get-string 'mode-line-letters))) " ")))) (defun lyskom-make-lyskom-unread-title-format () `(kom-show-unread-in-frame-title (lyskom-session-has-unreads (" (" ((lyskom-session-has-unreads ,(lyskom-recode-string-for-title (lyskom-get-string 'frame-title-unread) 'iso-8859-1)) (lyskom-session-has-unread-letters ,(lyskom-recode-string-for-title (lyskom-get-string 'frame-title-letters) 'iso-8859-1))) ")")))) (defvar icon-title-format) (defvar frame-icon-title-format) (if lyskom-is-loaded nil ;; Fix altered format for kom-default-language (when (and kom-default-language (symbolp kom-default-language)) (setq kom-default-language (list kom-default-language))) ;; Set up default language (setq lyskom-language (lyskom-default-language)) (setq lyskom-global-language lyskom-language) (unless kom-default-language (setq kom-default-language (list lyskom-language))) (setq-default lyskom-collate-table lyskom-default-collate-table) ;; We should set lyskom-char-classes to ;; (lyskom-compute-char-classes lyskom-collate-table)) ;; but that currently fails under Emacs 20.7, because ;; lyskom-default-collate-table isn't set properly. (setq-default lyskom-char-classes nil) (lyskom-set-language lyskom-language 'local) (lyskom-set-language lyskom-language 'global) (unless (or (memq 'lyskom-unread-mode-line global-mode-string) (rassq 'lyskom-unread-mode-line global-mode-string)) (lyskom-xemacs-or-gnu (let ((extent (make-extent nil nil nil))) (set-extent-keymap extent lyskom-modeline-keymap) (setq global-mode-string (append (list "" (cons extent 'lyskom-unread-mode-line)) global-mode-string))) (setq global-mode-string (append '("" lyskom-unread-mode-line) global-mode-string)))) (if (boundp 'frame-title-format) (setq frame-title-format (list "" frame-title-format 'lyskom-unread-title-format))) (if (boundp 'icon-title-format) (setq icon-title-format (list "" icon-title-format 'lyskom-unread-title-format))) (if (boundp 'frame-icon-title-format) (setq frame-icon-title-format (list "" frame-icon-title-format 'lyskom-unread-title-format))) (add-hook 'kill-buffer-hook 'lyskom-remove-buffer-from-lists) ;;; ;;; Set up lyskom-line-start-chars. The reason we do it here is that ;;; char-to-int may not be defined until compatibility.el has been ;;; loaded. ;;; (setq lyskom-line-start-chars (let ((tmp (make-vector 256 nil))) (mapcar (function (lambda (x) (aset tmp (lyskom-char-to-int x) t))) (lyskom-maybe-recode-string lyskom-line-start-chars-string 'iso-8859-1 t)) tmp)) ;; Setup the queue priorities (lyskom-set-queue-priority 'blocking 9) (lyskom-set-queue-priority 'main 9) (lyskom-set-queue-priority 'sending 9) (lyskom-set-queue-priority 'follow 9) (lyskom-set-queue-priority 'options 9) (lyskom-set-queue-priority 'deferred 6) (lyskom-set-queue-priority 'background 6) (lyskom-set-queue-priority 'modeline 6) (lyskom-set-queue-priority 'async 3) (lyskom-set-queue-priority 'prefetch 0) ;; Seed the randomizer (random t) (run-hooks 'lyskom-after-load-hook) (run-hooks 'kom-after-load-hook) (setq lyskom-is-loaded t)) (provide 'lyskom-rest) ;;; This should be the very last lines of lyskom.el Everything should ;;; be loaded now, so it's time to run the kom-after-load-hook. (lyskom-end-of-compilation) ;;; Local Variables: ;;; eval: (put 'lyskom-traverse 'lisp-indent-hook 2) ;;; end: