function varargout = guidemfile(varargin)
% GUIDEMFILE Support function for Guide

%   $Revision: 1.16.1.1 $  $Date: 2000/10/05 16:57:10 $

try
  [varargout{1:nargout}] = feval(varargin{:});
catch
  errordlg(['Unhandled internal error in guidemfile.',NL,lasterr], ...
	   'GUIDE');
  lasterr('');
end


function contents = getFileContentsNoSave(filename)
% get contents of file on disk; don't save editor's changes
fid = fopen(filename);
if fid == -1
  error([filename, ' does not exist.']);
else
  contents = fscanf(fid, '%c');
  fclose(fid);
end

function contents = getFileContents(filename)
% if this has newlines, assume it is the contents of an
% already-loaded file:  just return our input.
% This is the only place where we READ the file from disk.

if ~isempty(find(filename == NL))
  contents = filename;
else
  % If this file is currently open in the MATLAB editor and has
  % unsaved changes, we need to force a save in the editor before
  % loading the file ourselves (to catch any changes).
  % TODO: We should prompt the user the first time, with a "don't
  % ask me again" dialog.
  if isMFileDirty(filename)
    com.mathworks.ide.editor.EditorApplication.saveExistingFileNoPrompt(java.lang.String(filename));
  end
  contents = getFileContentsNoSave(filename);
end

% -------------------------------------------
function writeFileContents(filename, contents)

[filepath, funcname, ext] = fileparts(filename);

fid = fopen(filename, 'w');
fprintf(fid, '%s', contents);
fclose(fid);

% Now that we've changed the file, reload it in the editor,
% QUIETLY, if it is already open:
import com.mathworks.ide.editor.EditorApplication;
EditorApplication.reloadFileNoPrompt(java.lang.String(filename));

% GUIDE has no problem loading from a fig-file not on the path,
% but MATLAB will have a problem executing an Mfile not on the
% path.  So if it will not be seen, simply add that directory to
% the path.  I'd CD there, but we might have multiple guide
% sessions going in different off-path directories, and then
% CDing would only take care of one of them...
if ~onPath(filepath)
  addpath(filepath);
end

% clear this function out of the parser cache - we might be
% calling it right away if we're about to activate.
clear(funcname);


% -------------------------------------------------------------
function opts = getOptions(filename_or_contents) %%%%%%%%%%%%%%%%%%%%%%%%%
% return an options struct with all known options in this
% file.  It is an error to call this with a non-existent file.
guts = getFileContents(filename_or_contents);

% return functionNames field
opts.functionNames = getFunctionNames(guts);

% return syscolorfig field (1 if special string found; 0 otherwise)
opts.syscolorfig = 0;
ind = findSyscolorString(guts);
if ~isempty(ind)
  opts.syscolorfig = 1;
end

% return singleton field only if 'openfig' is found:
% 1 if openfig(..., 'reuse')
% 0 otherwise
ind = findConstructorString(guts);
if ~isempty(ind)
  opts.singleton = 0;
  if ~isempty(findstr(guts(ind(1):ind(2)), '''reuse'''))
    opts.singleton = 1;
  end
end

% return blocking field (1 if 'uiwait' found)
opts.blocking = 0;
ind = findBlockingString(guts);
if ~isempty(ind)
  opts.blocking = 1;
end

ind = findVersionString(guts);
if ~isempty(ind)
  opts.version = guts(ind(1):ind(2));
end

function [funcnames, linenums_out] = getFunctionNames(file_contents) %%%%%%%%%%%%%%
% should recognize funcs of the form:
% "function funcname"
% "function out = funcname"
% "function funcname(in)"
% "function out = funcname(in)"
% with or without trailing comment characters on the line

% replace CRs with NLs so we don't have to worry about this below
file_contents(find(file_contents == CR)) = NL;
% add trailing newline (internally only) so we don't have to worry
file_contents(end + 1) = NL;

% find all occurrences of the word 'function' at begin of line:
funcs = findstr(file_contents, [NL 'function']) + 1;
line_ends = find(file_contents == NL);

funcnames = {};

