function [varargout] = kpfun(h,arg);

% The function KPFUN adds keypress functionality to a figure.  Its basic
% usage is:
%
% KPFUN(h,arg)
%
% h is the figure handle of interest, and arg is an optional argument.  h
% can be a vector of figure handles.  When arg is not provided,
% functionality is toggled for each figure specified.  If no figure is
% specified, the current figure is affected.  If h contains 0, all figures 
% are selected.  The optional argument can take on the following values:
%
%     '?' - function provides feedback specifying whether functionality is
%           in place for that figure (displayed if no output is requested,
%           or returned as a vector otherwise).  1 means enabled, 0 means
%           not.
%     's' - for 'set', forces all figures to have functionality enabled
%     'r' - for 'remove', removes functionality
%     't' - for 'toggle', toggles functionality (this is the default)
%
% Once functionality has been enabled, the following keypresses will be
% available for the figure (listed in no particular order):
%
% 'g' - Toggle the grid
% 'n' - Release axis constraints (i.e. axis normal)
% 'N' - Set axes to show extents of the plot (i.e. auto-scaling)
% 'v' - Add a vertical colorbar
% 'V' - Remove a vertical colorbar
% 'h' - Add a horizontal colorbar
% 'H' - Remove a horizontal colorbar
% 'c' - Reset the color scale for the current viewing area
% 'C' - Reset the color scale for the full image
% 'u' - Pan up by 20% of the viewing area
% 'U' - Pan up by 4% of the viewing area
% 'd', 'D', 'l', 'L', 'r', 'R' - Same for down, left, right
% ';' - Zoom in by ~20%
% ':' - Zoom out by ~120%
% '[' - Zoom in the x-axis by ~20%
% '{' - Zooom out in the x-axis by ~120%
% ']' - Zoom in the y-axis by ~20%
% '}' - Zooom out in the y-axis by ~120%
% 'S' - Send/steal figure data into the base workspace For each graphic
%       object a structure is created with fields x, y, and data containing
%       the x-axis, the y-axis, and the color data, respectively.  Multiple
%       objects result in a structure array.
% 's' - Saves the figure (pretty much like hitting the little disk icon)
% 'p' - Export figure to a .png file
% 'P' - Send figure to the printer
% 'j' - Export figure to a .jpg file
% 'm' - Send figure to the clipboard as an enhanced metafile
% 'M' - send figure to the clipboard as a bitmap
% 'f' - Increase all font sizes by 1 point
% 'F' - Decrease all font sizes by 1 point
% 'w' - Increase all line widths by 0.5 points
% 'W' - Decrease all line widths by 0.5 points
% 'O' - Remove a legend
% 'Q' - Close the figure
% 'q' - Disabled keypress functionality
% 'k' - Prompt for axis labels
% 'K' - Remove axis labels
% 't' - Prompt for plot title
% 'T' - Remove plot title
% 'x' - Reverse the x-axis
% 'X' - Toggle between linear and log scales for the x-axis
% 'y' - Reverse the y-axis
% 'Y' - Toggle between linear and log scales for the y-axis
% 'z' - Reverse the z-axis
% 'Z' - Toggle between linear and log scales for the z-axis
% 'i' - Invert the colormap
% 'a' - Turn off the axes
% 'A' - Turn on the axes
% '=' - Select the next object in the axes
% '+' - Select the previous object in the axes
% 'backspace' - Deselect all objects in the axes
% 'delete' - Delete selected objects
% '1' - Increase red contribution (by 0.1) to the color of the
%       selected line/text or to the top of the color scale if
%       if nothing is selected
% '2' - Same for green
% '3' - Same for blue
% '4' - Increase red contribution (by 0.1) to the color at the
%       bottom of the color scale
% '5' - Same for green
% '6' - Same for blue
% '!@#$%^' - Same as 1-6 above, but with decreases
% '\' - Cycle colormap forward by one step
% '|' - Cycle colormap backward by one step
% '-' - Downsample colormap by a factor of ~2
% '_' - Upsample colormap by a factor of ~2
% ',' - Set colormap to jet with 64 color resolution
% '<' - Cycle colormap through: GRAY, HOT, COOL, BONE, COPPER, PINK, FLAG,
%       PRISM, SPRING, SUMMER, AUTUMN, WINTER, and JET (maintains current 
%       resolution)
% '.' - Grab a single coordinate point and return it in the base workspace
%       as a row vector called figurepoint (cancel by hitting return)
% '>' - Same as '/', but collects two points (each row is a coordinate
%       point)
% arrows - Move the current axes up, down, left, or right
% ''' - Enlarge the current axes
% '"' - Shrink the current axes
% '7' - Enlarge the current axes horizontally
% '8' - Enlarge the current axes vertically
% '&*' - Shrink the current axes horizontally/vertically
% '9' - Introduce a new set of axes
% '(' - Delete the current set of axes
% 'b' - Increase marker size on lines
% 'B' - Decrease marker size on lines
% 'I' - Cycle through line styles
% 'J' - Cycle through marker styles
% '/' - Display the function for the next keypress
% '?' - Bring up a window with this KPFUN help file
% 'e' - Translate image or line to decibels (10*log10(data))
% 'E' - Translate image or line out of decibels (10^(data/10))
% '`' - Produce a new figure for an image that is a horizontal (left click)
%       or vertical (right click) slice through the image
% '`' - Produce a new figure for an image that is a horizontal (left click)
%       or vertical (right click) slice through the image, without
%       interpolation (i.e. takes the nearest row or column)
%
% Written by J.A. Dunne, 8-3-05
% Last Edited 10-04-06


if nargin<1, h = gcf; end

if ischar(h)
    arg = lower(h(1));
    h = gcf;
else
    if nargin<2
        arg = 't';
    else
        arg = lower(arg(1));
    end
end

if ~iscell(h)
    if ~all(h)
        h = findobj('type','figure');
    end
    for i=1:length(h)
        if arg=='t'
            if length(get(h(i),'KeyPressFcn'))
                stg='';
            else
                stg='kpfun({1})';
            end
        else
            if arg == '?'
                stg = get(h(i),'KeyPressFcn');
                out(i) = strcmp(stg,'kpfun({1})');
            else
                if arg=='r'
                    stg='';
                else
                    stg='kpfun({1})';
                end
            end
        end
        set(h(i),'KeyPressFcn',stg);
    end
    if arg=='?'
        if nargout>0
            varargout{1} = out;
        else
            for i=1:length(h)
                st = {'Disabled' 'Enabled'};
                disp(['Figure ' num2str(h(i)) ': ' st{out(i)+1}]);
            end
        end
    end
else
    persistent DisplayHelp
    if length(DisplayHelp)>0
        if length(get(gcf,'CurrentCharacter'))
            clear DisplayHelp
            defs = {
'g' 1.5 'Toggle the grid on/off'
'n' 1.5 'Release axis constraints (i.e. axis normal)'
'N' 2.3 'Reset all axes to automatic scaling'
'v' 1.5 'Add a vertical colorbar'
'V' 1.5 'Remove a vertical colorbar'
'h' 1.5 'Add a horizontal colorbar'
'H' 1.5 'Remove a horizontal colorbar'
'c' 2 'Reset the color scale for the current viewing area'
'C' 1.5 'Reset the color scale for the full image'
'u' 2 'Pan up by 20% of the viewing area'
'U' 2 'Pan up by 4% of the viewing area'
'd' 2 'Pan down by 20% of the viewing area'
'D' 2 'Pan down by 4% of the viewing area'
'l' 2 'Pan left by 20% of the viewing area'
'L' 2 'Pan left by 4% of the viewing area'
'r' 2 'Pan right by 20% of the viewing area'
'R' 2 'Pan right by 4% of the viewing area'
';' 1.5 'Zoom in by ~20%'
':' 1.5 'Zoom out by ~120%'
'[' 2 'Zoom in the x-axis by ~20%'
'{' 2 'Zooom out in the x-axis by ~120%'
']' 2 'Zoom in the y-axis by ~20%'
'}' 2 'Zooom out in the y-axis by ~120%'
'S' 6 {'Send/steal figure data into the base workspace For each graphic';'object a structure is created with fields x, y, and data containing';'the x-axis, the y-axis, and the color data, respectively.  Multiple';'objects result in a structure array.'}
's' 3 'Saves the figure (pretty much like hitting the little disk icon)'
'p' 2 'Export figure to a .png file'
'P' 2 'Send figure to the printer'
'j' 2 'Export figure to a .jpg file'
'm' 2.3 'Send figure to the clipboard as an enhanced metafile'
'M' 2.3 'send figure to the clipboard as a bitmap'
'f' 2 'Increase all font sizes by 1 point'
'F' 2 'Decrease all font sizes by 1 point'
'w' 2 'Increase all line widths by 0.5 points'
'W' 2 'Decrease all line widths by 0.5 points'
'O' 2 'Remove a legend'
'Q' 2 'Close the figure'
'q' 2 'Disabled keypress functionality'
'k' 2 'Prompt for axis labels'
'K' 2 'Remove axis labels'
't' 2 'Prompt for plot title'
'T' 2 'Remove plot title'
'x' 2 'Reverse the x-axis'
'X' 2.5 'Toggle between linear and log scales for the x-axis'
'y' 2 'Reverse the y-axis'
'Y' 2.5 'Toggle between linear and log scales for the y-axis'
'z' 2 'Reverse the z-axis'
'Z' 2.5 'Toggle between linear and log scales for the z-axis'
'i' 2 'Invert the colormap'
'a' 2 'Turn off the axes'
'A' 2 'Turn on the axes'
'=' 2 'Select the next object in the axes'
'+' 2 'Select the previous object in the axes'
'\' 2 'Cycle colormap forward by one step'
'|' 2 'Cycle colormap backward by one step'
'-' 2 'Downsample colormap by a factor of ~2'
'_' 2 'Upsample colormap by a factor of ~2'
',' 2 'Set colormap to jet with 64 color resolution'
'<' 5 {'Cycle colormap through: GRAY, HOT, COOL, BONE, COPPER,';'PINK, FLAG, PRISM, SPRING, SUMMER, AUTUMN, WINTER,';'and JET (maintains current resolution)'}
'.' 5 {'Grab a single coordinate point and return it in the base workspace';'as a row vector called figurepoint (cancel by hitting return)'}
'>' 5 {'Grab a two coordinate points and return them in the base workspace';'as a matrix called figurepoint (cancel by hitting return)'}
'''' 2 'Enlarge the current axes'
'"' 2 'Shrink the current axes'
'7' 2 'Enlarge the current axes horizontally'
'8' 2 'Enlarge the current axes vertically'
'&' 2 'Shrink the current axes horizontally'
'*' 2 'Shrink the current axes vertically'
'9' 2 'Introduce a new set of axes'
'(' 2 'Delete the current set of axes'
'b' 2 'Increase marker size on lines'
'B' 2 'Decrease marker size on lines'
'I' 2 'Cycle through line styles'
'J' 2 'Cycle through marker styles'
'?' 2.5 'Open a help window for KPFUN'
'/' 2.5 'Display the function for the next keypress'
'e' 2.5 'Translate image or line to decibels (10*log10(data))'
'E' 2.5 'Translate image or line out of decibels (10^d^a^t^a^/^1^0)'
'`' 3.5 {'Generate new figure with vertical (right click)' 'or horizontal (left click) slice of an image'}
'~' 3.5 {'Generate new figure with vertical (right click)' 'or horizontal (left click) slice of an image, without interpolation'}
char(28) 2 'Move current axes left'
char(29) 2 'Move current axes right'
char(30) 2 'Move current axes up'
char(31) 2 'Move current axes down'
char(8) 2 'Deselect all objects in the axes'
char(127) 2 'Delete selected objects'
'1' 6 {'Increase red contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'2' 6 {'Increase green contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'3' 6 {'Increase blue contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'!' 6 {'Decrease red contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'@' 6 {'Decrease green contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'#' 6 {'Decrease blue contribution (by 0.1) to the color of the';'selected line/text or to the top of the color scale';'if nothing is selected'}
'4' 4 {'Increase red contribution (by 0.1) to the color of the';'at the bottom of the color scale'}
'5' 4 {'Increase green contribution (by 0.1) to the color of the';'at the bottom of the color scale'}
'6' 4 {'Increase blue contribution (by 0.1) to the color of the';'at the bottom of the color scale'}
'$' 4 {'Decrease red contribution (by 0.1) to the color of the';'at the bottom of the color scale'}
'%' 4 {'Decrease green contribution (by 0.1) to the color of the';'at the bottom of the color scale'}
'6' 4 {'Decrease blue contribution (by 0.1) to the color of the';'at the bottom of the color scale'}};
            for i=1:size(defs,1)
                if strcmp(get(gcf,'CurrentCharacter'),defs{i,1})
                    t = timer;
                    set(t,'Period',1,'StartDelay',0,'ExecutionMode','singleShot');
                    set(t,'TimerFcn',{@flashmessage,defs{i,3},defs{i,2}});
                    start(t);
                    break
                end
            end
            return
        end
    end
    hf = gcf;
    switch get(gcf,'CurrentCharacter');
        case 'g'
            grid;
        case 'v'
            colorbar('vert');
        case 'V'
            delete(colorbar('vert'));
        case 'h'
            colorbar('horiz');
        case 'H'
            delete(colorbar('horiz'));
        case 'u'
            lims = axis(gca);
            dy = lims(4)-lims(3);
            lims([3 4]) = lims([3 4]) + .2*dy;
            axis(lims);
        case 'U'
            lims = axis(gca);
            dy = lims(4)-lims(3);
            lims([3 4]) = lims([3 4]) + .04*dy;
            axis(lims);
        case 'd'
            lims = axis(gca);
            dy = lims(4)-lims(3);
            lims([3 4]) = lims([3 4]) - .2*dy;
            axis(lims);
        case 'D'
            lims = axis(gca);
            dy = lims(4)-lims(3);
            lims([3 4]) = lims([3 4]) - .04*dy;
            axis(lims);
        case 'l'
            lims = axis(gca);
            dx = lims(2)-lims(1);
            lims([1 2]) = lims([1 2]) - .2*dx;
            axis(lims);
        case 'L'
            lims = axis(gca);
            dx = lims(2)-lims(1);
            lims([1 2]) = lims([1 2]) - .04*dx;
            axis(lims);
        case 'r'
            lims = axis(gca);
            dx = lims(2)-lims(1);
            lims([1 2]) = lims([1 2]) + .2*dx;
            axis(lims);
        case 'R'
            lims = axis(gca);
            dx = lims(2)-lims(1);
            lims([1 2]) = lims([1 2]) + .04*dx;
            axis(lims);
        case ';'
            lims = axis(gca);
            dx = (lims(2)-lims(1))/10;
            dy = (lims(4)-lims(3))/10;
            axis([lims(1)+dx lims(2)-dx lims(3)+dy lims(4)-dy]);
        case ':'
            lims = axis(gca);
            dx = (lims(2)-lims(1))/8;
            dy = (lims(4)-lims(3))/8;
            axis([lims(1)-dx lims(2)+dx lims(3)-dy lims(4)+dy]);
        case '['
            lims = axis(gca);
            dx = (lims(2)-lims(1))/10;
            axis([lims(1)+dx lims(2)-dx lims(3) lims(4)]);
        case '{'
            lims = axis(gca);
            dx = (lims(2)-lims(1))/8;
            axis([lims(1)-dx lims(2)+dx lims(3) lims(4)]);
        case ']'
            lims = axis(gca);
            dy = (lims(4)-lims(3))/10;
            axis([lims(1) lims(2) lims(3)+dy lims(4)-dy]);
        case '}'
            lims = axis(gca);
            dy = (lims(4)-lims(3))/8;
            axis([lims(1) lims(2) lims(3)-dy lims(4)+dy]);
        case 'c'
            lims = axis(gca);
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'type'),'image')
                        % Found an image
                        cdata = get(hkids(i),'cdata');
                        xdata = get(hkids(i),'xdata');
                        if xdata(end)<xdata(1), xdata = flipud(xdata(:)); end
                        if length(xdata)~=size(cdata,2)
                            xdata = [xdata(1):xdata(2)];
                        end
                        ydata = get(hkids(i),'ydata');
                        if ydata(end)<ydata(1), ydata = flipud(ydata(:)); end
                        if length(ydata)~=size(cdata,1)
                            ydata = [ydata(1):ydata(2)];
                        end
                        xlims = interp1(xdata,1:size(cdata,2),lims([1 2]),'nearest','extrap');
                        ylims = interp1(ydata,1:size(cdata,1),lims([3 4]),'nearest','extrap');
                        newmat = cdata([ylims(1):ylims(2)],[xlims(1):xlims(2)]);
                        mn = min(min(newmat));
                        mx = max(max(newmat));
                        caxis([mn mx]);
                    break
                end
            end
        case 'C'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'type'),'image')
                        % Found an image
                        cdata = get(hkids(i),'cdata');
                        mn = min(min(cdata));
                        mx = max(max(cdata));
                        caxis([mn mx]);
                    break
                end
            end
        case 'S'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if ~strcmp(get(hkids(i),'type'),'text')
                    obj(i).x = get(hkids(i),'xdata');
                    obj(i).y = get(hkids(i),'ydata');
                    obj(i).data = [];
                    if strcmp(get(hkids(i),'type'),'image')
                        obj(i).data = get(hkids(i),'cdata');
                    end
                else
                    p = get(hkids(i),'position');
                    obj(i).x = p(1);
                    obj(i).y = p(2);
                    obj(i).data = get(hkids(i),'string');
                end
            end
            assignin('base','figuredata',obj);
            disp('Data taken from figure and stored in variable ''figuredata''.')
        case 'O'
            delete(legend);
        case 'Q'
            close(hf);
        case 'q'
            set(hf,'KeyPressFcn','');
        case 'K'
            delete(xlabel(''));
            delete(ylabel(''));
            delete(zlabel(''));
        case 'T'
            delete(title(''));
        case 'a'
            axis off
        case 'A'
            axis on
        case 'x'
            val = get(gca,'xdir');
            if strcmp(lower(val),'normal')
                set(gca,'xdir','reverse');
            else
                set(gca,'xdir','normal');
            end
        case 'y'
            val = get(gca,'ydir');
            if strcmp(lower(val),'normal')
                set(gca,'ydir','reverse');
            else
                set(gca,'ydir','normal');
            end
        case 'z'
            val = get(gca,'zdir');
            if strcmp(lower(val),'normal')
                set(gca,'zdir','reverse');
            else
                set(gca,'zdir','normal');
            end
        case 'X'
            val = get(gca,'xscale');
            if strcmp(lower(val),'linear')
                set(gca,'xscale','log');
            else
                set(gca,'xscale','linear');
            end
        case 'Y'
            val = get(gca,'yscale');
            if strcmp(lower(val),'linear')
                set(gca,'yscale','log');
            else
                set(gca,'yscale','linear');
            end
        case 'Z'
            val = get(gca,'zscale');
            if strcmp(lower(val),'linear')
                set(gca,'zscale','log');
            else
                set(gca,'zscale','linear');
            end
        case 'i'
            colormap(flipud(colormap));
        case 'm'
            print -dmeta;
        case 'M'
            print -dbitmap;
        case 'P'
            printdlg(hf);
        case 's'
            [fname, path] = uiputfile({'*.fig' 'MATLAB Figure Files'}, 'Enter file name');
            if ischar(fname)
                [pathstr,name,ext,versn] = fileparts([path fname]);
                fn = [pathstr filesep name '.fig'];
                saveas(hf,fn);
            end
        case 'p'
            [fname, path] = uiputfile({'*.png' 'Portable Network Graphic Files'}, 'Enter file name');
            if ischar(fname)
                [pathstr,name,ext,versn] = fileparts([path fname]);
                fn = [pathstr filesep name '.png'];
                print(hf,'-dpng',fn);
            end
        case 'j'
            [fname, path] = uiputfile({'*.jpg' 'JPEG Files'}, 'Enter file name');
            if ischar(fname)
                [pathstr,name,ext,versn] = fileparts([path fname]);
                fn = [pathstr filesep name '.jpg'];
                print(hf,'-djpeg',fn);
            end
        case 'w'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(lower(get(hkids(i),'type')),'line')
                    set(hkids(i),'linewidth',get(hkids(i),'linewidth')+0.5);
                end
            end
        case 'W'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(lower(get(hkids(i),'type')),'line')
                    if get(hkids(i),'linewidth')>0.5
                        set(hkids(i),'linewidth',get(hkids(i),'linewidth')-0.5);
                    end
                end
            end
        case 'f'
            set(gca,'fontsize',get(gca,'fontsize')+1);
            set(get(gca,'xlabel'),'fontsize',get(get(gca,'xlabel'),'fontsize')+1);
            set(get(gca,'ylabel'),'fontsize',get(get(gca,'ylabel'),'fontsize')+1);
            set(get(gca,'zlabel'),'fontsize',get(get(gca,'zlabel'),'fontsize')+1);
            set(get(gca,'title'),'fontsize',get(get(gca,'title'),'fontsize')+1);
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(lower(get(hkids(i),'type')),'text')
                    set(hkids(i),'fontsize',get(hkids(i),'fontsize')+1);
                end
            end
        case 'F'
            x=get(gca,'fontsize');
            if x>1, set(gca,'fontsize',x-1); end
            x=get(get(gca,'xlabel'),'fontsize');
            if x>1, set(get(gca,'xlabel'),'fontsize',x-1); end
            x=get(get(gca,'ylabel'),'fontsize');
            if x>1, set(get(gca,'ylabel'),'fontsize',x-1); end
            x=get(get(gca,'zlabel'),'fontsize');
            if x>1, set(get(gca,'zlabel'),'fontsize',x-1); end
            x=get(get(gca,'title'),'fontsize');
            if x>1, set(get(gca,'title'),'fontsize',x-1); end
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(lower(get(hkids(i),'type')),'text')
                    x = get(hkids(i),'fontsize');
                    if x>1, set(hkids(i),'fontsize',x-1); end
                end
            end
        case 'n'
            axis normal;
        case '1'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',min([1 1 1],get(hkids(i),'color')+[0.1 0 0]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = min([1 1 1],cm(end,:)+[0.1 0 0]);
                colormap(cm);
            end
        case '2'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',min([1 1 1],get(hkids(i),'color')+[0 0.1 0]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = min([1 1 1],cm(end,:)+[0 0.1 0]);
                colormap(cm);
            end
        case '3'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',min([1 1 1],get(hkids(i),'color')+[0 0 0.1]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = min([1 1 1],cm(end,:)+[0 0 0.1]);
                colormap(cm);
            end
        case '!'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',max([0 0 0],get(hkids(i),'color')-[0.1 0 0]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = max([0 0 0],cm(end,:)-[0.1 0 0]);
                colormap(cm);
            end
        case '@'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',max([0 0 0],get(hkids(i),'color')-[0 0.1 0]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = max([0 0 0],cm(end,:)-[0 0.1 0]);
                colormap(cm);
            end
        case '#'
            hkids = get(gca,'children');
            nonefound = 1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    nonefound = 0;
                    switch get(hkids(i),'type')
                        case {'line','text'}
                            set(hkids(i),'color',max([0 0 0],get(hkids(i),'color')-[0 0 0.1]));
                    end
                end
            end
            if nonefound
                cm = colormap;
                cm(end,:) = max([0 0 0],cm(end,:)-[0 0 0.1]);
                colormap(cm);
            end
       case '4'
            cm = colormap;
            cm(1,:) = min([1 1 1],cm(1,:)+[0.1 0 0]);
            colormap(cm);
       case '5'
            cm = colormap;
            cm(1,:) = min([1 1 1],cm(1,:)+[0 0.1 0]);
            colormap(cm);
       case '6'
            cm = colormap;
            cm(1,:) = min([1 1 1],cm(1,:)+[0 0 0.1]);
            colormap(cm);
       case '$'
            cm = colormap;
            cm(1,:) = max([0 0 0],cm(1,:)-[0.1 0 0]);
            colormap(cm);
       case '%'
            cm = colormap;
            cm(1,:) = max([0 0 0],cm(1,:)-[0 0.1 0]);
            colormap(cm);
       case '^'
            cm = colormap;
            cm(1,:) = max([0 0 0],cm(1,:)-[0 0 0.1]);
            colormap(cm);
       case '\'
            cm = colormap;
            if size(cm,1)>1
                colormap(cm([2:end 1],:));
            end
        case '|'
            cm = colormap;
            if size(cm,1)>1
                colormap(cm([end 1:end-1],:));
            end
        case '-'
            cm = colormap;
            colormap(cm(1:2:end,:));
        case '_'
            cm = colormap;
            colormap(interp2(1:3,1:size(cm,1),cm,1:3,[1:0.5:size(cm,1)]'));
        case ','
            colormap(jet(64));
        case '<'
            cm = colormap;
            maps = {'gray' 'hot' 'cool' 'bone' 'copper' 'pink' 'flag' 'prism' 'spring' 'summer' 'autumn' 'winter' 'jet'};
            newmap = 'gray';
            for i=1:length(maps)-1
                if isequal(cm,eval([maps{i} '(' num2str(size(cm,1)) ')']))
                    newmap = maps{i+1};
                    break;
                end
            end
            colormap(eval([newmap '(' num2str(size(cm,1)) ')']));
            t = timer;
            set(t,'TimerFcn',{@flashmessage,newmap,1});
            set(t,'Period',1,'StartDelay',0,'ExecutionMode','singleShot');
            start(t);
        case '='
            hkids = get(gca,'children');
            hsel = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    hsel = i;
                end
            end
            if hsel==length(hkids)
                hsel = 0;
            end
            hsel = hsel + 1;
            opts = {'off' 'on'};
            for i=1:length(hkids)
                set(hkids(i),'selected',opts{(hsel==i)+1});
            end
        case char(127) 
            hkids = get(gca,'children');
            hsel = [];
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    hsel = [hsel hkids(i)];
                end
            end
            if length(hsel)>0, delete(hsel); end
        case '+'
            hkids = get(gca,'children');
            hsel = length(hkids)+1;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    hsel = i;
                end
            end
            if hsel==1
                hsel = length(hkids)+1;
            end
            hsel = hsel - 1;
            opts = {'off' 'on'};
            for i=1:length(hkids)
                set(hkids(i),'selected',opts{(hsel==i)+1});
            end
        case char(8)
            hkids = get(gca,'children');
            for i=1:length(hkids)
                set(hkids(i),'selected','off');
            end
        case '.'
            [x,y] = ginput(1);
            if length(x)>0
                assignin('base','figurepoint',[x y]);
                disp(['Point from figure (' num2str(x) ',' num2str(y) ') stored in variable ''figurepoint''.'])
            end
        case '>'
            [x,y] = ginput(2);
            if length(x)>1
                assignin('base','figurepoint',[x(:) y(:)]);
                disp(['Points from figure stored in variable ''figurepoint''.'])
            end
        case char(30)
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1) pos(2)+0.002 pos(3) pos(4)]);
            set(gca,'units',origunits);
        case char(31)
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1) pos(2)-0.002 pos(3) pos(4)]);
            set(gca,'units',origunits);
        case char(28)
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)-0.002 pos(2) pos(3) pos(4)]);
            set(gca,'units',origunits);
        case char(29)
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)+0.002 pos(2) pos(3) pos(4)]);
            set(gca,'units',origunits);
        case ''''
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)-0.001 pos(2)-0.001 pos(3)+0.002 pos(4)+0.002]);
            set(gca,'units',origunits);
        case '"'
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)+0.001 pos(2)+0.001 max([pos(3)-0.002 0.002]) max([pos(4)-0.002 0.002])]);
            set(gca,'units',origunits);
        case '7'
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)-0.001 pos(2) pos(3)+0.002 pos(4)]);
            set(gca,'units',origunits);
        case '8'
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1) pos(2)-0.001 pos(3) pos(4)+0.002]);
            set(gca,'units',origunits);
        case '&'
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1)+0.001 pos(2) max([pos(3)-0.002 0.002]) pos(4)]);
            set(gca,'units',origunits);
        case '*'
            origunits = get(gca,'units');
            set(gca,'units','normalized');
            pos = get(gca,'position');
            set(gca,'position',[pos(1) pos(2)+0.001 pos(3) max([pos(4)-0.002 0.002])]);
            set(gca,'units',origunits);
        case '9'
            axes;
        case '('
            delete(gca);
        case 't'
            AddOpts.Resize='on';
            AddOpts.WindowStyle='normal';
            AddOpts.Interpreter='tex';
            answer=inputdlg({'Plot Title'},'Enter Title',1,{get(get(gca,'title'),'string')},AddOpts);
            if length(answer)>0
                title(answer{1});
            end            
        case 'k'
            AddOpts.Resize='on';
            AddOpts.WindowStyle='normal';
            AddOpts.Interpreter='tex';
            answer=inputdlg({'X-axis label' 'Y-axis label' 'Z-axis label'},'Enter Axis Labels',1,...
                {get(get(gca,'xlabel'),'string') get(get(gca,'ylabel'),'string') get(get(gca,'zlabel'),'string')},AddOpts);
            if length(answer)>0
                xlabel(answer{1});
                if length(answer)>1
                    ylabel(answer{2});
                    if length(answer)>2
                        zlabel(answer{3});
                    end
                end
            end
        case 'e'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'type'),'image')
                    % Found an image
                    warning off
                    set(hkids(i),'cdata',10*log10(abs(get(hkids(i),'cdata'))));
                end
                if strcmp(get(hkids(i),'type'),'line')
                    % Found an image
                    warning off
                    set(hkids(i),'ydata',10*log10(abs(get(hkids(i),'ydata'))));
                end                
            end
        case 'E'
            hkids = get(gca,'children');
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'type'),'image')
                    % Found an image
                    set(hkids(i),'cdata',10.^(get(hkids(i),'cdata')/10));
                end
                if strcmp(get(hkids(i),'type'),'line')
                    % Found an image
                    set(hkids(i),'ydata',10.^(get(hkids(i),'ydata')/10));
                end                
            end
        case 'b'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                found = 1;
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'line')
                    set(hkids(i),'markersize',get(hkids(i),'MarkerSize')+1);
                end
            end
        case 'B'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                found = 1;
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'line')
                    set(hkids(i),'markersize',max([1 get(hkids(i),'MarkerSize')-1]));
                end
            end
        case 'I'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                found = 1;
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'line')
                    styles = {'-' '--' ':' '-.' 'none'};
                    newstyle = '-';
                    for i=1:length(styles)-1
                        if strcmp(get(hkids(found),'linestyle'),styles{i})
                            newstyle = styles{i+1};
                            break;
                        end
                    end
                    set(hkids(found),'linestyle',newstyle);
                end
            end
        case 'J'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                found = 1;
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'line')
                    styles = {'+' 'o' '*' '.' 'x' 'square' 'diamond' '^' 'v' '>' '<' 'pentagram' 'hexagram' 'none'};
                    newstyle = '+';
                    for i=1:length(styles)-1
                        if strcmp(get(hkids(found),'marker'),styles{i})
                            newstyle = styles{i+1};
                            break;
                        end
                    end
                    set(hkids(found),'marker',newstyle);
                end
            end
        case '/'
            DisplayHelp = 1;
            t = timer;
            set(t,'Period',1,'StartDelay',0,'ExecutionMode','singleShot');
            set(t,'TimerFcn',{@flashmessage,'Press a key for help',.7});
            start(t);
        case '?'
            % Open up a window and put this help file in it.
            h = figure('numbertitle','off',...
                'units','normalized',...
                'position',[.25 .2 .5 .6],...
                'Name','KPFUN Help');
            a = help('kpfun');
            b = {''};
            for i=1:length(a)
                if double(a(i))==10
                    b{end+1} = '';
                else
                    b{end} = [b{end} a(i)];
                end
            end
            uicontrol(h,'style','listbox',...
                'units','normalized',...
                'position',[.07 .1 .86 .85],...
                'string',b,...
                'max',2,...
                'min',1);
            
            uicontrol(h,'style','pushbutton',...
                'units','normalized',...
                'position',[.45 .02 .1 .06],...
                'string','close',...
                'callback','close(gcf)');
        case 'N'
            set(gca,'XLimMode','auto')
            set(gca,'YLimMode','auto')
            set(gca,'ZLimMode','auto')
        case '`'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                for i=1:length(hkids)
                    if strcmp(get(hkids(i),'type'),'image')
                        found = i;
                        break
                    end
                end
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'image')
                    [x,y,b] = ginput(1);
                    if ~(b==1 | b==3)
                        return
                    end
                    xdat = get(hkids(found),'xdata');
                    ydat = get(hkids(found),'ydata');
                    zdat = get(hkids(i),'cdata');
                    if x>max(xdat), x = max(xdat); end
                    if x<min(xdat), x = min(xdat); end
                    if y>max(ydat), y = max(ydat); end
                    if y<min(ydat), y = min(ydat); end
                    if length(xdat)~=size(zdat,2)
                        x = interp1(xdat,(0:(length(xdat)-1))/(length(xdat)-1),x);
                        xdat2 = (0:size(zdat,2)-1)/(size(zdat,2)-1);
                        x = interp1((0:(length(xdat)-1))/(length(xdat)-1),get(hkids(found),'xdata'),x);
                        xdat = interp1((0:(length(xdat)-1))/(length(xdat)-1),get(hkids(found),'xdata'),xdat2);
                    end
                    if length(ydat)~=size(zdat,1)
                        y = interp1(ydat,(0:(length(ydat)-1))/(length(ydat)-1),y);
                        ydat2 = (0:size(zdat,1)-1)/(size(zdat,1)-1);
                        y = interp1((0:(length(ydat)-1))/(length(ydat)-1),get(hkids(found),'ydata'),y);
                        ydat = interp1((0:(length(ydat)-1))/(length(ydat)-1),get(hkids(found),'ydata'),ydat2);
                    end
                    t = get(get(gca,'title'),'String');
                    if b==1
                        ax1 = xdat;
                        ax2 = interp2(xdat,ydat,zdat,xdat,y+0*xdat);
                        leg = ['Horizontal slice at y = ' num2str(y)];
                        xlab = get(get(gca,'xlabel'),'string');
                        ylab = get(get(gca,'ylabel'),'string');
                    else
                        ax1 = ydat;
                        ax2 = interp2(xdat,ydat,zdat,x+0*ydat,ydat);
                        leg = ['Vertical slice at x = ' num2str(x)];
                        xlab = get(get(gca,'ylabel'),'string');
                        ylab = get(get(gca,'xlabel'),'string');
                    end
                    figure; kpfun; plot(ax1,ax2); title(t); xlabel(xlab); legend(leg,'Location','best'); % ylabel(ylab);
                end
            else
                t = timer;
                set(t,'Period',1,'StartDelay',0,'ExecutionMode','singleShot');
                set(t,'TimerFcn',{@flashmessage,'Only available for images',1});
                start(t);
            end
        case '~'
            hkids = get(gca,'children');
            found = 0;
            for i=1:length(hkids)
                if strcmp(get(hkids(i),'selected'),'on')
                    found = i;
                    break
                end
            end
            if found<1 & length(hkids)>0
                for i=1:length(hkids)
                    if strcmp(get(hkids(i),'type'),'image')
                        found = i;
                        break
                    end
                end
            end
            if found>0
                if strcmp(get(hkids(found),'type'),'image')
                    [x,y,b] = ginput(1);
                    if ~(b==1 | b==3)
                        return
                    end
                    xdat = get(hkids(found),'xdata');
                    ydat = get(hkids(found),'ydata');
                    zdat = get(hkids(i),'cdata');
                    if x>max(xdat), x = max(xdat); end
                    if x<min(xdat), x = min(xdat); end
                    if y>max(ydat), y = max(ydat); end
                    if y<min(ydat), y = min(ydat); end
                    if length(xdat)~=size(zdat,2)
                        x = interp1(xdat,(0:(length(xdat)-1))/(length(xdat)-1),x);
                        xdat2 = (0:size(zdat,2)-1)/(size(zdat,2)-1);
                        x = interp1((0:(length(xdat)-1))/(length(xdat)-1),get(hkids(found),'xdata'),x);
                        xdat = interp1((0:(length(xdat)-1))/(length(xdat)-1),get(hkids(found),'xdata'),xdat2);
                    end
                    if length(ydat)~=size(zdat,1)
                        y = interp1(ydat,(0:(length(ydat)-1))/(length(ydat)-1),y);
                        ydat2 = (0:size(zdat,1)-1)/(size(zdat,1)-1);
                        y = interp1((0:(length(ydat)-1))/(length(ydat)-1),get(hkids(found),'ydata'),y);
                        ydat = interp1((0:(length(ydat)-1))/(length(ydat)-1),get(hkids(found),'ydata'),ydat2);
                    end
                    t = get(get(gca,'title'),'String');
                    if b==1
                        y = interp1(ydat,1:length(ydat),y,'nearest');
                        ax1 = xdat;
                        ax2 = interp2(xdat,ydat,zdat,xdat,y+0*xdat);
                        leg = ['Horizontal slice at y = ' num2str(y)];
                        xlab = get(get(gca,'xlabel'),'string');
                        ylab = get(get(gca,'ylabel'),'string');
                    else
                        x = interp1(xdat,1:length(xdat),x,'nearest');
                        ax1 = ydat;
                        ax2 = interp2(xdat,ydat,zdat,x+0*ydat,ydat);
                        leg = ['Vertical slice at x = ' num2str(x)];
                        xlab = get(get(gca,'ylabel'),'string');
                        ylab = get(get(gca,'xlabel'),'string');
                    end
                    figure; kpfun; plot(ax1,ax2); title(t); xlabel(xlab); legend(leg,'Location','best');  % ylabel(ylab);
                end
            else
                t = timer;
                set(t,'Period',1,'StartDelay',0,'ExecutionMode','singleShot');
                set(t,'TimerFcn',{@flashmessage,'Only available for images',1});
                start(t);
            end
                
% Available keys:  G enter(13)  space(32) tab(9) escape(27) o zero )
%                  all-cntl-chars
        otherwise
             disp(num2str(double(get(gcf,'CurrentCharacter'))))
    end
end

function flashmessage(obj,event,txt,d,kill) % ,opt
    persistent hshow hbck lastnum
    if isempty(lastnum)
        lastnum = 0;
    end
    if nargin<4, d=1; end
    
    if nargin<5
        if ~isempty(hshow)
            try
                delete([hshow hbck]);
            catch
                % Don't care
            end
        end
        lims = axis(gca);

        hs=text((lims(1)+lims(2))/2,(lims(3)+lims(4))/2,txt,'horizontalalignment','center','color',[0 0 0],'fontsize',10);
        bx = get(hs,'Extent');
        delete(hs);
        if strcmp(get(gca,'xdir'),'reverse')
            bx(3) = -bx(3);
        end
        if strcmp(get(gca,'ydir'),'reverse')
            bx(4) = -bx(4);
        end
        hbck = patch([bx(1) bx(1)+bx(3) bx(1)+bx(3) bx(1)],[bx(2) bx(2) bx(2)+bx(4) bx(2)+bx(4)],[.9 .9 .9],'linestyle','none');
        hshow = text((lims(1)+lims(2))/2,(lims(3)+lims(4))/2,txt,'horizontalalignment','center','color',[0 0 0],'fontsize',10);
        lastnum = lastnum + 1;
        t = timer;
        set(t,'Period',1,'StartDelay',d,'ExecutionMode','singleShot');
        set(t,'TimerFcn',{@flashmessage,'','',lastnum});
        start(t)
    else
        if kill == lastnum
            try
                delete([hshow hbck]);
            catch
                % Don't care
            end
            clear hshow
        end
    end
