# HG changeset patch # User Miles Bader # Date 1188354564 0 # Node ID c3228e91eb9ecd697b42ad81a5bfa8205869d420 # Parent a30538bafc32c1898d3aa5f57b4a15f8c4aeafab# Parent 57df421aa5e8077cc7f4a00c1132254efd937f9e Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 864) - Update from CVS Revision: emacs@sv.gnu.org/emacs--multi-tty--0--patch-41 diff -r a30538bafc32 -r c3228e91eb9e admin/ChangeLog --- a/admin/ChangeLog Wed Aug 29 02:29:12 2007 +0000 +++ b/admin/ChangeLog Wed Aug 29 02:29:24 2007 +0000 @@ -1,3 +1,7 @@ +2007-08-28 Glenn Morris + + * admin.el: Provide self. + 2007-08-10 Jan Dj,Ad(Brv * FOR-RELEASE (http): Add Gtk+ tool bar and GUD focus problem. diff -r a30538bafc32 -r c3228e91eb9e admin/admin.el --- a/admin/admin.el Wed Aug 29 02:29:12 2007 +0000 +++ b/admin/admin.el Wed Aug 29 02:29:24 2007 +0000 @@ -205,5 +205,7 @@ ?\" (0+ space) "/* Long version number */"))))) +(provide 'admin) + ;;; arch-tag: 4ea83636-2293-408b-884e-ad64f22a3bf5 ;; admin.el ends here. diff -r a30538bafc32 -r c3228e91eb9e lisp/ChangeLog --- a/lisp/ChangeLog Wed Aug 29 02:29:12 2007 +0000 +++ b/lisp/ChangeLog Wed Aug 29 02:29:24 2007 +0000 @@ -1,3 +1,17 @@ +2007-08-28 Johan Bockg,Ae(Brd (tiny change) + + * play/gamegrid.el (gamegrid-init): Set line-spacing to 0. + +2007-08-28 Glenn Morris + + * progmodes/cc-langs.el (c-constant-kwds): Add java: null, true, + false. + +2007-08-27 Thien-Thi Nguyen + + * progmodes/modula2.el (m2-definition, m2-module): + Don't use previous-line. Reported by T. V. Raman. + 2007-08-27 YAMAMOTO Mitsuharu * term/mac-win.el (mac-handle-toolbar-switch-mode): Add explicit diff -r a30538bafc32 -r c3228e91eb9e lisp/play/bubbles.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/play/bubbles.el Wed Aug 29 02:29:24 2007 +0000 @@ -0,0 +1,1433 @@ +;;; bubbles.el --- Puzzle game for Emacs. + +;; Copyright (C) 2007 Free Software Foundation, Inc. + +;; Author: Ulf Jasper +;; URL: http://ulf.epplejasper.de/ +;; Created: 5. Feb. 2007 +;; Keywords: games + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 3, or (at your option) +;; any later version. + +;; GNU Emacs 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 Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Bubbles is a puzzle game. Its goal is to remove as many bubbles as +;; possible in as few moves as possible. + +;; Bubbles is an implementation of the "Same Game", similar to "Same +;; GNOME" and many others, see . + +;; Installation +;; ------------ + +;; Add the following lines to your Emacs startup file (`~/.emacs'). +;; (add-to-list 'load-path "/path/to/bubbles/") +;; (autoload 'bubbles "bubbles" "Play Bubbles" t) + +;; ====================================================================== + +;;; History: + +;; 0.4 (2007-08-27) +;; - Allow for undoing last move. +;; - Bonus for removing all bubbles. +;; - Speed improvements. +;; - Animation enhancements. +;; - Added `bubbles-mode-hook'. +;; - Fixes: Don't move point. +;; - New URL. + +;; 0.3 (2007-03-11) +;; - Renamed shift modes and thus names of score files. All +;; highscores are lost, unless you rename the score files from +;; bubbles-shift-... to bubbles-...! +;; - Bugfixes: Check for successful image creation. +;; Disable menus and counter when game is over. +;; Tested with GNU Emacs 22.0.93 + +;; 0.2 (2007-02-24) +;; - Introduced game themes. +;; - Introduced graphics themes (changeable while playing). +;; - Added menu. +;; - Customization: grid size, colors, chars, shift mode. +;; - More keybindings. +;; - Changed shift direction from to-right to to-left. +;; - Bugfixes: Don't remove single-bubble regions; +;; Animation glitches fixed. +;; Tested with GNU Emacs 22.0.93 and 21.4.1. + +;; 0.1 (2007-02-11) +;; Initial release. Tested with GNU Emacs 22.0.93 and 21.4.1. + +;; ====================================================================== + +;;; Code: + +(defconst bubbles-version "0.4" "Version number of bubbles.el.") + +(require 'gamegrid) +(require 'cl) + +;; User options + +;; Careful with that axe, Eugene! Order does matter in the custom +;; section below. + +(defcustom bubbles-game-theme + 'easy + "Overall game theme. +The overall game theme specifies a grid size, a set of colors, +and a shift mode." + :type '(radio (const :tag "Easy" easy) + (const :tag "Medium" medium) + (const :tag "Difficult" difficult) + (const :tag "Hard" hard) + (const :tag "User defined" user-defined)) + :group 'bubbles) + +(defun bubbles-set-game-easy () + "Set game theme to 'easy'." + (interactive) + (setq bubbles-game-theme 'easy) + (bubbles)) + +(defun bubbles-set-game-medium () + "Set game theme to 'medium'." + (interactive) + (setq bubbles-game-theme 'medium) + (bubbles)) + +(defun bubbles-set-game-difficult () + "Set game theme to 'difficult'." + (interactive) + (setq bubbles-game-theme 'difficult) + (bubbles)) + +(defun bubbles-set-game-hard () + "Set game theme to 'hard'." + (interactive) + (setq bubbles-game-theme 'hard) + (bubbles)) + +(defun bubbles-set-game-userdefined () + "Set game theme to 'user-defined'." + (interactive) + (setq bubbles-game-theme 'user-defined) + (bubbles)) + +(defgroup bubbles nil + "Bubbles, a puzzle game." + :group 'games) + +(defcustom bubbles-graphics-theme + 'circles + "Graphics theme. +It is safe to choose a graphical theme. If Emacs cannot display +images the `ascii' theme will be used." + :type '(radio (const :tag "Circles" circles) + (const :tag "Squares" squares) + (const :tag "Diamonds" diamonds) + (const :tag "Balls" balls) + (const :tag "Emacs" emacs) + (const :tag "ASCII (no images)" ascii)) + :group 'bubbles) + +(defconst bubbles--grid-small '(10 . 10) + "Predefined small bubbles grid.") + +(defconst bubbles--grid-medium '(15 . 10) + "Predefined medium bubbles grid.") + +(defconst bubbles--grid-large '(20 . 15) + "Predefined large bubbles grid.") + +(defconst bubbles--grid-huge '(30 . 20) + "Predefined huge bubbles grid.") + +(defcustom bubbles-grid-size + bubbles--grid-medium + "Size of bubbles grid." + :type `(radio (const :tag "Small" ,bubbles--grid-small) + (const :tag "Medium" ,bubbles--grid-medium) + (const :tag "Large" ,bubbles--grid-large) + (const :tag "Huge" ,bubbles--grid-huge) + (cons :tag "User defined" + (integer :tag "Width") + (integer :tag "Height"))) + :group 'bubbles) + +(defconst bubbles--colors-2 '("orange" "violet") + "Predefined bubbles color list with two colors.") + +(defconst bubbles--colors-3 '("lightblue" "palegreen" "pink") + "Predefined bubbles color list with three colors.") + +(defconst bubbles--colors-4 '("firebrick" "sea green" "steel blue" "chocolate") + "Predefined bubbles color list with four colors.") + +(defconst bubbles--colors-5 '("firebrick" "sea green" "steel blue" + "sandy brown" "bisque3") + "Predefined bubbles color list with five colors.") + +(defcustom bubbles-colors + bubbles--colors-3 + "List of bubble colors. +The length of this list determines how many different bubble +types are present." + :type `(radio (const :tag "Red, darkgreen" ,bubbles--colors-2) + (const :tag "Red, darkgreen, blue" ,bubbles--colors-3) + (const :tag "Red, darkgreen, blue, orange" ,bubbles--colors-4) + (const :tag "Red, darkgreen, blue, orange, violet" + ,bubbles--colors-5) + (repeat :tag "User defined" color)) + :group 'bubbles) + +(defcustom bubbles-chars + '(?+ ?O ?# ?X ?. ?* ?& ?§) + "Characters used for bubbles. +Note that the actual number of different bubbles is determined by +the number of colors, see `bubbles-colors'." + :type '(repeat character) + :group 'bubbles) + +(defcustom bubbles-shift-mode + 'default + "Shift mode. +Available modes are `shift-default' and`shift-always'." + :type '(radio (const :tag "Default" default) + (const :tag "Shifter" always) + ;;(const :tag "Mega Shifter" 'mega) + ) + :group 'bubbles) + +(defcustom bubbles-mode-hook nil + "Hook run by Bubbles mode." + :group 'bubbles + :type 'hook) + +(defun bubbles-customize () + "Open customization buffer for bubbles." + (interactive) + (customize-group 'bubbles)) + +;; ====================================================================== +;; internal variables + +(defvar bubbles--score 0 + "Current Bubbles score.") + +(defvar bubbles--neighbourhood-score 0 + "Score of active bubbles neighbourhood.") + +(defvar bubbles--faces nil + "List of currently used faces.") + +(defvar bubbles--playing nil + "Play status indicator.") + +(defvar bubbles--empty-image nil + "Image used for removed bubbles (empty grid cells).") + +(defvar bubbles--images nil + "List of images for bubbles.") + +(defvar bubbles--images-ok nil + "Indicate whether images have been created successfully.") + +(defvar bubbles--col-offset 0 + "Horizontal offset for centering the bubbles grid.") + +(defvar bubbles--row-offset 0 + "Vertical offset for centering the bubbles grid.") + +(defvar bubbles--save-data nil + "List containing bubbles save data (SCORE BUFFERCONTENTS).") + +(defconst bubbles--image-template-circle + "/* XPM */ +static char * dot_xpm[] = { +\"20 20 2 1\", +\" c None\", +\". c #FFFFFF\", +\" ...... \", +\" .......... \", +\" .............. \", +\" ................ \", +\" ................ \", +\" .................. \", +\" .................. \", +\"....................\", +\"....................\", +\"....................\", +\"....................\", +\"....................\", +\"....................\", +\" .................. \", +\" .................. \", +\" ................ \", +\" ................ \", +\" .............. \", +\" .......... \", +\" ...... \"};") + +(defconst bubbles--image-template-square + "/* XPM */ +static char * dot_xpm[] = { +\"20 20 2 1\", +\"0 c None\", +\"1 c #FFFFFF\", +\"00000000000000000000\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"01111111111111111110\", +\"00000000000000000000\"};") + +(defconst bubbles--image-template-diamond + "/* XPM */ +static char * dot_xpm[] = { +\"20 20 2 1\", +\"0 c None\", +\"1 c #FFFFFF\", +\"00000000011000000000\", +\"00000000111100000000\", +\"00000001111110000000\", +\"00000011111111000000\", +\"00000111111111100000\", +\"00001111111111110000\", +\"00011111111111111000\", +\"00111111111111111100\", +\"01111111111111111110\", +\"11111111111111111111\", +\"01111111111111111110\", +\"00111111111111111100\", +\"00011111111111111000\", +\"00001111111111110000\", +\"00000111111111100000\", +\"00000011111111000000\", +\"00000001111110000000\", +\"00000000111100000000\", +\"00000000011000000000\", +\"00000000000000000000\"};") + +(defconst bubbles--image-template-emacs + "/* XPM */ +static char * emacs_24_xpm[] = { +\"24 24 129 2\", +\" c None\", +\". c #837DA4\", +\"+ c #807AA0\", +\"@ c #9894B2\", +\"# c #CCCAD9\", +\"$ c #C2C0D2\", +\"% c #B6B3C9\", +\"& c #A19DB9\", +\"* c #8681A5\", +\"= c #7D779B\", +\"- c #B6B3C7\", +\"; c #ABA7BE\", +\"> c #9792AF\", +\", c #AAA6BD\", +\"' c #CBC9D7\", +\") c #AAA7BE\", +\"! c #908BAA\", +\"~ c #797397\", +\"{ c #948FAC\", +\"] c #9A95B1\", +\"^ c #EBEAEF\", +\"/ c #F1F1F5\", +\"( c #BCB9CB\", +\"_ c #A9A5BD\", +\": c #757093\", +\"< c #918DA9\", +\"[ c #DDDBE4\", +\"} c #FFFFFF\", +\"| c #EAE9EF\", +\"1 c #A7A4BA\", +\"2 c #716C8F\", +\"3 c #8D89A5\", +\"4 c #9C98B1\", +\"5 c #DBDAE3\", +\"6 c #A4A1B7\", +\"7 c #6E698A\", +\"8 c #8B87A1\", +\"9 c #928EA7\", +\"0 c #C5C3D1\", +\"a c #F8F8F9\", +\"b c #CCCAD6\", +\"c c #A29FB4\", +\"d c #6A6585\", +\"e c #88849D\", +\"f c #B5B2C2\", +\"g c #F0F0F3\", +\"h c #E1E0E6\", +\"i c #A5A2B5\", +\"j c #A09DB1\", +\"k c #676281\", +\"l c #85819A\", +\"m c #9591A7\", +\"n c #E1E0E5\", +\"o c #F0EFF2\", +\"p c #B3B0C0\", +\"q c #9D9AAE\", +\"r c #635F7C\", +\"s c #827F96\", +\"t c #9997AA\", +\"u c #F7F7F9\", +\"v c #C8C7D1\", +\"w c #89869D\", +\"x c #9B99AB\", +\"y c #5F5B78\", +\"z c #7F7C93\", +\"A c #CFCDD6\", +\"B c #B7B5C2\", +\"C c #9996A9\", +\"D c #5C5873\", +\"E c #7A778D\", +\"F c #F5F5F6\", +\"G c #8E8C9E\", +\"H c #7D798F\", +\"I c #58546F\", +\"J c #6C6981\", +\"K c #D5D4DB\", +\"L c #F5F4F6\", +\"M c #9794A5\", +\"N c #625F78\", +\"O c #79768C\", +\"P c #55516A\", +\"Q c #605C73\", +\"R c #CAC9D1\", +\"S c #EAE9EC\", +\"T c #B4B3BE\", +\"U c #777488\", +\"V c #514E66\", +\"W c #DEDEE2\", +\"X c #F4F4F5\", +\"Y c #9D9BA9\", +\"Z c #747185\", +\"` c #4E4B62\", +\" . c #DEDDE1\", +\".. c #A6A5B0\", +\"+. c #716F81\", +\"@. c #4A475D\", +\"#. c #A4A3AE\", +\"$. c #F4F3F5\", +\"%. c #777586\", +\"&. c #6E6C7D\", +\"*. c #464358\", +\"=. c #514E62\", +\"-. c #B9B8C0\", +\";. c #D1D0D5\", +\">. c #747282\", +\",. c #6B6979\", +\"'. c #434054\", +\"). c #5A5769\", +\"!. c #D0CFD4\", +\"~. c #5B5869\", +\"{. c #696676\", +\"]. c #403D50\", +\"^. c #DBDADE\", +\"/. c #F3F3F4\", +\"(. c #646271\", +\"_. c #666473\", +\":. c #3D3A4C\", +\"<. c #555362\", +\"[. c #9E9DA6\", +\"}. c #9E9CA5\", +\"|. c #646170\", +\"1. c #393647\", +\"2. c #514E5D\", +\"3. c #83818C\", +\"4. c #A8A7AE\", +\"5. c #E6E6E8\", +\"6. c #DAD9DC\", +\"7. c #353343\", +\"8. c #32303E\", +\" . . . . . . . . . . . . . . . . . . \", +\" + @ # $ % % % % % % % % % % % % % % & * + + \", +\" = - ; > > > > > > > > , ' ) > > > > > > ! = \", +\"~ ~ { { { { { { { { { { { ] ^ / ( { { { { _ ~ ~ \", +\": : < < < < < < < < < < < < [ } } | < < < 1 : : \", +\"2 2 3 3 3 3 3 3 3 3 3 3 4 5 } } } 5 3 3 3 6 2 2 \", +\"7 7 8 8 8 8 8 8 8 8 9 0 a } } } b 8 8 8 8 c 7 7 \", +\"d d e e e e e e e f g } } } h i e e e e e j d d \", +\"k k l l l l l m n } } } o p l l l l l l l q k k \", +\"r r s s s s t u } } } v w s s s s s s s s x r r \", +\"y y z z z z A } } } B z z z z z z z z z z C y y \", +\"D D D D D D E F } } G D D D D D D D D D D H D D \", +\"I I I I I I I J K } L M N I I I I I I I I O I I \", +\"P P P P P P Q R } } } S T P P P P P P P P U P P \", +\"V V V V V V W } } X Y V V V V V V V V V V Z V V \", +\"` ` ` ` ` ` .} } ..` ` ` ` ` ` ` ` ` ` ` +.` ` \", +\"@.@.@.@.@.@.@.#.$.$.%.@.@.@.@.@.@.@.@.@.@.&.@.@.\", +\"*.*.*.*.*.*.*.*.=.-.} ;.>.*.*.*.*.*.*.*.*.,.*.*.\", +\"'.'.'.'.'.'.'.'.'.'.).!.} !.~.'.'.'.'.'.'.{.'.'.\", +\"].].].].].].].].].].].].^.} /.(.].].].].]._.].].\", +\":.:.:.:.:.:.:.:.:.:.<.[./.} } }.:.:.:.:.:.|.:.:.\", +\" 1.1.1.1.1.1.1.1.2.3.4.5.6.3.1.1.1.1.1.1.1.1. \", +\" 7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7. \", +\" 8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8. \"};") + +(defconst bubbles--image-template-ball + "/* XPM */ +static char * dot3d_xpm[] = { +\"20 20 190 2\", +\" c None\", +\". c #F9F6F6\", +\"+ c #D6D0D0\", +\"@ c #BFBBBB\", +\"# c #AAA4A4\", +\"$ c #ABAAAB\", +\"% c #A8A8A8\", +\"& c #A29D9D\", +\"* c #B5B2B2\", +\"= c #CDC9C9\", +\"- c #D7D0D0\", +\"; c #B3AFAF\", +\"> c #B5B5B5\", +\", c #B7B7B7\", +\"' c #B8B8B8\", +\") c #B6B6B6\", +\"! c #B3B3B3\", +\"~ c #AFAFAF\", +\"{ c #A9A9A9\", +\"] c #A2A2A2\", +\"^ c #9C9A9A\", +\"/ c #C9C5C5\", +\"( c #FDFBFB\", +\"_ c #C3BCBC\", +\": c #BBBBBB\", +\"< c #C0C0C0\", +\"[ c #C3C2C2\", +\"} c #C3C3C3\", +\"| c #C2C2C2\", +\"1 c #BEBEBE\", +\"2 c #B9B9B9\", +\"3 c #B2B2B2\", +\"4 c #ABAAAA\", +\"5 c #999999\", +\"6 c #ACA7A7\", +\"7 c #C2BBBB\", +\"8 c #C5C5C5\", +\"9 c #CACBCB\", +\"0 c #CECECE\", +\"a c #CFCFCF\", +\"b c #CDCDCD\", +\"c c #C8C9C9\", +\"d c #9F9F9F\", +\"e c #959595\", +\"f c #A9A5A5\", +\"g c #D5CFCE\", +\"h c #BDBDBD\", +\"i c #C6C6C6\", +\"j c #D5D5D5\", +\"k c #D9D9D9\", +\"l c #DADADA\", +\"m c #D8D8D8\", +\"n c #D2D2D2\", +\"o c #CBCBCB\", +\"p c #A4A4A5\", +\"q c #9A9A9A\", +\"r c #8F8F8F\", +\"s c #C3BFBF\", +\"t c #AFACAB\", +\"u c #CCCCCC\", +\"v c #D6D6D6\", +\"w c #DEDEDE\", +\"x c #E4E4E4\", +\"y c #E5E5E5\", +\"z c #E2E2E2\", +\"A c #DBDBDB\", +\"B c #C9C8C8\", +\"C c #A8A9A8\", +\"D c #9D9E9D\", +\"E c #929292\", +\"F c #8A8888\", +\"G c #D3CECE\", +\"H c #B0B0B0\", +\"I c #D1D1D1\", +\"J c #DCDCDC\", +\"K c #E6E6E6\", +\"L c #EEEEEE\", +\"M c #F1F1F0\", +\"N c #EBEBEB\", +\"O c #D7D7D8\", +\"P c #ABABAB\", +\"Q c #A0A0A0\", +\"R c #949494\", +\"S c #898989\", +\"T c #C0BDBD\", +\"U c #B9B6B6\", +\"V c #B1B1B1\", +\"W c #BCBCBC\", +\"X c #C8C8C8\", +\"Y c #D3D3D3\", +\"Z c #DFDFDE\", +\"` c #EAEAEA\", +\" . c #F5F5F5\", +\".. c #FAFAFA\", +\"+. c #F1F1F1\", +\"@. c #CECFCF\", +\"#. c #ACACAC\", +\"$. c #A1A1A1\", +\"%. c #8A8A8A\", +\"&. c #9B9999\", +\"*. c #C7C7C7\", +\"=. c #DDDDDD\", +\"-. c #E8E8E8\", +\";. c #F2F2F2\", +\">. c #898A89\", +\",. c #7A7878\", +\"'. c #AEAEAE\", +\"). c #C4C4C4\", +\"!. c #CBCBCA\", +\"~. c #AAAAAA\", +\"{. c #939393\", +\"]. c #888888\", +\"^. c #7C7C7C\", +\"/. c #AAAAAB\", +\"(. c #BFBFBF\", +\"_. c #C9C9C9\", +\":. c #DFDEDF\", +\"<. c #A6A6A6\", +\"[. c #9B9B9B\", +\"}. c #909191\", +\"|. c #858586\", +\"1. c #797979\", +\"2. c #989494\", +\"3. c #A5A6A5\", +\"4. c #B9B9B8\", +\"5. c #C1C1C1\", +\"6. c #CFCFCE\", +\"7. c #979797\", +\"8. c #8D8D8D\", +\"9. c #828282\", +\"0. c #747171\", +\"a. c #ADAAAA\", +\"b. c #A9A8A9\", +\"c. c #B8B9B9\", +\"d. c #A5A5A5\", +\"e. c #9C9C9C\", +\"f. c #7E7E7D\", +\"g. c #929191\", +\"h. c #C9C4C4\", +\"i. c #989898\", +\"j. c #ADADAD\", +\"k. c #9D9D9D\", +\"l. c #8C8C8C\", +\"m. c #787878\", +\"n. c #B8B6B6\", +\"o. c #939191\", +\"p. c #A5A5A6\", +\"q. c #ABABAA\", +\"r. c #A8A8A9\", +\"s. c #A3A3A3\", +\"t. c #858585\", +\"u. c #757474\", +\"v. c #C5C1C1\", +\"w. c #969696\", +\"x. c #9B9B9C\", +\"y. c #A4A4A4\", +\"z. c #9E9E9E\", +\"A. c #939394\", +\"B. c #7D7D7D\", +\"C. c #747474\", +\"D. c #B7B5B5\", +\"E. c #A5A1A1\", +\"F. c #919191\", +\"G. c #9A9999\", +\"H. c #838383\", +\"I. c #757575\", +\"J. c #939090\", +\"K. c #A29E9E\", +\"L. c #868686\", +\"M. c #8D8D8C\", +\"N. c #8E8E8E\", +\"O. c #8D8D8E\", +\"P. c #8B8C8C\", +\"Q. c #848485\", +\"R. c #7F7F80\", +\"S. c #7A7A7A\", +\"T. c #737373\", +\"U. c #929090\", +\"V. c #828080\", +\"W. c #818181\", +\"X. c #808080\", +\"Y. c #7E7E7E\", +\"Z. c #737272\", +\"`. c #B7B4B4\", +\" + c #BCBABA\", +\".+ c #959494\", +\"++ c #747172\", +\"@+ c #767676\", +\"#+ c #6F6D6D\", +\"$+ c #8F8E8E\", +\" . + @ # $ % & * = . \", +\" - ; > , ' ) ! ~ { ] ^ / \", +\" ( _ > : < [ } | 1 2 3 4 ] 5 6 ( \", +\" 7 ) 1 8 9 0 a b c | : 3 { d e f \", +\" g ! h i 0 j k l m n o | 2 ~ p q r s \", +\". t ' | u v w x y z A n B 1 ! C D E F . \", +\"G H : i I J K L M N z O b | ) P Q R S T \", +\"U V W X Y Z ` ...+.y l @.} ' #.$.e %.&.\", +\"& H W *.n =.-.;. .L x k 0 [ , #.Q e >.,.\", +\"] '.2 ).a k z -.` K w j !.< > ~.d {.].^.\", +\"d /.> (._.I k =.:.J v 0 8 : V <.[.}.|.1.\", +\"2.3.~ 4.5._.6.n Y I u i 1 > P $.7.8.9.0.\", +\"a.d b.V c.(.).*.X i | h ) '.d.e.E ].f.g.\", +\"h.i.$.C ~ > 2 W W : ' ! j.d.k.e l.9.m.n.\", +\". o.i.d p.q.'.H V H j.r.s.k.e 8.t.^.u.. \", +\" v.r w.x.Q s.d.d.y.] z.5 A.8.t.B.C.D. \", +\" E.l.F.e i.G.q 5 7.{.r %.H.^.I.J. \", +\" ( K.L.%.M.N.N.O.P.S Q.R.S.T.U.( \", +\" @ V.W.H.H.9.X.Y.S.I.Z.`. \", +\" . +.+++@+C.#+$+D.. \"};") + +;; ====================================================================== +;; Functions + +(defsubst bubbles--grid-width () + "Return the grid width for the current game theme." + (car (case bubbles-game-theme + ('easy + bubbles--grid-small) + ('medium + bubbles--grid-medium) + ('difficult + bubbles--grid-large) + ('hard + bubbles--grid-huge) + ('user-defined + bubbles-grid-size)))) + +(defsubst bubbles--grid-height () + "Return the grid height for the current game theme." + (cdr (case bubbles-game-theme + ('easy + bubbles--grid-small) + ('medium + bubbles--grid-medium) + ('difficult + bubbles--grid-large) + ('hard + bubbles--grid-huge) + ('user-defined + bubbles-grid-size)))) + +(defsubst bubbles--colors () + "Return the color list for the current game theme." + (case bubbles-game-theme + ('easy + bubbles--colors-2) + ('medium + bubbles--colors-3) + ('difficult + bubbles--colors-4) + ('hard + bubbles--colors-5) + ('user-defined + bubbles-colors))) + +(defsubst bubbles--shift-mode () + "Return the shift mode for the current game theme." + (case bubbles-game-theme + ('easy + 'default) + ('medium + 'default) + ('difficult + 'always) + ('hard + 'always) + ('user-defined + bubbles-shift-mode))) + +(defun bubbles-save-settings () + "Save current customization settings." + (interactive) + (custom-set-variables + (list 'bubbles-game-theme `(quote ,bubbles-game-theme) t) + (list 'bubbles-graphics-theme `(quote ,bubbles-graphics-theme) t)) + (customize-save-customized)) + +(defsubst bubbles--empty-char () + "The character used for removed bubbles (empty grid cells)." + ? ) + +(defun bubbles-set-graphics-theme-ascii () + "Set graphics theme to `ascii'." + (interactive) + (setq bubbles-graphics-theme 'ascii) + (bubbles--update-faces-or-images)) + +(defun bubbles-set-graphics-theme-circles () + "Set graphics theme to `circles'." + (interactive) + (setq bubbles-graphics-theme 'circles) + (bubbles--initialize-images) + (bubbles--update-faces-or-images)) + +(defun bubbles-set-graphics-theme-squares () + "Set graphics theme to `squares'." + (interactive) + (setq bubbles-graphics-theme 'squares) + (bubbles--initialize-images) + (bubbles--update-faces-or-images)) + +(defun bubbles-set-graphics-theme-diamonds () + "Set graphics theme to `diamonds'." + (interactive) + (setq bubbles-graphics-theme 'diamonds) + (bubbles--initialize-images) + (bubbles--update-faces-or-images)) + +(defun bubbles-set-graphics-theme-balls () + "Set graphics theme to `balls'." + (interactive) + (setq bubbles-graphics-theme 'balls) + (bubbles--initialize-images) + (bubbles--update-faces-or-images)) + +(defun bubbles-set-graphics-theme-emacs () + "Set graphics theme to `emacs'." + (interactive) + (setq bubbles-graphics-theme 'emacs) + (bubbles--initialize-images) + (bubbles--update-faces-or-images)) + +;; bubbles mode map +(defvar bubbles-mode-map + (make-keymap 'bubbles-mode-map)) +(define-key bubbles-mode-map "q" 'bubbles-quit) +(define-key bubbles-mode-map "\n" 'bubbles-plop) +(define-key bubbles-mode-map " " 'bubbles-plop) +(define-key bubbles-mode-map [double-down-mouse-1] 'bubbles-plop) +(define-key bubbles-mode-map [mouse-2] 'bubbles-plop) +(define-key bubbles-mode-map "\C-m" 'bubbles-plop) +(define-key bubbles-mode-map "u" 'bubbles-undo) +(define-key bubbles-mode-map "p" 'previous-line) +(define-key bubbles-mode-map "n" 'next-line) +(define-key bubbles-mode-map "f" 'forward-char) +(define-key bubbles-mode-map "b" 'backward-char) + + +;; game theme menu +(defvar bubbles-game-theme-menu (make-sparse-keymap "Game Theme")) +(define-key bubbles-game-theme-menu [bubbles-set-game-userdefined] + (list 'menu-item "User defined" 'bubbles-set-game-userdefined + :button '(:radio . (eq bubbles-game-theme 'user-defined)))) +(define-key bubbles-game-theme-menu [bubbles-set-game-hard] + (list 'menu-item "Hard" 'bubbles-set-game-hard + :button '(:radio . (eq bubbles-game-theme 'hard)))) +(define-key bubbles-game-theme-menu [bubbles-set-game-difficult] + (list 'menu-item "Difficult" 'bubbles-set-game-difficult + :button '(:radio . (eq bubbles-game-theme 'difficult)))) +(define-key bubbles-game-theme-menu [bubbles-set-game-medium] + (list 'menu-item "Medium" 'bubbles-set-game-medium + :button '(:radio . (eq bubbles-game-theme 'medium)))) +(define-key bubbles-game-theme-menu [bubbles-set-game-easy] + (list 'menu-item "Easy" 'bubbles-set-game-easy + :button '(:radio . (eq bubbles-game-theme 'easy)))) + +;; graphics theme menu +(defvar bubbles-graphics-theme-menu (make-sparse-keymap "Graphics Theme")) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-ascii] + (list 'menu-item "ASCII" 'bubbles-set-graphics-theme-ascii + :button '(:radio . (eq bubbles-graphics-theme 'ascii)))) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-emacs] + (list 'menu-item "Emacs" 'bubbles-set-graphics-theme-emacs + :button '(:radio . (eq bubbles-graphics-theme 'emacs)))) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-balls] + (list 'menu-item "Balls" 'bubbles-set-graphics-theme-balls + :button '(:radio . (eq bubbles-graphics-theme 'balls)))) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-diamonds] + (list 'menu-item "Diamonds" 'bubbles-set-graphics-theme-diamonds + :button '(:radio . (eq bubbles-graphics-theme 'diamonds)))) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-squares] + (list 'menu-item "Squares" 'bubbles-set-graphics-theme-squares + :button '(:radio . (eq bubbles-graphics-theme 'squares)))) +(define-key bubbles-graphics-theme-menu [bubbles-set-graphics-theme-circles] + (list 'menu-item "Circles" 'bubbles-set-graphics-theme-circles + :button '(:radio . (eq bubbles-graphics-theme 'circles)))) + +;; menu +(defvar bubbles-menu (make-sparse-keymap "Bubbles")) +(define-key bubbles-menu [bubbles-quit] + (list 'menu-item "Quit" 'bubbles-quit)) +(define-key bubbles-menu [bubbles] + (list 'menu-item "New game" 'bubbles)) +(define-key bubbles-menu [bubbles-separator-1] + '("--")) +(define-key bubbles-menu [bubbles-save-settings] + (list 'menu-item "Save all settings" 'bubbles-save-settings)) +(define-key bubbles-menu [bubbles-customize] + (list 'menu-item "Edit all settings" 'bubbles-customize)) +(define-key bubbles-menu [bubbles-game-theme-menu] + (list 'menu-item "Game Theme" bubbles-game-theme-menu)) +(define-key bubbles-menu [bubbles-graphics-theme-menu] + (list 'menu-item "Graphics Theme" bubbles-graphics-theme-menu + :enable 'bubbles--playing)) +(define-key bubbles-menu [bubbles-separator-2] + '("--")) +(define-key bubbles-menu [bubbles-undo] + (list 'menu-item "Undo last move" 'bubbles-undo + :enable '(and bubbles--playing bubbles--save-data))) + +;; bind menu to mouse +(define-key bubbles-mode-map [down-mouse-3] bubbles-menu) +;; Put menu in menu-bar +(define-key bubbles-mode-map [menu-bar Bubbles] + (cons "Bubbles" bubbles-menu)) + +(defun bubbles-mode () + "Major mode for playing bubbles. +\\{bubbles-mode-map}" + (kill-all-local-variables) + (use-local-map bubbles-mode-map) + (setq major-mode 'bubbles-mode) + (setq mode-name "Bubbles") + (setq buffer-read-only t) + (buffer-enable-undo) + (add-hook 'post-command-hook 'bubbles--mark-neighbourhood t t) + (run-hooks 'bubbles-mode-hook)) + +;;;###autoload +(defun bubbles () + "Play Bubbles game." + (interactive) + (switch-to-buffer (get-buffer-create "*bubbles*")) + (when (or (not bubbles--playing) + (y-or-n-p "Start new game? ")) + (setq bubbles--save-data nil) + (setq bubbles--playing t) + (bubbles--initialize))) + +(defun bubbles-quit () + "Quit Bubbles." + (interactive) + (message "bubbles-quit") + (bury-buffer)) + +(defun bubbles--compute-offsets () + "Update horizontal and vertical offsets for centering the bubbles grid. +Set `bubbles--col-offset' and `bubbles--row-offset'." + (cond ((and (display-images-p) + bubbles--images-ok + (not (eq bubbles-graphics-theme 'ascii)) + (fboundp 'window-inside-pixel-edges)) + ;; compute offset in units of pixels + (let ((bubbles--image-size + (car (image-size (car bubbles--images) t)))) + (setq bubbles--col-offset + (list + (max 0 (/ (- (nth 2 (window-inside-pixel-edges)) + (nth 0 (window-inside-pixel-edges)) + (* ( + bubbles--image-size 2) ;; margin + (bubbles--grid-width))) 2)))) + (setq bubbles--row-offset + (list + (max 0 (/ (- (nth 3 (window-inside-pixel-edges)) + (nth 1 (window-inside-pixel-edges)) + (* (+ bubbles--image-size 1) ;; margin + (bubbles--grid-height))) 2)))))) + (t + ;; compute offset in units of chars + (setq bubbles--col-offset + (max 0 (/ (- (window-width) + (bubbles--grid-width)) 2))) + (setq bubbles--row-offset + (max 0 (/ (- (window-height) + (bubbles--grid-height) 2) 2)))))) + +(defun bubbles--remove-overlays () + "Remove all overlays." + (if (fboundp 'remove-overlays) + (remove-overlays))) + +(defun bubbles--initialize () + "Initialize Bubbles game." + (bubbles--initialize-faces) + (bubbles--initialize-images) + (bubbles--remove-overlays) + + (switch-to-buffer (get-buffer-create "*bubbles*")) + (bubbles--compute-offsets) + (let ((inhibit-read-only t)) + (set-buffer-modified-p nil) + (erase-buffer) + (insert " ") + (add-text-properties + (point-min) (point) (list 'intangible t 'display + (cons 'space + (list :height bubbles--row-offset)))) + (insert "\n") + (let ((max-char (length (bubbles--colors)))) + (dotimes (i (bubbles--grid-height)) + (let ((p (point))) + (insert " ") + (add-text-properties + p (point) (list 'intangible t + 'display (cons 'space + (list :width + bubbles--col-offset))))) + (dotimes (j (bubbles--grid-width)) + (let* ((index (random max-char)) + (char (nth index bubbles-chars))) + (insert char) + (add-text-properties (1- (point)) (point) (list 'index index)))) + (insert "\n")) + (insert "\n ") + (add-text-properties + (1- (point)) (point) (list 'intangible t 'display + (cons 'space + (list :width bubbles--col-offset))))) + (put-text-property (point-min) (point-max) 'pointer 'arrow)) + (bubbles-mode) + (bubbles--reset-score) + (bubbles--update-faces-or-images) + (bubbles--goto 0 0)) + +(defun bubbles--initialize-faces () + "Prepare faces for playing `bubbles'." + (copy-face 'default 'bubbles--highlight-face) + (set-face-background 'bubbles--highlight-face "#8080f4") + (when (display-color-p) + (setq bubbles--faces + (mapcar (lambda (color) + (let ((fname (intern (format "bubbles--face-%s" color)))) + (unless (facep fname) + (copy-face 'default fname) + (set-face-foreground fname color)) + fname)) + (bubbles--colors))))) + +(defsubst bubbles--row (pos) + "Return row of point POS." + (save-excursion + (goto-char pos) + (beginning-of-line) + (1- (count-lines (point-min) (point))))) + +(defsubst bubbles--col (pos) + "Return column of point POS." + (save-excursion + (goto-char pos) + (1- (current-column)))) + +(defun bubbles--goto (row col) + "Move point to bubble at coordinates ROW and COL." + (if (or (< row 0) + (< col 0) + (>= row (bubbles--grid-height)) + (>= col (bubbles--grid-width))) + ;; Error! return nil + nil + ;; go + (goto-char (point-min)) + (forward-line (1+ row)) + (forward-char (1+ col)) + (point))) + +(defun bubbles--char-at (row col) + "Return character at bubble ROW and COL." + (save-excursion + (if (bubbles--goto row col) + (char-after (point)) + nil))) + +(defun bubbles--mark-direct-neighbours (row col char) + "Mark direct neighbours of bubble at ROW COL with same CHAR." + (save-excursion + (let ((count 0)) + (when (and (bubbles--goto row col) + (eq char (char-after (point))) + (not (get-text-property (point) 'active))) + (add-text-properties (point) (1+ (point)) + '(active t face 'bubbles--highlight-face)) + (setq count (+ 1 + (bubbles--mark-direct-neighbours row (1+ col) char) + (bubbles--mark-direct-neighbours row (1- col) char) + (bubbles--mark-direct-neighbours (1+ row) col char) + (bubbles--mark-direct-neighbours (1- row) col char)))) + count))) + +(defun bubbles--mark-neighbourhood (&optional pos) + "Mark neighbourhood of point. +Use optional parameter POS instead of point if given." + (when bubbles--playing + (unless pos (setq pos (point))) + (condition-case err + (let ((char (char-after pos)) + (inhibit-read-only t) + (row (bubbles--row (point))) + (col (bubbles--col (point)))) + (add-text-properties (point-min) (point-max) + '(face default active nil)) + (let ((count 0)) + (when (and row col (not (eq char (bubbles--empty-char)))) + (setq count (bubbles--mark-direct-neighbours row col char)) + (unless (> count 1) + (add-text-properties (point-min) (point-max) + '(face default active nil)) + (setq count 0))) + (bubbles--update-neighbourhood-score count)) + (put-text-property (point-min) (point-max) 'pointer 'arrow) + (bubbles--update-faces-or-images) + (sit-for 0)) + (error (message "Bubbles: Internal error %s" err))))) + +(defun bubbles--neighbourhood-available () + "Return t if another valid neighbourhood is available." + (catch 'found + (save-excursion + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (let ((c (bubbles--char-at i j))) + (if (and (not (eq c (bubbles--empty-char))) + (or (eq c (bubbles--char-at (1+ i) j)) + (eq c (bubbles--char-at i (1+ j))))) + (throw 'found t))))) + nil))) + +(defun bubbles--count () + "Count remaining bubbles." + (let ((count 0)) + (save-excursion + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (let ((c (bubbles--char-at i j))) + (if (not (eq c (bubbles--empty-char))) + (setq count (1+ count))))))) + count)) + +(defun bubbles--reset-score () + "Reset bubbles score." + (setq bubbles--neighbourhood-score 0 + bubbles--score 0) + (bubbles--update-score)) + +(defun bubbles--update-score () + "Calculate and display new bubble score." + (setq bubbles--score (+ bubbles--score bubbles--neighbourhood-score)) + (bubbles--show-scores)) + +(defun bubbles--update-neighbourhood-score (size) + "Calculate and display score of active neighbourhood from its SIZE." + (if (> size 1) + (setq bubbles--neighbourhood-score (expt (- size 1) 2)) + (setq bubbles--neighbourhood-score 0)) + (bubbles--show-scores)) + +(defun bubbles--show-scores () + "Display current scores." + (save-excursion + (goto-char (or (next-single-property-change (point-min) 'status) + (point-max))) + (let ((inhibit-read-only t) + (pos (point))) + (delete-region (point) (point-max)) + (insert (format "Selected: %4d\n" bubbles--neighbourhood-score)) + (insert " ") + (add-text-properties (1- (point)) (point) + (list 'intangible t 'display + (cons 'space + (list :width bubbles--col-offset)))) + (insert (format "Score: %4d" bubbles--score)) + (put-text-property pos (point) 'status t)))) + +(defun bubbles--game-over () + "Finish bubbles game." + (bubbles--update-faces-or-images) + (setq bubbles--playing nil + bubbles--save-data nil) + ;; add bonus if all bubbles were removed + (when (= 0 (bubbles--count)) + (setq bubbles--score (+ bubbles--score (* (bubbles--grid-height) + (bubbles--grid-width)))) + (bubbles--show-scores)) + ;; Game over message + (goto-char (point-max)) + (let* ((inhibit-read-only t)) + (insert "\n ") + (add-text-properties (1- (point)) (point) + (list 'intangible t 'display + (cons 'space + (list :width bubbles--col-offset)))) + (insert "Game Over!")) + ;; save score + (gamegrid-add-score (format "bubbles-%s-%d-%d-%d-scores" + (symbol-name (bubbles--shift-mode)) + (length (bubbles--colors)) + (bubbles--grid-width) (bubbles--grid-height)) + bubbles--score)) + +(defun bubbles-plop () + "Remove active bubbles region." + (interactive) + (when (and bubbles--playing + (> bubbles--neighbourhood-score 0)) + (setq bubbles--save-data (list bubbles--score (buffer-string))) + (setq buffer-undo-list '(apply bubbles-undo . nil)) + (let ((inhibit-read-only t)) + ;; blank out current neighbourhood + (let ((row (bubbles--row (point))) + (col (bubbles--col (point)))) + (goto-char (point-max)) + (while (not (bobp)) + (backward-char) + (while (get-text-property (point) 'active) + (delete-char 1) + (insert (bubbles--empty-char)) + (add-text-properties (1- (point)) (point) (list 'removed t + 'index -1)))) + (bubbles--goto row col)) + ;; show new score + (bubbles--update-score) + ;; update display and wait + (bubbles--update-faces-or-images) + (sit-for 0) + (sleep-for 0.2) + (discard-input) + ;; drop down + (let ((something-dropped nil)) + (save-excursion + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (bubbles--goto i j) + (while (get-text-property (point) 'removed) + (setq something-dropped (or (bubbles--shift 'top i j) + something-dropped)))))) + ;; update display and wait + (bubbles--update-faces-or-images) + (when something-dropped + (sit-for 0))) + (discard-input) + ;; shift to left + (put-text-property (point-min) (point-max) 'removed nil) + (save-excursion + (goto-char (point-min)) + (let ((removed-string (format "%c" (bubbles--empty-char)))) + (while (search-forward removed-string nil t) + (put-text-property (1- (point)) (point) 'removed t)))) + (let ((shifted nil)) + (cond ((eq (bubbles--shift-mode) 'always) + (save-excursion + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (bubbles--goto i j) + (while (get-text-property (point) 'removed) + (setq shifted (or (bubbles--shift 'right i j) shifted)))))) + (bubbles--update-faces-or-images) + (sleep-for 0.5)) + (t ;; default shift-mode + (save-excursion + (dotimes (j (bubbles--grid-width)) + (bubbles--goto (1- (bubbles--grid-height)) j) + (let ((shifted-cols 0)) + (while (get-text-property (point) 'removed) + (setq shifted-cols (1+ shifted-cols)) + (bubbles--shift 'right (1- (bubbles--grid-height)) j)) + (dotimes (k shifted-cols) + (let ((i (- (bubbles--grid-height) 2))) + (while (>= i 0) + (setq shifted (or (bubbles--shift 'right i j) shifted)) + (setq i (1- i)))))))))) + (when shifted + ;;(sleep-for 0.5) + (bubbles--update-faces-or-images) + (sit-for 0))) + (put-text-property (point-min) (point-max) 'removed nil) + (unless (bubbles--neighbourhood-available) + (bubbles--game-over))))) + +(defun bubbles-undo () + "Undo last move." + (interactive) + (when bubbles--save-data + (let ((inhibit-read-only t) + (pos (point))) + (erase-buffer) + (insert (cadr bubbles--save-data)) + (bubbles--update-faces-or-images) + (setq bubbles--score (car bubbles--save-data)) + (goto-char pos)))) + +(defun bubbles--shift (from row col) + "Move bubbles FROM one side to position ROW COL. +Return t if new char is non-empty." + (save-excursion + (when (bubbles--goto row col) + (let ((char-org (char-after (point))) + (char-new (bubbles--empty-char)) + (removed nil) + (trow row) + (tcol col) + (index -1)) + (cond ((eq from 'top) + (setq trow (1- row))) + ((eq from 'left) + (setq tcol (1- col))) + ((eq from 'right) + (setq tcol (1+ col)))) + (save-excursion + (when (bubbles--goto trow tcol) + (setq char-new (char-after (point))) + (setq removed (get-text-property (point) 'removed)) + (setq index (get-text-property (point) 'index)) + (bubbles--shift from trow tcol))) + (insert char-new) + (delete-char 1) + (add-text-properties (1- (point)) (point) (list 'index index + 'removed removed)) + (not (eq char-new (bubbles--empty-char))))))) + +(defun bubbles--initialize-images () + "Prepare images for playing `bubbles'." + (when (and (display-images-p) + (not (eq bubbles-graphics-theme 'ascii))) + (let ((template (case bubbles-graphics-theme + ('circles bubbles--image-template-circle) + ('balls bubbles--image-template-ball) + ('squares bubbles--image-template-square) + ('diamonds bubbles--image-template-diamond) + ('emacs bubbles--image-template-emacs)))) + (setq bubbles--empty-image + (create-image (replace-regexp-in-string + "^\"\\(.*\\)\t.*c .*\",$" + "\"\\1\tc #FFFFFF\"," template) + 'xpm t + ;;:mask 'heuristic + :margin '(2 . 1))) + (setq bubbles--images + (mapcar (lambda (color) + (let* ((rgb (color-values color)) + (red (nth 0 rgb)) + (green (nth 1 rgb)) + (blue (nth 2 rgb))) + (with-temp-buffer + (insert template) + (goto-char (point-min)) + (re-search-forward + "^\"[0-9]+ [0-9]+ \\(.*?\\) .*\",$" nil t) + (goto-char (point-min)) + (while (re-search-forward + "^\"\\(.*\\)\t.*c \\(#.*\\)\",$" nil t) + (let* ((crgb (color-values (match-string 2))) + (r (nth 0 crgb)) + (g (nth 1 crgb)) + (b (nth 2 crgb)) + (brightness (/ (+ r g b) 3.0 256 256)) + (val (sin (* brightness (/ pi 2)))) + (rr (* red val)) + (gg (* green val)) + (bb (* blue val)) + ;;(rr (/ (+ red r) 2)) + ;;(gg (/ (+ green g) 2)) + ;;(bb (/ (+ blue b) 2)) + (color (format "#%02x%02x%02x" + (/ rr 256) (/ gg 256) + (/ bb 256)))) + (replace-match (format "\"\\1\tc %s\"," + (upcase color))))) + (create-image (buffer-string) 'xpm t + :margin '(2 . 1) + ;;:mask 'heuristic + )))) + (bubbles--colors)))) + ;; check images + (setq bubbles--images-ok bubbles--empty-image) + (mapc (lambda (elt) + (setq bubbles--images-ok (and bubbles--images-ok elt))) + bubbles--images))) + +(defun bubbles--update-faces-or-images () + "Update faces and/or images, depending on graphics mode." + (bubbles--set-faces) + (bubbles--show-images)) + +(defun bubbles--set-faces () + "Update faces in the bubbles buffer." + (unless (and (display-images-p) + bubbles--images-ok + (not (eq bubbles-graphics-theme 'ascii))) + (when (display-color-p) + (save-excursion + (let ((inhibit-read-only t)) + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (bubbles--goto i j) + (let* ((index (get-text-property (point) 'index)) + (face (nth index bubbles--faces)) + (fg-col (face-foreground face))) + (when (get-text-property (point) 'active) + (set-face-foreground 'bubbles--highlight-face "#ff0000") + (setq face 'bubbles--highlight-face)) + (put-text-property (point) (1+ (point)) + 'face face))))))))) + +(defun bubbles--show-images () + "Update images in the bubbles buffer." + (bubbles--remove-overlays) + (if (and (display-images-p) + bubbles--images-ok + (not (eq bubbles-graphics-theme 'ascii))) + (save-excursion + (goto-char (point-min)) + (forward-line 1) + (let ((inhibit-read-only t) + char) + (dotimes (i (bubbles--grid-height)) + (dotimes (j (bubbles--grid-width)) + (forward-char 1) + (let ((index (get-text-property (point) 'index))) + (let ((img bubbles--empty-image)) + (if (>= index 0) + (setq img (nth index bubbles--images))) + (put-text-property (point) (1+ (point)) + 'display (cons img nil))))) + (forward-line 1)))) + (save-excursion + (let ((inhibit-read-only t)) + (goto-char (point-min)) + (while (not (eobp)) + (let ((disp-prop (get-text-property (point) 'display))) + (if (and (listp disp-prop) + (listp (car disp-prop)) + (eq (caar disp-prop) 'image)) + (put-text-property (point) (1+ (point)) 'display nil)) + (forward-char 1))) + (put-text-property (point-min) (point-max) 'pointer 'arrow))))) + +(provide 'bubbles) + +;; arch-tag: 2cd7237a-b0ad-400d-a7fd-75f676dceb70 +;;; bubbles.el ends here diff -r a30538bafc32 -r c3228e91eb9e lisp/play/gamegrid.el --- a/lisp/play/gamegrid.el Wed Aug 29 02:29:12 2007 +0000 +++ b/lisp/play/gamegrid.el Wed Aug 29 02:29:24 2007 +0000 @@ -386,6 +386,7 @@ (defun gamegrid-init (options) (setq buffer-read-only t truncate-lines t + line-spacing 0 gamegrid-display-options options) (buffer-disable-undo (current-buffer)) (gamegrid-initialize-display)) diff -r a30538bafc32 -r c3228e91eb9e lisp/progmodes/cc-langs.el --- a/lisp/progmodes/cc-langs.el Wed Aug 29 02:29:12 2007 +0000 +++ b/lisp/progmodes/cc-langs.el Wed Aug 29 02:29:24 2007 +0000 @@ -2075,6 +2075,7 @@ "false" "true") ; Defined in C99. objc '("nil" "Nil") idl '("TRUE" "FALSE") + java '("true" "false" "null") ; technically "literals", not keywords pike '("UNDEFINED")) ;; Not a keyword, but practically works as one. (c-lang-defconst c-primary-expr-kwds diff -r a30538bafc32 -r c3228e91eb9e lisp/progmodes/modula2.el --- a/lisp/progmodes/modula2.el Wed Aug 29 02:29:12 2007 +0000 +++ b/lisp/progmodes/modula2.el Wed Aug 29 02:29:24 2007 +0000 @@ -295,7 +295,7 @@ (insert "DEFINITION MODULE ") (let ((name (read-string "Name: "))) (insert name ";\n\n\n\nEND " name ".\n")) - (previous-line 3)) + (forward-line -3)) (defun m2-else () "Insert ELSE keyword and indent for next line." @@ -364,7 +364,7 @@ (insert "IMPLEMENTATION MODULE ") (let ((name (read-string "Name: "))) (insert name ";\n\n\n\nEND " name ".\n") - (previous-line 3) + (forward-line -3) (m2-header) (m2-type) (newline)