for i = funcs

  linenums(end+1) = length(find(line_ends < i))+1;
  
  this_line = file_contents(i:(line_ends(min(find(line_ends>i)))));
  % strip off trailing comment (if any)
  comments = find(this_line == '%');
  if ~isempty(comments)
    this_line = this_line(1:(comments(1)-1));
  end
  
  % strip away input args (if any):
  paren = find(this_line == '(');
  if ~isempty(paren)
    this_line = this_line(1:(paren(1) - 1));
  end
  
  % strip away output args (if any), otherwise strip away word 'function':
  equalsign = find(this_line == '=');
  if ~isempty(equalsign)
    this_line = this_line((equalsign(1) + 1):end);
  else
    this_line = this_line(9:end);
  end
  
  % finally strip away all whitespace:
  this_line = this_line(~isspace(this_line));
  
  funcnames{end+1} = this_line;
end
if nargout == 2
  linenums_out = linenums;
end


function isDirty = isMFileDirty(filename)
[filepath, funcname, ext] = fileparts(filename);
mname = fullfile(filepath, [funcname,'.m']);
isDirty = com.mathworks.ide.editor.EditorApplication.isDirty(mname)

% ------------------------------------------------
function [header, body] = splitHeaderBody(contents)
% look for the first line that doesn't start with a comment,
% and return everything up to that in "header", and the remainder
% in "body".  If the function has no help at the top, and no H1
% line, then only the function declaration will be returned in
% header.  If the function has all help and no code, then body will
% be empty.
lines = find(contents == NL);
non_comments = contents(lines(1:end-1)+1) ~= '%';
headerEnd = min([lines(non_comments) length(contents)]);
header = contents(1:headerEnd);
body = contents((headerEnd+1):end);

function updateFile(fig, filename)
% takes a .fig file name, and generates or updates the
% corresponding mfile.  If the mfile doesn't exist yet, create the
% main function.  If the mfile does exist, update the main function
% as necessary.  Then, append any new callback subfunctions.
% Called whenever we choose "save" or "activate" or "edit Callback"
% in the layout editor.  Also called if we modify any mfile options
% in the application options, and hit OK.
% This is the only place where we ever WRITE the file to disk.

[filepath, funcname, ext] = fileparts(filename);
mname = fullfile(filepath, [funcname,'.m']);

optionsNew = guideopts(fig);
oldfilename = get(fig, 'filename');
if ~isempty(oldfilename)
  [oldfilepath, oldfuncname, oldext] = fileparts(oldfilename);
  oldmfile = fullfile(oldfilepath, [oldfuncname,'.m']);
  if exist(oldmfile)
    optionsNew.lastSavedFile = oldmfile;
    guideopts(fig, optionsNew);
  end
end

isSaveAs = 0;

% Take care of saveAs issues before doing the regular save stuff
if  isfield(optionsNew, 'lastSavedFile') ...
    & ~isequal(mname, optionsNew.lastSavedFile)

  isSaveAs = 1;
  % get a copy of the latest SAVED changes, before we get a copy of
  % the latest unsaved changes (which forces a save as a
  % side-effect).  We want to make the new file based on the latest
  % changes in the editor, but we don't want the old file to
  % contain those changes - so after we force the save and get the
  % latest contents for the save as, we put back the previous
  % version.
  old_contents = getFileContentsNoSave(optionsNew.lastSavedFile);
  contents =  getFileContents(optionsNew.lastSavedFile);
  % restore the old file to its last saved state, getting rid of
  % unsaved changes in the editor that were saved as a side-effect
  % of our reading it:
  writeFileContents(optionsNew.lastSavedFile, old_contents);

  % convert all occurrences of the old function name with new
  % function name, preserving case:
  % old -> new (all lowercase)
  % OLD -> NEW (all uppercase)
  [header, body] = splitHeaderBody(contents);
  header = strrep(header, lower(oldfuncname), lower(funcname));
  header = strrep(header, upper(oldfuncname), upper(funcname));
  contents = [header, body];
  
  % convert all callbacks containing calls to old fcn with calls to
  % new fcn:
  renameCallbacks(findall(fig), oldfuncname, funcname);
  
  % now write out the modified version of the old mfile to the new name:
  writeFileContents(mname, contents);
end

bringEditorForward = 0;
if exist(mname)

  % if the MFile already exists, treat any options in it as the
  % TRUTH, overriding what is contained in the options struct (which
  % may be stale).  BUT: if the 'override' flag exists in the
  % options struct, that means we've just come from the App Options
  % dialog, and we want to change what's in the Mfile.
  options = getOptions(mname);

  % allow figure's current color to override the MFile's system
  % color setting:
  if ~isequal(get(fig, 'color'),...
	      get(0,'defaultuicontrolbackgroundcolor'))
    options.syscolorfig = 0;
  end
  
  % If the optionsNew struct has the override field set, honor the
  % settings in it without checking what's in the MFile (remember
  % to clear that flag so next time we honor the mfile).
  if optionsNew.override
    optionsNew.override = 0;
  else
    % allow changes to the mfile to override fields in the stored
    % options structure:
    fields = {'singleton','syscolorfig','blocking'};
    for i=1:length(fields)
      if isfield(options, fields{i})
	optionsNew = setfield(optionsNew, fields{i}, getfield(options, fields{i}));
      end
    end
  end

  prev_contents = getFileContents(mname);
  contents = updateFileContents(prev_contents, optionsNew);
else
  prev_contents = '';
  contents = makeFileContents(filename, optionsNew);
  bringEditorForward = 1;
end
if optionsNew.callbacks
  contents = appendCallbacks(contents, fig, funcname);
end

guideopts(fig, optionsNew);

needToSave = ~contentsEqual(prev_contents, contents);

if needToSave | isSaveAs

  import com.mathworks.ide.editor.EditorApplication;

  if needToSave
    writeFileContents(mname, contents);
  end

  % Bring the editor forward.
  if bringEditorForward | isSaveAs
    EditorApplication.openDocument(java.lang.String(mname));
    if isempty(prev_contents)
    	pause(2)
    end
    if isSaveAs
      % close the previous filename in editor:
      EditorApplication.closeDocument(java.lang.String(optionsNew.lastSavedFile));
    end
  end

  optionsNew.lastSavedFile = mname;
  guideopts(fig, optionsNew);
  
end

function answer = onPath(filepath)
% determine whether the function is on the path (if not, someone
% else will want to add it to the path)

mlpath = lower([path pathsep]);
filepath = lower(filepath);
if isempty(findstr([filepath, pathsep],mlpath)) &...
      ~strcmp(pwd, filepath)
  answer = 0;
else
  answer = 1;
end
  

function answer = contentsEqual(contents1, contents2)
% compare two functions IGNORING the version strings:

ind = findVersionString(contents1);
if ~isempty(ind)
  contents1(ind(1):ind(2)) = '';
end
ind = findVersionString(contents2);
if ~isempty(ind)
  contents2(ind(1):ind(2)) = '';
end
answer = isequal(contents1, contents2);


function contents = updateFileContents(contents, options)%%%%%%%%
% Given the current contents of a file, and the selected options,
% modify the main function so that it matches the options.
% Includes singleton mode, system-color mode, and blocking mode.
% also generate a newer version string.  The new options are passed
% in, and we compare them to the previous options:

% first, determine current options - this is based on what
% is currently in the application M-file:
prev_options = getOptions(contents);

% replace the version string
ind = findVersionString(contents);
if ~isempty(ind)
  contents = [contents(1:(ind(1)-1)),makeVersionString, ...
	      NL, contents((ind(2)+1):end)];
end

% change constructor (if necessary and if possible)
if(isfield(prev_options,'singleton') &...
      prev_options.singleton ~= options.singleton)
  ind = findConstructorString(contents);
  if ~isempty(ind)
    contents = [contents(1:(ind(1)-1)),...
		makeConstructorString(options.singleton), ...
		contents((ind(2)+1):end)];
  end
end
  
% insert/remove syscolor block
if options.syscolorfig ~= prev_options.syscolorfig
  if prev_options.syscolorfig % remove it
    ind = findSyscolorString(contents);
    if ~isempty(ind)
      contents = [contents(1:(ind(1)-1)),contents((ind(2)+1):end)];
    end
  else % insert it
    % for now, just put it after the openfig
    ind = findstr(contents, 'openfig');
    if ~isempty(ind)
      ind = findNextOccurenceOfCharacter(contents, ind, NL);
      contents = [contents(1:(ind+1)),makeSyscolorString(1),contents((ind+2):end)];
    end
  end
end

% insert/remove blocking block
if options.blocking ~= prev_options.blocking
  if prev_options.blocking % remove it
    ind = findBlockingString(contents);
    if ~isempty(ind)
      contents = [contents(1:(ind(1)-1)),contents((ind(2)+1):end)];
    end
  else %insert it
       % put it just before: the
       %   the 'varargout{', or
       %   the first 'else/end', or
       %   'if nargout',
       % whichever comes first:
       ind = min([findstr(contents, 'varargout{'),...
		  findstr(contents, [NL 'else']),...
		  findstr(contents, ['if nargout']),...
		  findstr(contents, [NL 'end'])]);
       ind = findPreviousOccurenceOfCharacter(contents, ind, NL);
       contents = [contents(1:ind),makeBlockingString(1),contents((ind+1):end)];
  end
end

function str = AUTOMATIC
str = '<automatic>';


function setAutoCallback(h, cb)
prevCb = get(h, cb);
set(h, cb, AUTOMATIC);
if ~isempty(prevCb) & ~strcmp(prevCb, AUTOMATIC)
  setappdata(h, ['preserve',lower(cb)],prevCb);
end
com.mathworks.ide.inspector.Inspector.getInspector.refreshIfOpen;


function chooseAutoCallbacks(hVec)
for h = hVec(:)'
  switch get(h, 'type')
   case 'uicontrol'
    switch get(h,'style')
     case {'frame','text'}
      return
     otherwise
      if isempty(get(h, 'callback'))
	setAutoCallback(h,'callback');
      end
    end
  end
end

function renameCallbacks(hVec, oldFunc, newFunc)
oldLen = length(oldFunc);
newLen = length(newFunc);
for h = hVec(:)'
  callbacks = getCallbackProperties(h);
  for cb = callbacks(:)'
    val = get(h, cb{:});
    if strncmp(val, oldFunc, oldLen) & ...
	  (...
	      length(val) == oldLen |...
	      val(oldLen+1) == ' '   |...
	      val(oldLen+1) == '('    ...
	      )
      newVal = [newFunc, val((oldLen + 1):end)];
      set(h, cb{:}, newVal);
    end
  end
end
com.mathworks.ide.inspector.Inspector.getInspector.refreshIfOpen;


function loseAutoCallbacks(hVec)
for h = hVec(:)'
  callbacks = getCallbackProperties(h);
  for cb = callbacks(:)'
    if isequal(get(h, cb{:}), AUTOMATIC)
      set(h, cb{:}, '');
    end
  end
end
com.mathworks.ide.inspector.Inspector.getInspector.refreshIfOpen;


function callbacks = getCallbackProperties(h)
callbacks = {'CreateFcn'; 'DeleteFcn'; 'ButtondownFcn'};
switch get(h,'type')
 case 'figure'
  callbacks = [callbacks,
	       {'WindowButtonDownFcn',
		'WindowButtonMotionFcn',
		'WindowButtonUpFcn',
		'KeyPressFcn',
		'ResizeFcn',
		'CloseRequestFcn'}];
 case {'uicontrol','uimenu','uicontextmenu'}
  callbacks = [callbacks; {'Callback'}];
end


function contents = appendCallbacks(contents, fig, funcname)  %%%%%%%%%%%%
% traverse the tree of objects, looking for any callback containing
% '<automatic>'.  Replace that callback property with the "magic
% incantation" to get into the subfunction, and append that
% subfunction (if it doesnt' already exist).

subfcncallback = [
'function varargout = %s(h, eventdata, handles, varargin)\n'...
'%% Stub for %s of the %s handles.%s.\n'];

all_h = [fig; flipud(allchild(fig))];
for i = 1:length(all_h)

  callbacks = getCallbackProperties(all_h(i));
  this_tag = get(all_h(i),'tag');
  objtype = get(all_h(i),'type');
  
  for cb = 1:length(callbacks)
    if strcmp(get(all_h(i),callbacks{cb}), AUTOMATIC)
      this_cb = callbacks{cb};
      % find out what the callback was before this.  If it was
      % already a call into this function, just put it back, else,
      % construct a subfunction for it:
      PREVIOUS_CALLBACK = ['preserve',lower(this_cb)];
      body = getappdata(all_h(i), PREVIOUS_CALLBACK);

      [p,n,e]=fileparts(getCBMfileName(body));
      if strcmp(n, funcname)
	% put it back if it was already a call into this file:
	set(all_h(i),this_cb,body);
      else
	% Check if the object's tag is a valid variable name - if
        % not, then skip this callback, and issue a warning to the
        % user prompting them to change the tag if they want a
        % callback.  When OK is pressed on the warning dialog, jump
	% to that object's tag property in the inspector:
	if ~isvarname(this_tag)
	  warnstr = [...
	      'Tag must be a legal variable name for GUIDE to append ',...
	      'a callback function prototype to the application M-file. ',...
	      'The ',this_cb,' for the ',get(all_h(i),'type'),...
	      ' with Tag: ''',this_tag,''' can not be appended until ' ...
	      'a legal tag is chosen.'];
	  warnfig = warndlg(warnstr, 'GUIDE');
	  setappdata(warnfig, 'GUIDEInspectMe',all_h(i));
	  set(warnfig,'deletefcn','guidemfile(''delayedInspectTag'')');
	  continue
	end
	
	% construct a callback property value for the object to
        % call into this file:
	subfcn = [this_tag '_' this_cb];
	% replace <automatic> with callback of form
	% mfilename('subfcn',gcbo,[],guidata(gcbo))
	callback = [funcname, '(''', subfcn, ''',gcbo,[],guidata(gcbo))'];
	set(all_h(i),callbacks{cb},callback);

	% Now add the subfuction to this file (if it doesn't
        % already exist):
	existingSubfuncs = getFunctionNames(contents);
	if isempty(strmatch(subfcn, existingSubfuncs, 'exact'))
	  fcnguts = sprintf(subfcncallback, subfcn, this_cb, objtype, ...
			    this_tag);
	
	  if isempty(body)
	    body = sprintf('disp(''%s %s not implemented yet.'')',...
			   this_tag, this_cb);
	  end
	  contents = [contents NL NL NL makeFunctionBeginning NL fcnguts body];
	end % end if callback subfunction needs to be appended
      end % end if callback was already calling into this file

      if isappdata(all_h(i), PREVIOUS_CALLBACK)
	rmappdata(all_h(i), PREVIOUS_CALLBACK);
      end
      
    end % end converting <automatic> callback
  end % end WHILE loop over all callbacks on this object
end % end loop over all objects
com.mathworks.ide.inspector.Inspector.getInspector.refreshIfOpen;

function delayedInspectTag
warnfig = gcbo;
inspectMe = getappdata(gcbo,'GUIDEInspectMe');
inspect(inspectMe);
com.mathworks.ide.inspector.Inspector.activateInspector
com.mathworks.ide.inspector.Inspector.getInspector.selectProperty(java.lang.String('Tag'));

function t = TAB
t = 9; % ascii tab character

function n = NL
n = 10; % ascii newline character

function c = CR
c = 13; % ascii carriage-return character

function contents = makeFileContents(filename, options)
% Generate the main function the first time through:

[path, filename, ext] = fileparts(filename);
FILENAME = upper(filename);
% call NL and TAB functions once, assigning their output to
% variables of the same name, allowing us to use the variables many
% times below without making the actual subfunction calls.
NL = NL;
TAB = TAB;
contents =[...
'function varargout = ',filename,'(varargin)',NL,...
'% ',FILENAME,' Application M-file for ',filename,'.fig',NL,...
'%    FIG = ',FILENAME,' launch ',filename,' GUI.',NL,...
'%    ',FILENAME,'(''callback_name'', ...) invoke the named callback.',NL,...
'',NL,...
'% ',makeVersionString,NL,...
NL,...
'if nargin == 0  % LAUNCH GUI',NL,...
NL,...
TAB,'fig = ',makeConstructorString(options.singleton),NL,...
NL,...
makeSyscolorString(options.syscolorfig),...
TAB,'% Generate a structure of handles to pass to callbacks, and store it. ',NL,...
TAB,'handles = guihandles(fig);',NL,...
TAB,'guidata(fig, handles);',NL,...
NL,...
makeBlockingString(options.blocking),...
TAB,'if nargout > 0',NL,...
TAB,TAB,'varargout{1} = fig;',NL,...
TAB,'end',NL,...
NL,...
'elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK',NL,...
NL,...
TAB,'try',NL,...
TAB,TAB,'[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard',NL,...
TAB,'catch',NL,...
TAB,TAB,'disp(lasterr);',NL,...
TAB,'end',NL,...
NL,...
'end',NL,...
NL,...
NL,...
'%| ABOUT CALLBACKS:',NL,...
'%| GUIDE automatically appends subfunction prototypes to this file, and ',NL,...
'%| sets objects'' callback properties to call them through the FEVAL ',NL,...
'%| switchyard above. This comment describes that mechanism.',NL,...
'%|',NL,...
'%| Each callback subfunction declaration has the following form:',NL,...
'%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)',NL,...
'%|',NL,...
'%| The subfunction name is composed using the object''s Tag and the ',NL,...
'%| callback type separated by ''_'', e.g. ''slider2_Callback'',',NL,...
'%| ''figure1_CloseRequestFcn'', ''axis1_ButtondownFcn''.',NL,...
'%|',NL,...
'%| H is the callback object''s handle (obtained using GCBO).',NL,...
'%|',NL,...
'%| EVENTDATA is empty, but reserved for future use.',NL,...
'%|',NL,...
'%| HANDLES is a structure containing handles of components in GUI using',NL,...
'%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This',NL,...
'%| structure is created at GUI startup using GUIHANDLES and stored in',NL,...
'%| the figure''s application data using GUIDATA. A copy of the structure',NL,...
'%| is passed to each callback.  You can store additional information in',NL,...
'%| this structure at GUI startup, and you can change the structure',NL,...
'%| during callbacks.  Call guidata(h, handles) after changing your',NL,...
'%| copy to replace the stored original so that subsequent callbacks see',NL,...
'%| the updates. Type "help guihandles" and "help guidata" for more',NL,...
'%| information.',NL,...
'%|',NL,...
'%| VARARGIN contains any extra arguments you have passed to the',NL,...
'%| callback. Specify the extra arguments by editing the callback',NL,...
'%| property in the inspector. By default, GUIDE sets the property to:',NL,...
'%| <MFILENAME>(''<SUBFUNCTION_NAME>'', gcbo, [], guidata(gcbo))',NL,...
'%| Add any extra arguments after the last argument, before the final',NL,...
'%| closing parenthesis.',NL];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                 VERSION handling                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = makeVersionString
prefix = getVersionPrefix;
verStr = '2.0';
dateStr = date;
timeVec = clock;
timeStr = sprintf('%02d:%02d:%02d',fix(timeVec(4:6)));
str = sprintf('%s%s %s %s',prefix,verStr,dateStr,timeStr);


function ind = findVersionString(contents)
% return start and end index of version string (or [] if not found)
% consider the whole line from the beginning of the string to the
% \n to be the version string.
ind = [];
prefix = getVersionPrefix;
len = length(prefix);
ver_begin = findstr(contents, prefix);
if ~isempty(ver_begin)
  ver_end = ver_begin + len;
  line_end = findNextOccurenceOfCharacter(contents, ver_end, NL);
  ind = [ver_begin, line_end];
end

function str = getVersionPrefix
str = 'Last Modified by GUIDE v';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                CONSTRUCTOR handling                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = makeConstructorString(is_singleton)
if is_singleton
  arg = '''reuse''';
else
  arg = '''new''';
end
str = sprintf('openfig(mfilename,%s);',arg);

function ind = findConstructorString(contents)
ind = [];
const_start = findstr(contents, 'openfig');
if ~isempty(const_start)
  const_end = const_start + 6;
  if contents(const_end + 1) == '('
    closeparen = findNextOccurenceOfCharacter(contents, const_start,')');
    const_end = closeparen;
    if contents(const_end + 1) == ';'
      const_end = const_end + 1;
    end
  end
  ind = [const_start const_end];
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                SYSCOLOR handling                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = makeSyscolorString(is_syscolorfig)

if is_syscolorfig
  str = sprintf('%s\n%s\n\n', getSyscolorComment,getSyscolorCode);
else
  str = '';
end

function str = getSyscolorComment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
str = [TAB,'% Use system color scheme for figure:'];
function str = getSyscolorCode %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
str = ...
[TAB,'set(fig,''Color'',get(0,''defaultUicontrolBackgroundColor''));'];

function ind = findSyscolorString(contents) %%%%%%%%%%%%%%%%%%%%%
comment = findLineExtent(contents, findstr(contents, getSyscolorComment));
code = findLineExtent(contents, findstr(lower(contents), lower(getSyscolorCode)));
if isempty(code)
	code = findLineExtent(contents, findStrWithSpacing(lower(contents), lower(getSyscolorCode)));
end

ind = [min([comment code]) max([comment code])];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                BLOCKING handling                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function str = getBlockingComment
str = [TAB,'% Wait for callbacks to run and window to be dismissed:'];
function str = getBlockingCode
str = [TAB,'uiwait(fig);'];

function str = makeBlockingString(is_blocking)
if is_blocking
  str = sprintf('%s\n%s\n\n',getBlockingComment, getBlockingCode);
else
  str = '';
end

function ind = findBlockingString(contents)
lines = [findLineExtent(contents, findstr(contents, getBlockingComment)),...
	 findLineExtent(contents, findstr(contents, getBlockingCode))];
ind = [min(lines), max(lines)];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%             STRING SEARCHING UTILITIES                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function ind = findLineExtent(contents, pos) %%%%%%%%%%%%%%%%%%%%%%
if isempty(pos)
  ind = [];
else
  ind = [findPreviousOccurenceOfCharacter(contents, pos, NL),...
	 findNextOccurenceOfCharacter(contents, pos, NL)];
end

function ind = findNextOccurenceOfCharacter(contents, pos, character)
occurrences = find(contents == character);
ind = occurrences(min(find(occurrences>pos)));

function ind = findPreviousOccurenceOfCharacter(contents, pos, character)
occurrences = find(contents == character);
ind = occurrences(max(find(occurrences<pos)));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                    OTHER UTILITIES                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function mname = getCBMfileName(cb)
% parse callback of the form: FUNCTION('SUBFUNCTION',...)
% returning the full path to the Mfile named FUNCTION
mname = '';
if ~isempty(cb)
	funcname_end = min([find(cb==' '),find(cb == '('),length(cb)+1]);
	mname = which(cb(1:(funcname_end-1)));
end

function cbname = getCBSubfunctionName(cb)
cbname = '';
quotes = find(cb=='''');
if length(quotes) >= 2
  cbname = cb((quotes(1)+1):(quotes(2)-1));
end

function lineno = getSubfunctionLineNumber(mname, cbname)
contents = getFileContents(mname);
[names, linenos] = getFunctionNames(contents);
ind = strmatch(cbname, names, 'exact');
if length(ind) == 1
  %  lineno = length(find(find(contents==NL) < ind)) + 1;
  lineno = linenos(ind);
else
  lineno = 1;
end

function scrollToCBSubfunction(obj, whichCb)
currentCb = get(obj,whichCb);
if ~strcmp(currentCb, AUTOMATIC)
  mfunc = getCBMfileName(currentCb);
  subfunc = getCBSubfunctionName(currentCb);
  lineno = getSubfunctionLineNumber(mfunc,subfunc);
  com.mathworks.ide.editor.EditorApplication.openDocumentToLine(...
      mfunc, lineno, 1, 1);
end

      
function fcnBegin = makeFunctionBeginning
lineLength = 70;
fcnBegin = ['% ' ones(1,lineLength-2)*abs('-')];

% ***************************************************************
% Try to find System Color string - in case user inserted spaces.
% contents - contents of M-file.
% str      - string that is being searched for.
function codeIndex = findStrWithSpacing(contents, str)

% Initialize variables.
codeIndex = [];

% Determine if defaultUicontrolBackgroundColor is in contents.
% If not codeIndex = [] and return.
codeIndex = findstr('defaultuicontrolbackgroundcolor', contents);
if isempty(codeIndex)
	return
end

% Determine if the remaining contents of the DefaultUicontrolBackgroundColor
% line is str.

% Remove spaces.
str((str == ' ')) = '';

% Extract the line.
for i = 1:length(codeIndex)
	index = findLineExtent(contents, codeIndex(i));
	contentsLine = contents(index(1)+1:index(2)-1);
	
	% Remove spaces.
	contentsLine((contentsLine == ' ')) = '';

	% Compare - Return index if the same otherwise return [] (initialized value).
	if strcmp(str, contentsLine)
		codeIndex = index(1)+1; 
		return;
	end
end

% If defaultUicontrolBackgroundColor is found but it is not part
% of the entire string need to reset codeIndex to empty.
codeIndex = [];
