Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/ui/space_console.py417
-rw-r--r--release/ui/space_text.py373
-rw-r--r--source/blender/blenkernel/BKE_context.h2
-rw-r--r--source/blender/blenkernel/BKE_report.h21
-rw-r--r--source/blender/blenkernel/intern/context.c12
-rw-r--r--source/blender/blenkernel/intern/report.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c16
-rw-r--r--source/blender/blenloader/intern/writefile.c3
-rw-r--r--source/blender/editors/SConscript1
-rw-r--r--source/blender/editors/include/ED_space_api.h1
-rw-r--r--source/blender/editors/screen/area.c1
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_console/SConscript13
-rw-r--r--source/blender/editors/space_console/console_draw.c214
-rw-r--r--source/blender/editors/space_console/console_intern.h75
-rw-r--r--source/blender/editors/space_console/console_ops.c570
-rw-r--r--source/blender/editors/space_console/space_console.c336
-rw-r--r--source/blender/makesdna/DNA_space_types.h58
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h2
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_screen.c11
-rw-r--r--source/blender/makesrna/intern/rna_space.c134
-rw-r--r--source/blender/python/intern/bpy_ui.c1
-rw-r--r--source/blender/windowmanager/WM_types.h5
-rw-r--r--source/blender/windowmanager/intern/wm.c13
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c6
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c21
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c2
-rw-r--r--source/blender/windowmanager/wm.h2
29 files changed, 1924 insertions, 389 deletions
diff --git a/release/ui/space_console.py b/release/ui/space_console.py
new file mode 100644
index 00000000000..497f34a28d0
--- /dev/null
+++ b/release/ui/space_console.py
@@ -0,0 +1,417 @@
+
+import bpy
+
+class CONSOLE_HT_header(bpy.types.Header):
+ __space_type__ = "CONSOLE"
+ __idname__ = "CONSOLE_HT_header"
+
+ def draw(self, context):
+ sc = context.space_data
+ # text = sc.text
+ layout = self.layout
+
+ layout.template_header()
+
+ if context.area.show_menus:
+ row = layout.row()
+ row.itemM("CONSOLE_MT_console")
+
+ row = layout.row()
+ row.scale_x = 0.9
+ row.itemR(sc, "type", expand=True)
+ if sc.type == 'REPORT':
+ row.itemR(sc, "show_report_debug")
+ row.itemR(sc, "show_report_info")
+ row.itemR(sc, "show_report_operator")
+ row.itemR(sc, "show_report_warn")
+ row.itemR(sc, "show_report_error")
+
+
+class CONSOLE_MT_console(bpy.types.Menu):
+ __space_type__ = "CONSOLE"
+ __label__ = "Console"
+
+ def draw(self, context):
+ layout = self.layout
+ sc = context.space_data
+
+ layout.column()
+ layout.itemO("CONSOLE_OT_clear")
+
+def add_scrollback(text, text_type):
+ for l in text.split('\n'):
+ bpy.ops.CONSOLE_OT_scrollback_append(text=l.replace('\t', ' '), type=text_type)
+
+def get_console(console_id):
+ '''
+ helper function for console operators
+ currently each text datablock gets its own console - code.InteractiveConsole()
+ ...which is stored in this function.
+
+ console_id can be any hashable type
+ '''
+ import sys, code, io
+
+ try: consoles = get_console.consoles
+ except:consoles = get_console.consoles = {}
+
+ # clear all dead consoles, use text names as IDs
+ # TODO, find a way to clear IDs
+ '''
+ for console_id in list(consoles.keys()):
+ if console_id not in bpy.data.texts:
+ del consoles[id]
+ '''
+
+ try:
+ namespace, console, stdout, stderr = consoles[console_id]
+ except:
+ namespace = {'__builtins__':__builtins__} # locals()
+ namespace['bpy'] = bpy
+
+ console = code.InteractiveConsole(namespace)
+
+ if sys.version.startswith('2'):
+ stdout = io.BytesIO() # Py2x support
+ stderr = io.BytesIO()
+ else:
+ stdout = io.StringIO()
+ stderr = io.StringIO()
+
+ consoles[console_id]= namespace, console, stdout, stderr
+
+ return namespace, console, stdout, stderr
+
+class CONSOLE_OT_exec(bpy.types.Operator):
+ '''
+ Operator documentatuon text, will be used for the operator tooltip and python docs.
+ '''
+ __label__ = "Console Execute"
+
+ # Both prompts must be the same length
+ PROMPT = '>>> '
+ PROMPT_MULTI = '... '
+
+ # is this working???
+ '''
+ def poll(self, context):
+ return (context.space_data.type == 'PYTHON')
+ ''' # its not :|
+
+ def execute(self, context):
+ import sys
+
+ sc = context.space_data
+
+ try:
+ line = sc.history[-1].line
+ except:
+ return ('CANCELLED',)
+
+ if sc.type != 'PYTHON':
+ return ('CANCELLED',)
+
+ namespace, console, stdout, stderr = get_console(hash(context.region))
+
+ # redirect output
+ sys.stdout = stdout
+ sys.stderr = stderr
+
+ # run the console
+ if not line.strip():
+ line_exec = '\n' # executes a multiline statement
+ else:
+ line_exec = line
+
+ is_multiline = console.push(line_exec)
+
+ stdout.seek(0)
+ stderr.seek(0)
+
+ output = stdout.read()
+ output_err = stderr.read()
+
+ # cleanup
+ sys.stdout = sys.__stdout__
+ sys.stderr = sys.__stderr__
+ sys.last_traceback = None
+
+ # So we can reuse, clear all data
+ stdout.truncate(0)
+ stderr.truncate(0)
+
+ bpy.ops.CONSOLE_OT_scrollback_append(text = sc.prompt+line, type='INPUT')
+
+ if is_multiline: sc.prompt = self.PROMPT_MULTI
+ else: sc.prompt = self.PROMPT
+
+ # insert a new blank line
+ bpy.ops.CONSOLE_OT_history_append(text="", current_character=0)
+
+ # Insert the output into the editor
+ # not quite correct because the order might have changed, but ok 99% of the time.
+ if output: add_scrollback(output, 'OUTPUT')
+ if output_err: add_scrollback(output_err, 'ERROR')
+
+
+ return ('FINISHED',)
+
+
+def autocomp(bcon):
+ '''
+ This function has been taken from a BGE console autocomp I wrote a while ago
+ the dictionaty bcon is not needed but it means I can copy and paste from the old func
+ which works ok for now.
+
+ could be moved into its own module.
+ '''
+
+
+ def is_delimiter(ch):
+ '''
+ For skipping words
+ '''
+ if ch == '_':
+ return False
+ if ch.isalnum():
+ return False
+
+ return True
+
+ def is_delimiter_autocomp(ch):
+ '''
+ When autocompleteing will earch back and
+ '''
+ if ch in '._[] "\'':
+ return False
+ if ch.isalnum():
+ return False
+
+ return True
+
+
+ def do_autocomp(autocomp_prefix, autocomp_members):
+ '''
+ return text to insert and a list of options
+ '''
+ autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
+
+ print("AUTO: '%s'" % autocomp_prefix)
+ print("MEMBERS: '%s'" % str(autocomp_members))
+
+ if not autocomp_prefix:
+ return '', autocomp_members
+ elif len(autocomp_members) > 1:
+ # find a common string between all members after the prefix
+ # 'ge' [getA, getB, getC] --> 'get'
+
+ # get the shortest member
+ min_len = min([len(v) for v in autocomp_members])
+
+ autocomp_prefix_ret = ''
+
+ for i in range(len(autocomp_prefix), min_len):
+ char_soup = set()
+ for v in autocomp_members:
+ char_soup.add(v[i])
+
+ if len(char_soup) > 1:
+ break
+ else:
+ autocomp_prefix_ret += char_soup.pop()
+
+ print(autocomp_prefix_ret)
+ return autocomp_prefix_ret, autocomp_members
+ elif len(autocomp_members) == 1:
+ return autocomp_members[0][len(autocomp_prefix):], []
+ else:
+ return '', []
+
+
+ def BCon_PrevChar(bcon):
+ cursor = bcon['cursor']-1
+ if cursor<0:
+ return None
+
+ try:
+ return bcon['edit_text'][cursor]
+ except:
+ return None
+
+
+ def BCon_NextChar(bcon):
+ try:
+ return bcon['edit_text'][bcon['cursor']]
+ except:
+ return None
+
+ def BCon_cursorLeft(bcon):
+ bcon['cursor'] -= 1
+ if bcon['cursor'] < 0:
+ bcon['cursor'] = 0
+
+ def BCon_cursorRight(bcon):
+ bcon['cursor'] += 1
+ if bcon['cursor'] > len(bcon['edit_text']):
+ bcon['cursor'] = len(bcon['edit_text'])
+
+ def BCon_AddScrollback(bcon, text):
+
+ bcon['scrollback'] = bcon['scrollback'] + text
+
+
+ def BCon_cursorInsertChar(bcon, ch):
+ if bcon['cursor']==0:
+ bcon['edit_text'] = ch + bcon['edit_text']
+ elif bcon['cursor']==len(bcon['edit_text']):
+ bcon['edit_text'] = bcon['edit_text'] + ch
+ else:
+ bcon['edit_text'] = bcon['edit_text'][:bcon['cursor']] + ch + bcon['edit_text'][bcon['cursor']:]
+
+ bcon['cursor']
+ if bcon['cursor'] > len(bcon['edit_text']):
+ bcon['cursor'] = len(bcon['edit_text'])
+ BCon_cursorRight(bcon)
+
+
+ TEMP_NAME = '___tempname___'
+
+ cursor_orig = bcon['cursor']
+
+ ch = BCon_PrevChar(bcon)
+ while ch != None and (not is_delimiter(ch)):
+ ch = BCon_PrevChar(bcon)
+ BCon_cursorLeft(bcon)
+
+ if ch != None:
+ BCon_cursorRight(bcon)
+
+ #print (cursor_orig, bcon['cursor'])
+
+ cursor_base = bcon['cursor']
+
+ autocomp_prefix = bcon['edit_text'][cursor_base:cursor_orig]
+
+ print("PREFIX:'%s'" % autocomp_prefix)
+
+ # Get the previous word
+ if BCon_PrevChar(bcon)=='.':
+ BCon_cursorLeft(bcon)
+ ch = BCon_PrevChar(bcon)
+ while ch != None and is_delimiter_autocomp(ch)==False:
+ ch = BCon_PrevChar(bcon)
+ BCon_cursorLeft(bcon)
+
+ cursor_new = bcon['cursor']
+
+ if ch != None:
+ cursor_new+=1
+
+ pytxt = bcon['edit_text'][cursor_new:cursor_base-1].strip()
+ print("AUTOCOMP EVAL: '%s'" % pytxt)
+ #try:
+ if pytxt:
+ bcon['console'].runsource(TEMP_NAME + '=' + pytxt, '<input>', 'single')
+ # print val
+ else: ##except:
+ val = None
+
+ try:
+ val = bcon['namespace'][TEMP_NAME]
+ del bcon['namespace'][TEMP_NAME]
+ except:
+ val = None
+
+ if val:
+ autocomp_members = dir(val)
+
+ autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
+
+ bcon['cursor'] = cursor_orig
+ for v in autocomp_prefix_ret:
+ BCon_cursorInsertChar(bcon, v)
+ cursor_orig = bcon['cursor']
+
+ if autocomp_members:
+ BCon_AddScrollback(bcon, ', '.join(autocomp_members))
+
+ del val
+
+ else:
+ # Autocomp global namespace
+ autocomp_members = bcon['namespace'].keys()
+
+ if autocomp_prefix:
+ autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
+
+ autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
+
+ bcon['cursor'] = cursor_orig
+ for v in autocomp_prefix_ret:
+ BCon_cursorInsertChar(bcon, v)
+ cursor_orig = bcon['cursor']
+
+ if autocomp_members:
+ BCon_AddScrollback(bcon, ', '.join(autocomp_members))
+
+ bcon['cursor'] = cursor_orig
+
+
+class CONSOLE_OT_autocomplete(bpy.types.Operator):
+ '''
+ Operator documentatuon text, will be used for the operator tooltip and python docs.
+ '''
+ __label__ = "Console Autocomplete"
+
+ def poll(self, context):
+ return context.space_data.type == 'PYTHON'
+
+ def execute(self, context):
+
+ sc = context.space_data
+
+ namespace, console, stdout, stderr = get_console(hash(context.region))
+
+ current_line = sc.history[-1]
+ line = current_line.line
+
+ if not console:
+ return ('CANCELLED',)
+
+ if sc.type != 'PYTHON':
+ return ('CANCELLED',)
+
+ # fake cursor, use for autocomp func.
+ bcon = {}
+ bcon['cursor'] = current_line.current_character
+ bcon['console'] = console
+ bcon['edit_text'] = line
+ bcon['namespace'] = namespace
+ bcon['scrollback'] = '' # nor from the BGE console
+
+
+ # This function isnt aware of the text editor or being an operator
+ # just does the autocomp then copy its results back
+ autocomp(bcon)
+
+ # Now we need to copy back the line from blender back into the text editor.
+ # This will change when we dont use the text editor anymore
+ if bcon['scrollback']:
+ add_scrollback(bcon['scrollback'], 'INFO')
+
+ # copy back
+ current_line.line = bcon['edit_text']
+ current_line.current_character = bcon['cursor']
+
+ context.area.tag_redraw()
+
+ return ('FINISHED',)
+
+
+
+bpy.types.register(CONSOLE_HT_header)
+bpy.types.register(CONSOLE_MT_console)
+
+bpy.ops.add(CONSOLE_OT_exec)
+bpy.ops.add(CONSOLE_OT_autocomplete)
+
diff --git a/release/ui/space_text.py b/release/ui/space_text.py
index c6ce1cb71d6..07e43f32054 100644
--- a/release/ui/space_text.py
+++ b/release/ui/space_text.py
@@ -226,376 +226,6 @@ class TEXT_MT_edit(bpy.types.Menu):
layout.itemM("TEXT_MT_edit_to3d")
-
-def get_console(text):
- '''
- helper function for console operators
- currently each text datablock gets its own console - code.InteractiveConsole()
- ...which is stored in this function.
- '''
- import sys, code, io
-
- try: consoles = get_console.consoles
- except:consoles = get_console.consoles = {}
-
- # clear all dead consoles, use text names as IDs
- for id in list(consoles.keys()):
- if id not in bpy.data.texts:
- del consoles[id]
-
- if not text:
- return None, None, None
-
- id = text.name
-
- try:
- namespace, console, stdout = consoles[id]
- except:
- namespace = locals()
- namespace['bpy'] = bpy
-
- console = code.InteractiveConsole(namespace)
-
- if sys.version.startswith('2'): stdout = io.BytesIO() # Py2x support
- else: stdout = io.StringIO()
-
- consoles[id]= namespace, console, stdout
-
- return namespace, console, stdout
-
-class TEXT_OT_console_exec(bpy.types.Operator):
- '''
- Operator documentatuon text, will be used for the operator tooltip and python docs.
- '''
- __label__ = "Console Execute"
-
- # Each text block gets its own console info.
- console = {}
-
- # Both prompts must be the same length
- PROMPT = '>>> '
- PROMPT_MULTI = '... '
-
- def execute(self, context):
- import sys
-
- st = context.space_data
- text = st.text
-
- if not text:
- return ('CANCELLED',)
-
- namespace, console, stdout = get_console(text)
-
- line = text.current_line.line
-
- # redirect output
- sys.stdout = stdout
- sys.stderr = stdout
-
- # run the console
- if not line.strip():
- line = '\n' # executes a multiline statement
-
- if line.startswith(self.PROMPT_MULTI) or line.startswith(self.PROMPT):
- line = line[len(self.PROMPT):]
- was_prefix = True
- else:
- was_prefix = False
-
-
- is_multiline = console.push(line)
-
- stdout.seek(0)
- output = stdout.read()
-
- # cleanup
- sys.stdout = sys.__stdout__
- sys.stderr = sys.__stderr__
- sys.last_traceback = None
-
- # So we can reuse, clear all data
- stdout.truncate(0)
-
- if is_multiline:
- prefix = self.PROMPT_MULTI
- else:
- prefix = self.PROMPT
-
- # Kindof odd, add the prefix if we didnt have one. makes it easier to re-read.
- if not was_prefix:
- bpy.ops.TEXT_OT_move(type='LINE_BEGIN')
- bpy.ops.TEXT_OT_insert(text = prefix)
-
- bpy.ops.TEXT_OT_move(type='LINE_END')
-
- # Insert the output into the editor
- bpy.ops.TEXT_OT_insert(text= '\n' + output + prefix)
-
- return ('FINISHED',)
-
-
-def autocomp(bcon):
- '''
- This function has been taken from a BGE console autocomp I wrote a while ago
- the dictionaty bcon is not needed but it means I can copy and paste from the old func
- which works ok for now.
-
- could be moved into its own module.
- '''
-
-
- def is_delimiter(ch):
- '''
- For skipping words
- '''
- if ch == '_':
- return False
- if ch.isalnum():
- return False
-
- return True
-
- def is_delimiter_autocomp(ch):
- '''
- When autocompleteing will earch back and
- '''
- if ch in '._[] "\'':
- return False
- if ch.isalnum():
- return False
-
- return True
-
-
- def do_autocomp(autocomp_prefix, autocomp_members):
- '''
- return text to insert and a list of options
- '''
- autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
-
- print("AUTO: '%s'" % autocomp_prefix)
- print("MEMBERS: '%s'" % str(autocomp_members))
-
- if not autocomp_prefix:
- return '', autocomp_members
- elif len(autocomp_members) > 1:
- # find a common string between all members after the prefix
- # 'ge' [getA, getB, getC] --> 'get'
-
- # get the shortest member
- min_len = min([len(v) for v in autocomp_members])
-
- autocomp_prefix_ret = ''
-
- for i in range(len(autocomp_prefix), min_len):
- char_soup = set()
- for v in autocomp_members:
- char_soup.add(v[i])
-
- if len(char_soup) > 1:
- break
- else:
- autocomp_prefix_ret += char_soup.pop()
-
- print(autocomp_prefix_ret)
- return autocomp_prefix_ret, autocomp_members
- elif len(autocomp_members) == 1:
- return autocomp_members[0][len(autocomp_prefix):], []
- else:
- return '', []
-
-
- def BCon_PrevChar(bcon):
- cursor = bcon['cursor']-1
- if cursor<0:
- return None
-
- try:
- return bcon['edit_text'][cursor]
- except:
- return None
-
-
- def BCon_NextChar(bcon):
- try:
- return bcon['edit_text'][bcon['cursor']]
- except:
- return None
-
- def BCon_cursorLeft(bcon):
- bcon['cursor'] -= 1
- if bcon['cursor'] < 0:
- bcon['cursor'] = 0
-
- def BCon_cursorRight(bcon):
- bcon['cursor'] += 1
- if bcon['cursor'] > len(bcon['edit_text']):
- bcon['cursor'] = len(bcon['edit_text'])
-
- def BCon_AddScrollback(bcon, text):
-
- bcon['scrollback'] = bcon['scrollback'] + text
-
-
- def BCon_cursorInsertChar(bcon, ch):
- if bcon['cursor']==0:
- bcon['edit_text'] = ch + bcon['edit_text']
- elif bcon['cursor']==len(bcon['edit_text']):
- bcon['edit_text'] = bcon['edit_text'] + ch
- else:
- bcon['edit_text'] = bcon['edit_text'][:bcon['cursor']] + ch + bcon['edit_text'][bcon['cursor']:]
-
- bcon['cursor']
- if bcon['cursor'] > len(bcon['edit_text']):
- bcon['cursor'] = len(bcon['edit_text'])
- BCon_cursorRight(bcon)
-
-
- TEMP_NAME = '___tempname___'
-
- cursor_orig = bcon['cursor']
-
- ch = BCon_PrevChar(bcon)
- while ch != None and (not is_delimiter(ch)):
- ch = BCon_PrevChar(bcon)
- BCon_cursorLeft(bcon)
-
- if ch != None:
- BCon_cursorRight(bcon)
-
- #print (cursor_orig, bcon['cursor'])
-
- cursor_base = bcon['cursor']
-
- autocomp_prefix = bcon['edit_text'][cursor_base:cursor_orig]
-
- print("PREFIX:'%s'" % autocomp_prefix)
-
- # Get the previous word
- if BCon_PrevChar(bcon)=='.':
- BCon_cursorLeft(bcon)
- ch = BCon_PrevChar(bcon)
- while ch != None and is_delimiter_autocomp(ch)==False:
- ch = BCon_PrevChar(bcon)
- BCon_cursorLeft(bcon)
-
- cursor_new = bcon['cursor']
-
- if ch != None:
- cursor_new+=1
-
- pytxt = bcon['edit_text'][cursor_new:cursor_base-1].strip()
- print("AUTOCOMP EVAL: '%s'" % pytxt)
- #try:
- if pytxt:
- bcon['console'].runsource(TEMP_NAME + '=' + pytxt, '<input>', 'single')
- # print val
- else: ##except:
- val = None
-
- try:
- val = bcon['namespace'][TEMP_NAME]
- del bcon['namespace'][TEMP_NAME]
- except:
- val = None
-
- if val:
- autocomp_members = dir(val)
-
- autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
-
- bcon['cursor'] = cursor_orig
- for v in autocomp_prefix_ret:
- BCon_cursorInsertChar(bcon, v)
- cursor_orig = bcon['cursor']
-
- if autocomp_members:
- BCon_AddScrollback(bcon, ', '.join(autocomp_members))
-
- del val
-
- else:
- # Autocomp global namespace
- autocomp_members = bcon['namespace'].keys()
-
- if autocomp_prefix:
- autocomp_members = [v for v in autocomp_members if v.startswith(autocomp_prefix)]
-
- autocomp_prefix_ret, autocomp_members = do_autocomp(autocomp_prefix, autocomp_members)
-
- bcon['cursor'] = cursor_orig
- for v in autocomp_prefix_ret:
- BCon_cursorInsertChar(bcon, v)
- cursor_orig = bcon['cursor']
-
- if autocomp_members:
- BCon_AddScrollback(bcon, ', '.join(autocomp_members))
-
- bcon['cursor'] = cursor_orig
-
-
-class TEXT_OT_console_autocomplete(bpy.types.Operator):
- '''
- Operator documentatuon text, will be used for the operator tooltip and python docs.
- '''
- __label__ = "Console Autocomplete"
-
- def execute(self, context):
-
- st = context.space_data
- text = st.text
-
- namespace, console, stdout = get_console(text)
-
- line = text.current_line.line
-
- if not console:
- return ('CANCELLED',)
-
-
- # fake cursor, use for autocomp func.
- bcon = {}
- bcon['cursor'] = text.current_character
- bcon['console'] = console
- bcon['edit_text'] = line
- bcon['namespace'] = namespace
- bcon['scrollback'] = '' # nor from the BGE console
-
-
- # This function isnt aware of the text editor or being an operator
- # just does the autocomp then copy its results back
- autocomp(bcon)
-
- # Now we need to copy back the line from blender back into the text editor.
- # This will change when we dont use the text editor anymore
-
- # clear the line
- bpy.ops.TEXT_OT_move(type='LINE_END')
- bpy.ops.TEXT_OT_move_select(type = 'LINE_BEGIN')
- bpy.ops.TEXT_OT_delete(type = 'PREVIOUS_CHARACTER')
-
- if bcon['scrollback']:
- bpy.ops.TEXT_OT_move_select(type = 'LINE_BEGIN')
- bpy.ops.TEXT_OT_insert(text = bcon['scrollback'].strip() + '\n')
- bpy.ops.TEXT_OT_move_select(type='LINE_BEGIN')
-
- bpy.ops.TEXT_OT_insert(text = bcon['edit_text'])
-
- # Read only
- if 0:
- text.current_character = bcon['cursor']
- else:
- bpy.ops.TEXT_OT_move(type = 'LINE_BEGIN')
-
- for i in range(bcon['cursor']):
- bpy.ops.TEXT_OT_move(type='NEXT_CHARACTER')
-
-
- return ('FINISHED',)
-
-
-
bpy.types.register(TEXT_HT_header)
bpy.types.register(TEXT_PT_properties)
bpy.types.register(TEXT_PT_find)
@@ -607,6 +237,3 @@ bpy.types.register(TEXT_MT_edit_select)
bpy.types.register(TEXT_MT_edit_markers)
bpy.types.register(TEXT_MT_edit_to3d)
-bpy.ops.add(TEXT_OT_console_exec)
-bpy.ops.add(TEXT_OT_console_autocomplete)
-
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 92c79ff757f..5baf5af81d1 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -111,11 +111,13 @@ struct SpaceLink *CTX_wm_space_data(const bContext *C);
struct ARegion *CTX_wm_region(const bContext *C);
void *CTX_wm_region_data(const bContext *C);
struct ARegion *CTX_wm_menu(const bContext *C);
+struct ReportList *CTX_wm_reports(const bContext *C);
struct View3D *CTX_wm_view3d(const bContext *C);
struct RegionView3D *CTX_wm_region_view3d(const bContext *C);
struct SpaceText *CTX_wm_space_text(const bContext *C);
struct SpaceImage *CTX_wm_space_image(const bContext *C);
+struct SpaceConsole *CTX_wm_space_console(const bContext *C);
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index 1bb7152fbf3..26853866ebb 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -40,15 +40,22 @@ extern "C" {
* is needed. */
typedef enum ReportType {
- RPT_DEBUG = 0,
- RPT_INFO = 1000,
- RPT_WARNING = 2000,
- RPT_ERROR = 3000,
- RPT_ERROR_INVALID_INPUT = 3001,
- RPT_ERROR_INVALID_CONTEXT = 3002,
- RPT_ERROR_OUT_OF_MEMORY = 3003
+ RPT_DEBUG = 1<<0,
+ RPT_INFO = 1<<1,
+ RPT_OPERATOR = 1<<2,
+ RPT_WARNING = 1<<3,
+ RPT_ERROR = 1<<4,
+ RPT_ERROR_INVALID_INPUT = 1<<5,
+ RPT_ERROR_INVALID_CONTEXT = 1<<6,
+ RPT_ERROR_OUT_OF_MEMORY = 1<<7
} ReportType;
+#define RPT_DEBUG_ALL (RPT_DEBUG)
+#define RPT_INFO_ALL (RPT_INFO)
+#define RPT_OPERATOR_ALL (RPT_OPERATOR)
+#define RPT_WARNING_ALL (RPT_WARNING)
+#define RPT_ERROR_ALL (RPT_ERROR|RPT_ERROR_INVALID_INPUT|RPT_ERROR_INVALID_CONTEXT|RPT_ERROR_OUT_OF_MEMORY)
+
enum ReportListFlags {
RPT_PRINT = 1,
RPT_STORE = 2,
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 1b499384886..bbf3ceb01e8 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -204,6 +204,11 @@ struct ARegion *CTX_wm_menu(const bContext *C)
return C->wm.menu;
}
+struct ReportList *CTX_wm_reports(const bContext *C)
+{
+ return C->wm.manager->reports;
+}
+
View3D *CTX_wm_view3d(const bContext *C)
{
if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D)
@@ -226,6 +231,13 @@ struct SpaceText *CTX_wm_space_text(const bContext *C)
return NULL;
}
+struct SpaceConsole *CTX_wm_space_console(const bContext *C)
+{
+ if(C->wm.area && C->wm.area->spacetype==SPACE_CONSOLE)
+ return C->wm.area->spacedata.first;
+ return NULL;
+}
+
struct SpaceImage *CTX_wm_space_image(const bContext *C)
{
if(C->wm.area && C->wm.area->spacetype==SPACE_IMAGE)
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 8de8cf8d0f4..6564329ef82 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -49,6 +49,7 @@ static char *report_type_str(int type)
switch(type) {
case RPT_DEBUG: return "Debug";
case RPT_INFO: return "Info";
+ case RPT_OPERATOR: return "Operator";
case RPT_WARNING: return "Warning";
case RPT_ERROR: return "Error";
case RPT_ERROR_INVALID_INPUT: return "Invalid Input Error";
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 37dda0e41f4..5489c55f789 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4221,7 +4221,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
wm->keymaps.first= wm->keymaps.last= NULL;
wm->paintcursors.first= wm->paintcursors.last= NULL;
wm->queue.first= wm->queue.last= NULL;
- wm->reports.first= wm->reports.last= NULL;
+ wm->reports= NULL;
wm->jobs.first= wm->jobs.last= NULL;
wm->windrawable= NULL;
@@ -4856,6 +4856,20 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->path= NULL;
}
+ else if(sl->spacetype==SPACE_CONSOLE) {
+ SpaceConsole *sconsole= (SpaceConsole *)sl;
+ ConsoleLine *cl;
+
+ link_list(fd, &sconsole->scrollback);
+ link_list(fd, &sconsole->history);
+
+ //for(cl= sconsole->scrollback.first; cl; cl= cl->next)
+ // cl->line= newdataadr(fd, cl->line);
+
+ //for(cl= sconsole->history.first; cl; cl= cl->next)
+ // cl->line= newdataadr(fd, cl->line);
+
+ }
}
sa->actionzones.first= sa->actionzones.last= NULL;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ebec409ddf4..958e8bb874b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1960,6 +1960,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
else if(sl->spacetype==SPACE_LOGIC){
writestruct(wd, DATA, "SpaceLogic", 1, sl);
}
+ else if(sl->spacetype==SPACE_CONSOLE) {
+ writestruct(wd, DATA, "SpaceConsole", 1, sl);
+ }
sl= sl->next;
}
}
diff --git a/source/blender/editors/SConscript b/source/blender/editors/SConscript
index 9baaf7ae7a5..d7bb567e3eb 100644
--- a/source/blender/editors/SConscript
+++ b/source/blender/editors/SConscript
@@ -30,6 +30,7 @@ SConscript(['datafiles/SConscript',
'space_text/SConscript',
'space_sequencer/SConscript',
'space_logic/SConscript',
+ 'space_console/SConscript',
'transform/SConscript',
'screen/SConscript',
'sculpt_paint/SConscript',
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index f2b46369d13..efaf0f56f92 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -51,6 +51,7 @@ void ED_spacetype_script(void);
void ED_spacetype_text(void);
void ED_spacetype_sequencer(void);
void ED_spacetype_logic(void);
+void ED_spacetype_console(void);
/* calls for instancing and freeing spacetype static data
called in WM_init_exit */
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index addda6e02ee..9617a1fbea2 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1059,6 +1059,7 @@ static char *windowtype_pup(void)
"|%l" //293
"|Scripts Window %x14"//313
+ "|Console %x18"
);
}
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index c8df9bb9741..5a55c5fb717 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -75,6 +75,7 @@ void ED_spacetypes_init(void)
ED_spacetype_text();
ED_spacetype_sequencer();
ED_spacetype_logic();
+ ED_spacetype_console();
// ...
/* register operator types for screen and all spaces */
diff --git a/source/blender/editors/space_console/SConscript b/source/blender/editors/space_console/SConscript
new file mode 100644
index 00000000000..a29c17f6937
--- /dev/null
+++ b/source/blender/editors/space_console/SConscript
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+Import ('env')
+
+sources = env.Glob('*.c')
+defs = []
+incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../python ../../makesrna ../../blenfont'
+
+if not env['WITH_BF_PYTHON']:
+ defs.append('DISABLE_PYTHON')
+
+env.BlenderLib ( 'bf_editors_space_console', sources, Split(incs), defs, libtype=['core'], priority=[95] )
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
new file mode 100644
index 00000000000..042c84041d0
--- /dev/null
+++ b/source/blender/editors/space_console/console_draw.c
@@ -0,0 +1,214 @@
+/**
+ * $Id: text_draw.c 21558 2009-07-13 11:41:24Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLF_api.h"
+
+#include "BLI_blenlib.h"
+
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_global.h"
+#include "BKE_main.h"
+// #include "BKE_suggestions.h"
+#include "BKE_text.h"
+#include "BKE_report.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_datafiles.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+//#include "console_intern.h"
+
+static void console_font_begin(SpaceConsole *sc)
+{
+ static int mono= -1; // XXX needs proper storage
+
+ if(mono == -1)
+ mono= BLF_load_mem("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
+
+ BLF_set(mono);
+ BLF_aspect(1.0);
+
+ BLF_size(sc->lheight, 72);
+}
+
+static void console_line_color(int type)
+{
+ switch(type){
+ case CONSOLE_LINE_OUTPUT:
+ glColor4ub(96, 128, 255, 255);
+ break;
+ case CONSOLE_LINE_INPUT:
+ glColor4ub(255, 255, 255, 255);
+ break;
+ case CONSOLE_LINE_INFO:
+ glColor4ub(0, 170, 0, 255);
+ break;
+ case CONSOLE_LINE_ERROR:
+ glColor4ub(220, 96, 96, 255);
+ break;
+ }
+}
+
+static void console_report_color(int type)
+{
+ if(type & RPT_ERROR_ALL) return glColor4ub(220, 0, 0, 255);
+ if(type & RPT_WARNING_ALL) return glColor4ub(220, 96, 96, 255);
+ if(type & RPT_OPERATOR_ALL) return glColor4ub(96, 128, 255, 255);
+ if(type & RPT_INFO_ALL) return glColor4ub(0, 170, 0, 255);
+ if(type & RPT_DEBUG_ALL) return glColor4ub(196, 196, 196, 255);
+ return glColor4ub(196, 196, 196, 255); /* unknown */
+}
+
+
+/* return 0 if the last line is off the screen
+ * should be able to use this for any string type */
+static int console_draw_string(char *str, int str_len, int console_width, int lheight, int ymax, int *x, int *y)
+{
+ if(str_len > console_width) { /* wrap? */
+ int tot_lines = (str_len/console_width)+1; /* total number of lines for wrapping */
+ char *line_stride= str + ((tot_lines-1) * console_width); /* advance to the last line and draw it first */
+ char eol; /* baclup the end of wrapping */
+
+ /* last part needs no clipping */
+ BLF_position(*x, *y, 0); (*y) += lheight;
+ BLF_draw(line_stride);
+ line_stride -= console_width;
+
+ for(; line_stride >= str; line_stride -= console_width) {
+ eol = line_stride[console_width];
+ line_stride[console_width]= '\0';
+
+ BLF_position(*x, *y, 0); (*y) += lheight;
+ BLF_draw(line_stride);
+
+ line_stride[console_width] = eol; /* restore */
+
+ /* check if were out of view bounds */
+ if(*y > ymax)
+ return 0;
+ }
+ }
+ else { /* simple, no wrap */
+ BLF_position(*x, *y, 0); (*y) += lheight;
+ BLF_draw(str);
+
+ if(*y > ymax)
+ return 0;
+ }
+
+ return 1;
+}
+
+#define CONSOLE_DRAW_MARGIN 8
+
+void console_text_main(struct SpaceConsole *sc, struct ARegion *ar, ReportList *reports)
+{
+ ConsoleLine *cl= sc->history.last;
+
+ int x_orig=CONSOLE_DRAW_MARGIN, y_orig=CONSOLE_DRAW_MARGIN;
+ int x,y;
+ int cwidth;
+ int console_width; /* number of characters that fit into the width of the console (fixed width) */
+
+
+ console_font_begin(sc);
+ cwidth = BLF_fixed_width();
+
+ console_width= (ar->winx - CONSOLE_DRAW_MARGIN*2)/cwidth;
+ if (console_width < 8) console_width= 8;
+
+ x= x_orig; y= y_orig;
+
+ if(sc->type==CONSOLE_TYPE_PYTHON) {
+ int prompt_len= strlen(sc->prompt);
+
+ /* text */
+ console_line_color(CONSOLE_LINE_INPUT);
+
+ /* command line */
+ if(prompt_len) {
+ BLF_position(x, y, 0); x += cwidth * prompt_len;
+ BLF_draw(sc->prompt);
+ }
+ BLF_position(x, y, 0);
+ BLF_draw(cl->line);
+
+ /* cursor */
+ console_line_color(CONSOLE_LINE_ERROR); /* lazy */
+ glRecti(x+(cwidth*cl->cursor) -1, y-2, x+(cwidth*cl->cursor) +1, y+sc->lheight-2);
+
+ x= x_orig; /* remove prompt offset */
+
+ y += sc->lheight;
+
+ for(cl= sc->scrollback.last; cl; cl= cl->prev) {
+ console_line_color(cl->type);
+
+ if(!console_draw_string(cl->line, cl->len, console_width, sc->lheight, ar->winy + sc->lheight, &x, &y))
+ break; /* past the y limits */
+
+ }
+ }
+ else {
+ Report *report;
+ int report_mask= 0;
+
+ /* convert our display toggles into a flag compatible with BKE_report flags */
+ if(sc->rpt_mask & CONSOLE_RPT_DEBUG) report_mask |= RPT_DEBUG_ALL;
+ if(sc->rpt_mask & CONSOLE_RPT_INFO) report_mask |= RPT_INFO_ALL;
+ if(sc->rpt_mask & CONSOLE_RPT_OP) report_mask |= RPT_OPERATOR_ALL;
+ if(sc->rpt_mask & CONSOLE_RPT_WARN) report_mask |= RPT_WARNING_ALL;
+ if(sc->rpt_mask & CONSOLE_RPT_ERR) report_mask |= RPT_ERROR_ALL;
+
+ for(report=reports->list.last; report; report=report->prev) {
+
+ if(report->type & report_mask) {
+ console_report_color(report->type);
+ if(!console_draw_string(report->message, strlen(report->message), console_width, sc->lheight, ar->winy + sc->lheight, &x, &y))
+ break; /* past the y limits */
+ }
+
+ }
+ }
+
+}
diff --git a/source/blender/editors/space_console/console_intern.h b/source/blender/editors/space_console/console_intern.h
new file mode 100644
index 00000000000..55474844d87
--- /dev/null
+++ b/source/blender/editors/space_console/console_intern.h
@@ -0,0 +1,75 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef ED_CONSOLE_INTERN_H
+#define ED_CONSOLE_INTERN_H
+
+/* internal exports only */
+
+struct ConsoleLine;
+struct wmOperatorType;
+struct ReportList;
+
+/* TODO, make into a pref */
+#define CONSOLE_SCROLLBACK_LIMIT 128
+
+/* console_draw.c */
+void console_text_main(struct SpaceConsole *sc, struct ARegion *ar, struct ReportList *reports);
+
+/* console_ops.c */
+void console_history_free(SpaceConsole *sc, ConsoleLine *cl);
+void console_scrollback_free(SpaceConsole *sc, ConsoleLine *cl);
+ConsoleLine *console_history_add_str(const bContext *C, char *str, int own);
+ConsoleLine *console_scrollback_add_str(const bContext *C, char *str, int own);
+
+ConsoleLine *console_history_verify(const bContext *C);
+
+
+void CONSOLE_OT_move(wmOperatorType *ot);
+void CONSOLE_OT_delete(wmOperatorType *ot);
+void CONSOLE_OT_insert(wmOperatorType *ot);
+
+void CONSOLE_OT_history_append(wmOperatorType *ot);
+void CONSOLE_OT_scrollback_append(wmOperatorType *ot);
+
+void CONSOLE_OT_clear(wmOperatorType *ot);
+void CONSOLE_OT_history_cycle(wmOperatorType *ot);
+void CONSOLE_OT_zoom(wmOperatorType *ot);
+
+enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD };
+enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
+
+/* defined in DNA_space_types.h */
+static EnumPropertyItem console_line_type_items[] = {
+ {CONSOLE_LINE_OUTPUT, "OUTPUT", 0, "Output", ""},
+ {CONSOLE_LINE_INPUT, "INPUT", 0, "Input", ""},
+ {CONSOLE_LINE_INFO, "INFO", 0, "Information", ""},
+ {CONSOLE_LINE_ERROR, "ERROR", 0, "Error", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+#endif /* ED_CONSOLE_INTERN_H */
+
diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c
new file mode 100644
index 00000000000..cb883d2d450
--- /dev/null
+++ b/source/blender/editors/space_console/console_ops.c
@@ -0,0 +1,570 @@
+/**
+ * $Id: text_ops.c 21549 2009-07-12 12:47:34Z campbellbarton $
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h> /* ispunct */
+#include <sys/stat.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_blenlib.h"
+#include "PIL_time.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+// #include "BKE_suggestions.h"
+//#include "BKE_text.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "console_intern.h"
+
+void console_history_free(SpaceConsole *sc, ConsoleLine *cl)
+{
+ BLI_remlink(&sc->history, cl);
+ MEM_freeN(cl->line);
+ MEM_freeN(cl);
+}
+void console_scrollback_free(SpaceConsole *sc, ConsoleLine *cl)
+{
+ BLI_remlink(&sc->scrollback, cl);
+ MEM_freeN(cl->line);
+ MEM_freeN(cl);
+}
+
+void console_scrollback_limit(SpaceConsole *sc)
+{
+ int tot;
+ for(tot= BLI_countlist(&sc->scrollback); tot > CONSOLE_SCROLLBACK_LIMIT; tot--)
+ console_scrollback_free(sc, sc->scrollback.first);
+}
+
+/* return 0 if no change made, clamps the range */
+static int console_line_cursor_set(ConsoleLine *cl, int cursor)
+{
+ int cursor_new;
+
+ if(cursor < 0) cursor_new= 0;
+ else if(cursor > cl->len) cursor_new= cl->len;
+ else cursor_new= cursor;
+
+ if(cursor_new == cl->cursor)
+ return 0;
+
+ cl->cursor= cursor_new;
+ return 1;
+}
+
+static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from)
+{
+ ConsoleLine *ci= MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
+
+ if(from) {
+ ci->line= BLI_strdup(from->line);
+ ci->len= strlen(ci->line);
+ ci->len_alloc= ci->len;
+
+ ci->cursor= from->cursor;
+ ci->type= from->type;
+ } else {
+ ci->line= MEM_callocN(64, "console-in-line");
+ ci->len_alloc= 64;
+ ci->len= 0;
+ }
+
+ BLI_addtail(lb, ci);
+ return ci;
+}
+
+static ConsoleLine *console_history_add(const bContext *C, ConsoleLine *from)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+
+ return console_lb_add__internal(&sc->history, from);
+}
+
+static ConsoleLine *console_scrollback_add(const bContext *C, ConsoleLine *from)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+
+ return console_lb_add__internal(&sc->scrollback, from);
+}
+
+static ConsoleLine *console_lb_add_str__internal(ListBase *lb, const bContext *C, char *str, int own)
+{
+ ConsoleLine *ci= MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add");
+ if(own) ci->line= str;
+ else ci->line= BLI_strdup(str);
+
+ ci->len = ci->len_alloc = strlen(str);
+
+ BLI_addtail(lb, ci);
+ return ci;
+}
+ConsoleLine *console_history_add_str(const bContext *C, char *str, int own)
+{
+ return console_lb_add_str__internal(&CTX_wm_space_console(C)->history, C, str, own);
+}
+ConsoleLine *console_scrollback_add_str(const bContext *C, char *str, int own)
+{
+ return console_lb_add_str__internal(&CTX_wm_space_console(C)->scrollback, C, str, own);
+}
+
+ConsoleLine *console_history_verify(const bContext *C)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+ ConsoleLine *ci= sc->history.last;
+ if(ci==NULL)
+ ci= console_history_add(C, NULL);
+
+ return ci;
+}
+
+
+static void console_line_verify_length(ConsoleLine *ci, int len)
+{
+ /* resize the buffer if needed */
+ if(len > ci->len_alloc) {
+ int new_len= len * 2; /* new length */
+ char *new_line= MEM_callocN(new_len, "console line");
+ memcpy(new_line, ci->line, ci->len);
+ MEM_freeN(ci->line);
+
+ ci->line= new_line;
+ ci->len_alloc= new_len;
+ }
+}
+
+static int console_line_insert(ConsoleLine *ci, char *str)
+{
+ int len = strlen(str);
+
+ if(len==0)
+ return 0;
+
+ console_line_verify_length(ci, len + ci->len);
+
+ memmove(ci->line+ci->cursor+len, ci->line+ci->cursor, (ci->len - ci->cursor)+1);
+ memcpy(ci->line+ci->cursor, str, len);
+
+ ci->len += len;
+ ci->cursor += len;
+
+ return len;
+}
+
+static int console_edit_poll(const bContext *C)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+
+ if(!sc || sc->type != CONSOLE_TYPE_PYTHON)
+ return 0;
+
+ return 1;
+}
+
+/* static funcs for text editing */
+
+
+/* similar to the text editor, with some not used. keep compatible */
+static EnumPropertyItem move_type_items[]= {
+ {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
+ {LINE_END, "LINE_END", 0, "Line End", ""},
+ {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+ {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static int move_exec(const bContext *C, wmOperator *op)
+{
+ ConsoleLine *ci= console_history_verify(C);
+
+ int type= RNA_enum_get(op->ptr, "type");
+ int done= 0;
+
+ switch(type) {
+ case LINE_BEGIN:
+ done= console_line_cursor_set(ci, 0);
+ break;
+ case LINE_END:
+ done= console_line_cursor_set(ci, INT_MAX);
+ break;
+ case PREV_CHAR:
+ done= console_line_cursor_set(ci, ci->cursor-1);
+ break;
+ case NEXT_CHAR:
+ done= console_line_cursor_set(ci, ci->cursor+1);
+ break;
+ }
+
+ if(done) {
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CONSOLE_OT_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Cursor";
+ ot->idname= "CONSOLE_OT_move";
+
+ /* api callbacks */
+ ot->exec= move_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to.");
+}
+
+
+static int insert_exec(const bContext *C, wmOperator *op)
+{
+ ConsoleLine *ci= console_history_verify(C);
+ char *str= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+
+ int len= console_line_insert(ci, str);
+
+ MEM_freeN(str);
+
+ if(len==0)
+ return OPERATOR_CANCELLED;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+static int insert_invoke(const bContext *C, wmOperator *op, wmEvent *event)
+{
+ char str[2] = {event->ascii, '\0'};
+ RNA_string_set(op->ptr, "text", str);
+ return insert_exec(C, op);
+}
+
+void CONSOLE_OT_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Insert";
+ ot->idname= "CONSOLE_OT_insert";
+
+ /* api callbacks */
+ ot->exec= insert_exec;
+ ot->invoke= insert_invoke;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
+}
+
+
+static EnumPropertyItem delete_type_items[]= {
+ {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
+ {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""},
+// {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""},
+// {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static int delete_exec(const bContext *C, wmOperator *op)
+{
+
+ ConsoleLine *ci= console_history_verify(C);
+
+
+ int done = 0;
+
+ int type= RNA_enum_get(op->ptr, "type");
+
+ if(ci->len==0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch(type) {
+ case DEL_NEXT_CHAR:
+ if(ci->cursor < ci->len) {
+ memmove(ci->line + ci->cursor, ci->line + ci->cursor+1, (ci->len - ci->cursor)+1);
+ ci->len--;
+ done= 1;
+ }
+ break;
+ case DEL_PREV_CHAR:
+ if(ci->cursor > 0) {
+ ci->cursor--; /* same as above */
+ memmove(ci->line + ci->cursor, ci->line + ci->cursor+1, (ci->len - ci->cursor)+1);
+ ci->len--;
+ done= 1;
+ }
+ break;
+ }
+
+ if(!done)
+ return OPERATOR_CANCELLED;
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+void CONSOLE_OT_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete";
+ ot->idname= "CONSOLE_OT_delete";
+
+ /* api callbacks */
+ ot->exec= delete_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete.");
+}
+
+
+/* the python exec operator uses this */
+static int clear_exec(const bContext *C, wmOperator *op)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+
+ short scrollback= RNA_boolean_get(op->ptr, "scrollback");
+ short history= RNA_boolean_get(op->ptr, "history");
+
+ /*ConsoleLine *ci= */ console_history_verify(C);
+
+ if(scrollback) { /* last item in mistory */
+ while(sc->scrollback.first)
+ console_scrollback_free(sc, sc->scrollback.first);
+ }
+
+ if(history) {
+ while(sc->history.first)
+ console_history_free(sc, sc->history.first);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void CONSOLE_OT_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear";
+ ot->idname= "CONSOLE_OT_clear";
+
+ /* api callbacks */
+ ot->exec= clear_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "scrollback", 1, "Scrollback", "Clear the scrollback history");
+ RNA_def_boolean(ot->srna, "history", 0, "History", "Clear the command history");
+}
+
+
+
+/* the python exec operator uses this */
+static int history_cycle_exec(const bContext *C, wmOperator *op)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+ ConsoleLine *ci= console_history_verify(C); /* TODO - stupid, just prevernts crashes when no command line */
+
+ short reverse= RNA_boolean_get(op->ptr, "reverse"); /* assumes down, reverse is up */
+
+ if(reverse) { /* last item in mistory */
+ ci= sc->history.last;
+ BLI_remlink(&sc->history, ci);
+ BLI_addhead(&sc->history, ci);
+ }
+ else {
+ ci= sc->history.first;
+ BLI_remlink(&sc->history, ci);
+ BLI_addtail(&sc->history, ci);
+ }
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void CONSOLE_OT_history_cycle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "History Cycle";
+ ot->idname= "CONSOLE_OT_history_cycle";
+
+ /* api callbacks */
+ ot->exec= history_cycle_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "reverse", 0, "Reverse", "reverse cycle history");
+}
+
+
+/* the python exec operator uses this */
+static int history_append_exec(const bContext *C, wmOperator *op)
+{
+ ConsoleLine *ci= console_history_verify(C);
+
+
+ char *str= RNA_string_get_alloc(op->ptr, "text", NULL, 0); /* own this text in the new line, dont free */
+ int cursor= RNA_int_get(op->ptr, "current_character");
+
+ ci= console_history_add_str(C, str, 1); /* own the string */
+ console_line_cursor_set(ci, cursor);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void CONSOLE_OT_history_append(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "History Append";
+ ot->idname= "CONSOLE_OT_history_append";
+
+ /* api callbacks */
+ ot->exec= history_append_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
+ RNA_def_int(ot->srna, "current_character", 0, 0, INT_MAX, "Cursor", "The index of the cursor.", 0, 10000);
+}
+
+
+/* the python exec operator uses this */
+static int scrollback_append_exec(const bContext *C, wmOperator *op)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+ ConsoleLine *ci= console_history_verify(C);
+
+ char *str= RNA_string_get_alloc(op->ptr, "text", NULL, 0); /* own this text in the new line, dont free */
+ int type= RNA_enum_get(op->ptr, "type");
+
+ ci= console_scrollback_add_str(C, str, 1); /* own the string */
+ ci->type= type;
+
+ console_scrollback_limit(sc);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+void CONSOLE_OT_scrollback_append(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Scrollback Append";
+ ot->idname= "CONSOLE_OT_scrollback_append";
+
+ /* api callbacks */
+ ot->exec= scrollback_append_exec;
+ ot->poll= console_edit_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
+ RNA_def_enum(ot->srna, "type", console_line_type_items, CONSOLE_LINE_OUTPUT, "Type", "Console output type.");
+}
+
+static int zoom_exec(const bContext *C, wmOperator *op)
+{
+ SpaceConsole *sc= CTX_wm_space_console(C);
+
+ int delta= RNA_int_get(op->ptr, "delta");
+
+ sc->lheight += delta;
+ CLAMP(sc->lheight, 8, 32);
+
+ ED_area_tag_redraw(CTX_wm_area(C));
+
+ return OPERATOR_FINISHED;
+}
+
+
+void CONSOLE_OT_zoom(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Console Zoom";
+ ot->idname= "CONSOLE_OT_zoom";
+
+ /* api callbacks */
+ ot->exec= zoom_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
+
+ /* properties */
+ RNA_def_int(ot->srna, "delta", 0, 0, INT_MAX, "Delta", "Scale the view font.", 0, 1000);
+}
+
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
new file mode 100644
index 00000000000..ee80fe3d2d9
--- /dev/null
+++ b/source/blender/editors/space_console/space_console.c
@@ -0,0 +1,336 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+ #include <string.h>
+#include <stdio.h>
+
+#include "DNA_space_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_screen.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
+
+#include "BIF_gl.h"
+
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+#include "UI_view2d.h"
+
+#include "console_intern.h" // own include
+
+
+/* ******************** default callbacks for console space ***************** */
+
+static SpaceLink *console_new(const bContext *C)
+{
+ ARegion *ar;
+ SpaceConsole *sconsole;
+
+ sconsole= MEM_callocN(sizeof(SpaceConsole), "initconsole");
+ sconsole->spacetype= SPACE_CONSOLE;
+
+ sconsole->lheight= 14;
+ sconsole->type= CONSOLE_TYPE_PYTHON;
+ sconsole->rpt_mask= CONSOLE_RPT_OP; /* ? - not sure whats a good default here?*/
+
+ /* header */
+ ar= MEM_callocN(sizeof(ARegion), "header for console");
+
+ BLI_addtail(&sconsole->regionbase, ar);
+ ar->regiontype= RGN_TYPE_HEADER;
+ ar->alignment= RGN_ALIGN_BOTTOM;
+
+
+ /* main area */
+ ar= MEM_callocN(sizeof(ARegion), "main area for text");
+
+ BLI_addtail(&sconsole->regionbase, ar);
+ ar->regiontype= RGN_TYPE_WINDOW;
+
+ ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM_O);
+ ar->v2d.align = (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_POS_Y);
+ ar->v2d.keepzoom = (V2D_LOCKZOOM_X|V2D_LOCKZOOM_Y|V2D_KEEPZOOM|V2D_KEEPASPECT);
+ ar->v2d.keeptot= V2D_KEEPTOT_STRICT;
+ ar->v2d.minzoom= ar->v2d.maxzoom= 1.0f;
+
+ return (SpaceLink *)sconsole;
+}
+
+/* not spacelink itself */
+static void console_free(SpaceLink *sl)
+{
+ SpaceConsole *sc= (SpaceConsole*) sl;
+
+ while(sc->scrollback.first)
+ console_scrollback_free(sc, sc->scrollback.first);
+
+ while(sc->history.first)
+ console_history_free(sc, sc->history.first);
+}
+
+
+/* spacetype; init callback */
+static void console_init(struct wmWindowManager *wm, ScrArea *sa)
+{
+
+}
+
+static SpaceLink *console_duplicate(SpaceLink *sl)
+{
+ SpaceConsole *sconsolen= MEM_dupallocN(sl);
+
+ /* clear or remove stuff from old */
+
+ /* TODO - duplicate?, then we also need to duplicate the py namespace */
+ sconsolen->scrollback.first= sconsolen->scrollback.last= NULL;
+ sconsolen->history.first= sconsolen->history.last= NULL;
+
+ return (SpaceLink *)sconsolen;
+}
+
+
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void console_main_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ListBase *keymap;
+
+ UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy);
+
+ /* own keymap */
+ keymap= WM_keymap_listbase(wm, "Console", SPACE_CONSOLE, 0); /* XXX weak? */
+ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
+}
+
+static void console_main_area_draw(const bContext *C, ARegion *ar)
+{
+ /* draw entirely, view changes should be handled here */
+ SpaceConsole *sc= CTX_wm_space_console(C);
+ //View2D *v2d= &ar->v2d;
+ //float col[3];
+
+ /* clear and setup matrix */
+ //UI_GetThemeColor3fv(TH_BACK, col);
+ //glClearColor(col[0], col[1], col[2], 0.0);
+ glClearColor(0, 0, 0, 1.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* worlks best with no view2d matrix set */
+ /*UI_view2d_view_ortho(C, v2d);*/
+
+ /* data... */
+
+ /* add helper text, why not? */
+ if(sc->scrollback.first==NULL) {
+ console_scrollback_add_str(C, " * Python Interactive Console *", 0);
+ console_scrollback_add_str(C, "Command History: Up/Down Arrow", 0);
+ console_scrollback_add_str(C, "Cursor: Left/Right Home/End", 0);
+ console_scrollback_add_str(C, "Remove: Backspace/Delete", 0);
+ console_scrollback_add_str(C, "Execute: Enter", 0);
+ console_scrollback_add_str(C, "Autocomplete: Tab", 0);
+ console_scrollback_add_str(C, "Ctrl +/- Wheel: Zoom", 0);
+ console_scrollback_add_str(C, "Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.ui", 0);
+ }
+
+ console_history_verify(C); /* make sure we have some command line */
+ console_text_main(sc, ar, CTX_wm_reports(C));
+
+ /* reset view matrix */
+ /* UI_view2d_view_restore(C); */
+
+ /* scrollers */
+ /*
+ scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ UI_view2d_scrollers_draw(C, v2d, scrollers);
+ UI_view2d_scrollers_free(scrollers);
+ */
+}
+
+void console_operatortypes(void)
+{
+ WM_operatortype_append(CONSOLE_OT_move);
+ WM_operatortype_append(CONSOLE_OT_delete);
+ WM_operatortype_append(CONSOLE_OT_insert);
+
+ /* for use by python only */
+ WM_operatortype_append(CONSOLE_OT_history_append);
+ WM_operatortype_append(CONSOLE_OT_scrollback_append);
+
+
+ WM_operatortype_append(CONSOLE_OT_clear);
+ WM_operatortype_append(CONSOLE_OT_history_cycle);
+ WM_operatortype_append(CONSOLE_OT_zoom);
+}
+
+void console_keymap(struct wmWindowManager *wm)
+{
+ ListBase *keymap= WM_keymap_listbase(wm, "Console", SPACE_CONSOLE, 0);
+
+ /*
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_OSKEY, 0)->ptr, "type", LINE_BEGIN);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", EKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", LINE_END);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", EKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "type", LINE_END);
+ */
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", PADPLUSKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_zoom", PADMINUS, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
+
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
+
+ RNA_boolean_set(WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "reverse", 1);
+ WM_keymap_add_item(keymap, "CONSOLE_OT_history_cycle", DOWNARROWKEY, KM_PRESS, 0, 0);
+
+ /*
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
+
+
+ //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_CHAR);
+ //RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_NEXT_WORD);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD);
+ */
+
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_CHAR);
+ RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_CHAR);
+
+#ifndef DISABLE_PYTHON
+ WM_keymap_add_item(keymap, "CONSOLE_OT_exec", RETKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
+ WM_keymap_add_item(keymap, "CONSOLE_OT_autocomplete", TABKEY, KM_PRESS, 0, 0); /* python operator - space_text.py */
+#endif
+ WM_keymap_add_item(keymap, "CONSOLE_OT_insert", KM_TEXTINPUT, KM_PRESS, KM_ANY, 0); // last!
+}
+
+/****************** header region ******************/
+
+/* add handlers, stuff you only do once or on area/region changes */
+static void console_header_area_init(wmWindowManager *wm, ARegion *ar)
+{
+ ED_region_header_init(ar);
+}
+
+static void console_header_area_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_header(C, ar);
+}
+
+static void console_main_area_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ SpaceConsole *sc= sa->spacedata.first;
+
+ /* context changes */
+ switch(wmn->category) {
+ case NC_CONSOLE:
+ if(wmn->data == ND_CONSOLE) { /* generic redraw request */
+ ED_area_tag_redraw(sa);
+ }
+ else if(wmn->data == ND_CONSOLE_REPORT && sc->type==CONSOLE_TYPE_REPORT) {
+ /* redraw also but only for report view, could do less redraws by checking the type */
+ ED_area_tag_redraw(sa);
+ }
+ break;
+ }
+}
+
+/* only called once, from space/spacetypes.c */
+void ED_spacetype_console(void)
+{
+ SpaceType *sc= MEM_callocN(sizeof(SpaceType), "spacetype console");
+ ARegionType *art;
+
+ sc->spaceid= SPACE_CONSOLE;
+
+ sc->new= console_new;
+ sc->free= console_free;
+ sc->init= console_init;
+ sc->duplicate= console_duplicate;
+ sc->operatortypes= console_operatortypes;
+ sc->keymap= console_keymap;
+ sc->listener= console_main_area_listener;
+
+ /* regions: main window */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
+ art->regionid = RGN_TYPE_WINDOW;
+ art->init= console_main_area_init;
+ art->draw= console_main_area_draw;
+
+
+
+ BLI_addhead(&sc->regiontypes, art);
+
+ /* regions: header */
+ art= MEM_callocN(sizeof(ARegionType), "spacetype console region");
+ art->regionid = RGN_TYPE_HEADER;
+ art->minsizey= HEADERY;
+ art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D;
+
+ art->init= console_header_area_init;
+ art->draw= console_header_area_draw;
+
+ BLI_addhead(&sc->regiontypes, art);
+
+
+
+ BKE_spacetype_register(sc);
+}
+
+
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index cc6987084d0..ca50d8494c0 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -464,6 +464,61 @@ typedef struct SpaceImaSel {
} SpaceImaSel;
+typedef struct ConsoleLine {
+ struct ConsoleLine *next, *prev;
+
+ /* keep these 3 vars so as to share free, realloc funcs */
+ int len_alloc; /* allocated length */
+ int len; /* real len - strlen() */
+ char *line;
+
+ int cursor;
+ int type; /* only for use when in the 'scrollback' listbase */
+} ConsoleLine;
+
+/* ConsoleLine.type */
+enum {
+ CONSOLE_LINE_OUTPUT=0,
+ CONSOLE_LINE_INPUT,
+ CONSOLE_LINE_INFO, /* autocomp feedback */
+ CONSOLE_LINE_ERROR
+};
+
+/* SpaceConsole.rpt_mask */
+enum {
+ CONSOLE_TYPE_PYTHON=0,
+ CONSOLE_TYPE_REPORT,
+};
+
+/* SpaceConsole.type see BKE_report.h */
+enum {
+ CONSOLE_RPT_DEBUG = 1<<0,
+ CONSOLE_RPT_INFO = 1<<1,
+ CONSOLE_RPT_OP = 1<<2,
+ CONSOLE_RPT_WARN = 1<<3,
+ CONSOLE_RPT_ERR = 1<<4,
+};
+
+typedef struct SpaceConsole {
+ SpaceLink *next, *prev;
+ ListBase regionbase; /* storage of regions for inactive spaces */
+ int spacetype;
+ float blockscale; // XXX are these needed?
+
+ short blockhandler[8]; // XXX are these needed?
+
+ /* space vars */
+ int type; /* console/report/..? */
+ int rpt_mask; /* which reports to display */
+ int flag, lheight;
+
+ ListBase scrollback; /* ConsoleLine; output */
+ ListBase history; /* ConsoleLine; command history, current edited line is the first */
+ char prompt[8];
+
+} SpaceConsole;
+
+
/* view3d Now in DNA_view3d_types.h */
@@ -810,7 +865,8 @@ enum {
SPACE_TIME,
SPACE_NODE,
SPACE_LOGIC,
- SPACEICONMAX = SPACE_LOGIC
+ SPACE_CONSOLE,
+ SPACEICONMAX = SPACE_CONSOLE
};
#endif
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index fcf3d0aec23..9a60e3c92b8 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -68,7 +68,7 @@ typedef struct wmWindowManager {
ListBase queue; /* refresh/redraw wmNotifier structs */
- ListBase reports; /* information and error reports */
+ struct ReportList *reports; /* information and error reports */
ListBase jobs; /* threaded jobs manager */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index ed1a8052acd..a04a09d4d11 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -371,6 +371,7 @@ extern StructRNA RNA_SoundSequence;
extern StructRNA RNA_Space;
extern StructRNA RNA_Space3DView;
extern StructRNA RNA_SpaceButtonsWindow;
+extern StructRNA RNA_SpaceConsole;
extern StructRNA RNA_SpaceDopeSheetEditor;
extern StructRNA RNA_SpaceGraphEditor;
extern StructRNA RNA_SpaceImageEditor;
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index fb836a98a52..e3171d38932 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -43,6 +43,9 @@ EnumPropertyItem region_type_items[] = {
#ifdef RNA_RUNTIME
+#include "ED_screen.h"
+
+
#include "WM_api.h"
#include "WM_types.h"
@@ -97,15 +100,23 @@ static void rna_def_scrarea(BlenderRNA *brna)
prop= RNA_def_property(srna, "show_menus", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", HEADER_NO_PULLDOWN);
RNA_def_property_ui_text(prop, "Show Menus", "Show menus in the header.");
+
+ RNA_def_function(srna, "tag_redraw", "ED_area_tag_redraw");
}
static void rna_def_region(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna= RNA_def_struct(brna, "Region", NULL);
RNA_def_struct_ui_text(srna, "Region", "Region in a subdivided screen area.");
RNA_def_struct_sdna(srna, "ARegion");
+
+ prop= RNA_def_property(srna, "id", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "swinid");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Region ID", "Uniqute ID for this region.");
}
static void rna_def_bscreen(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 697548de817..fb41262b812 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -24,6 +24,8 @@
#include <stdlib.h>
+#include "MEM_guardedalloc.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_types.h"
@@ -56,6 +58,7 @@ EnumPropertyItem space_type_items[] = {
{SPACE_TIME, "TIMELINE", 0, "Timeline", ""},
{SPACE_NODE, "NODE_EDITOR", 0, "Node Editor", ""},
{SPACE_LOGIC, "LOGIC_EDITOR", 0, "Logic Editor", ""},
+ {SPACE_CONSOLE, "CONSOLE", 0, "Console", ""},
{0, NULL, 0, NULL, NULL}};
#define DC_RGB {0, "COLOR", ICON_IMAGE_RGB, "Color", "Draw image with RGB colors."}
@@ -122,6 +125,8 @@ static StructRNA* rna_Space_refine(struct PointerRNA *ptr)
return &RNA_SpaceNodeEditor;
case SPACE_LOGIC:
return &RNA_SpaceLogicEditor;*/
+ case SPACE_CONSOLE:
+ return &RNA_SpaceConsole;
default:
return &RNA_Space;
}
@@ -234,6 +239,46 @@ StructRNA *rna_SpaceButtonsWindow_pin_id_typef(PointerRNA *ptr)
return &RNA_ID;
}
+/* Space Console */
+static void rna_ConsoleLine_line_get(PointerRNA *ptr, char *value)
+{
+ ConsoleLine *ci= (ConsoleLine*)ptr->data;
+ strcpy(value, ci->line);
+}
+
+static int rna_ConsoleLine_line_length(PointerRNA *ptr)
+{
+ ConsoleLine *ci= (ConsoleLine*)ptr->data;
+ return ci->len;
+}
+
+static void rna_ConsoleLine_line_set(PointerRNA *ptr, const char *value)
+{
+ ConsoleLine *ci= (ConsoleLine*)ptr->data;
+ int len= strlen(value);
+
+ if(len < ci->len_alloc) { /* allocated size is enough? */
+ strcpy(ci->line, value);
+ }
+ else { /* allocate a new strnig */
+ MEM_freeN(ci->line);
+ ci->line= BLI_strdup(value);
+ ci->len_alloc= len;
+ }
+ ci->len= len;
+
+ if(ci->cursor > len) /* clamp the cursor */
+ ci->cursor= len;
+}
+
+static void rna_ConsoleLine_cursor_index_range(PointerRNA *ptr, int *min, int *max)
+{
+ ConsoleLine *ci= (ConsoleLine*)ptr->data;
+
+ *min= 0;
+ *max= ci->len;
+}
+
#else
static void rna_def_space(BlenderRNA *brna)
@@ -987,6 +1032,93 @@ static void rna_def_space_nla(BlenderRNA *brna)
// TODO... autosnap, dopesheet?
}
+static void rna_def_console_line(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ConsoleLine", NULL);
+ RNA_def_struct_ui_text(srna, "Console Input", "Input line for the interactive console.");
+
+ prop= RNA_def_property(srna, "line", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_ConsoleLine_line_get", "rna_ConsoleLine_line_length", "rna_ConsoleLine_line_set");
+ RNA_def_property_ui_text(prop, "Line", "Text in the line.");
+
+ prop= RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */
+ RNA_def_property_int_sdna(prop, NULL, "cursor");
+ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_ConsoleLine_cursor_index_range");
+
+}
+
+static EnumPropertyItem console_type_items[] = {
+ {CONSOLE_TYPE_PYTHON, "PYTHON", 0, "Python", ""},
+ {CONSOLE_TYPE_REPORT, "REPORT", 0, "Report", ""},
+ {0, NULL, 0, NULL, NULL}};
+
+static void rna_def_space_console(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "SpaceConsole", "Space");
+ RNA_def_struct_sdna(srna, "SpaceConsole");
+ RNA_def_struct_ui_text(srna, "Space Console", "Interactive python console.");
+
+ /* display */
+ prop= RNA_def_property(srna, "font_size", PROP_INT, PROP_NONE); /* copied from text editor */
+ RNA_def_property_int_sdna(prop, NULL, "lheight");
+ RNA_def_property_range(prop, 8, 32);
+ RNA_def_property_ui_text(prop, "Font Size", "Font size to use for displaying the text.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE, NULL);
+
+ prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, console_type_items);
+ RNA_def_property_ui_text(prop, "Type", "Console type.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE, NULL);
+
+ /* reporting display */
+ prop= RNA_def_property(srna, "show_report_debug", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", CONSOLE_RPT_DEBUG);
+ RNA_def_property_ui_text(prop, "Show Debug", "Display debug reporting info.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE_REPORT, NULL);
+
+ prop= RNA_def_property(srna, "show_report_info", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", CONSOLE_RPT_INFO);
+ RNA_def_property_ui_text(prop, "Show Info", "Display general information.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE_REPORT, NULL);
+
+ prop= RNA_def_property(srna, "show_report_operator", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", CONSOLE_RPT_OP);
+ RNA_def_property_ui_text(prop, "Show Operator", "Display the operator log.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE_REPORT, NULL);
+
+ prop= RNA_def_property(srna, "show_report_warn", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", CONSOLE_RPT_WARN);
+ RNA_def_property_ui_text(prop, "Show Warn", "Display warnings.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE_REPORT, NULL);
+
+ prop= RNA_def_property(srna, "show_report_error", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", CONSOLE_RPT_ERR);
+ RNA_def_property_ui_text(prop, "Show Error", "Display error text.");
+ RNA_def_property_update(prop, NC_CONSOLE | ND_CONSOLE_REPORT, NULL);
+
+
+
+ prop= RNA_def_property(srna, "prompt", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Prompt", "Command line prompt.");
+ RNA_def_struct_name_property(srna, prop);
+
+ prop= RNA_def_property(srna, "history", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "history", NULL);
+ RNA_def_property_struct_type(prop, "ConsoleLine");
+ RNA_def_property_ui_text(prop, "History", "Command history.");
+
+ prop= RNA_def_property(srna, "scrollback", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "scrollback", NULL);
+ RNA_def_property_struct_type(prop, "ConsoleLine");
+ RNA_def_property_ui_text(prop, "Output", "Command output.");
+}
+
static void rna_def_fileselect_params(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1127,6 +1259,8 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_space_dopesheet(brna);
rna_def_space_graph(brna);
rna_def_space_nla(brna);
+ rna_def_space_console(brna);
+ rna_def_console_line(brna);
}
#endif
diff --git a/source/blender/python/intern/bpy_ui.c b/source/blender/python/intern/bpy_ui.c
index 088fe436c69..64b8a33fd66 100644
--- a/source/blender/python/intern/bpy_ui.c
+++ b/source/blender/python/intern/bpy_ui.c
@@ -557,6 +557,7 @@ PyObject *BPY_ui_module( void )
PyModule_AddObject( mod, "SCRIPT", PyLong_FromSsize_t(SPACE_SCRIPT) );
PyModule_AddObject( mod, "TIME", PyLong_FromSsize_t(SPACE_TIME) );
PyModule_AddObject( mod, "NODE", PyLong_FromSsize_t(SPACE_NODE) );
+ PyModule_AddObject( mod, "CONSOLE", PyLong_FromSsize_t(SPACE_CONSOLE) );
/* INCREF since its its assumed that all these functions return the
* module with a new ref like PyDict_New, since they are passed to
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index ab55f8a4459..3a646c5e799 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -131,6 +131,7 @@ typedef struct wmNotifier {
#define NC_WORLD (13<<24)
#define NC_FILE (14<<24)
#define NC_ANIMATION (15<<24)
+#define NC_CONSOLE (16<<24)
/* data type, 256 entries is enough, it can overlap */
#define NOTE_DATA 0x00FF0000
@@ -200,6 +201,10 @@ typedef struct wmNotifier {
#define ND_NLA_EDIT (76<<16)
#define ND_NLA_ACTCHANGE (77<<16)
+ /* console */
+#define ND_CONSOLE (78<<16) /* general redraw */
+#define ND_CONSOLE_REPORT (79<<16) /* update for reports, could spesify type */
+
/* subtype, 256 entries too */
#define NOTE_SUBTYPE 0x0000FF00
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 7dec14664ae..6b3b128d34b 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -79,9 +79,11 @@ void WM_operator_free(wmOperator *op)
/* all operations get registered in the windowmanager here */
/* called on event handling by event_system.c */
-void wm_operator_register(wmWindowManager *wm, wmOperator *op)
+void wm_operator_register(bContext *C, wmOperator *op)
{
+ wmWindowManager *wm= CTX_wm_manager(C);
int tot;
+ char *buf;
BLI_addtail(&wm->operators, op);
tot= BLI_countlist(&wm->operators);
@@ -92,6 +94,15 @@ void wm_operator_register(wmWindowManager *wm, wmOperator *op)
WM_operator_free(opt);
tot--;
}
+
+
+ /* Report the string representation of the operator */
+ buf = WM_operator_pystring(op);
+ BKE_report(wm->reports, RPT_OPERATOR, buf);
+ MEM_freeN(buf);
+
+ /* so the console is redrawn */
+ WM_event_add_notifier(C, NC_CONSOLE|ND_CONSOLE_REPORT, NULL);
}
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 3ef6e545dda..ffd1054d954 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -268,7 +268,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat)
if(repeat==0) {
if(op->type->flag & OPTYPE_REGISTER)
- wm_operator_register(CTX_wm_manager(C), op);
+ wm_operator_register(C, op);
else
WM_operator_free(op);
}
@@ -374,7 +374,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
ED_undo_push_op(C, op);
if(ot->flag & OPTYPE_REGISTER)
- wm_operator_register(wm, op);
+ wm_operator_register(C, op);
else
WM_operator_free(op);
}
@@ -697,7 +697,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
ED_undo_push_op(C, op);
if(ot->flag & OPTYPE_REGISTER)
- wm_operator_register(CTX_wm_manager(C), op);
+ wm_operator_register(C, op);
else
WM_operator_free(op);
handler->op= NULL;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 0bc35ffa9b2..5938677afe7 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -51,6 +51,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_mball.h"
+#include "BKE_report.h"
#include "BKE_utildefines.h"
#include "BKE_packedFile.h"
@@ -100,6 +101,22 @@ static void sound_init_listener(void)
G.listener->dopplervelocity = 340.29f;
}
+
+static void wm_init_reports(bContext *C)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wm->reports= MEM_callocN(sizeof(ReportList), "wmReportList");
+ BKE_reports_init(wm->reports, RPT_STORE);
+}
+static void wm_free_reports(bContext *C)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ BKE_reports_clear(wm->reports);
+ MEM_freeN(wm->reports);
+}
+
+
+
/* only called once, for startup */
void WM_init(bContext *C)
{
@@ -124,6 +141,8 @@ void WM_init(bContext *C)
/* get the default database, plus a wm */
WM_read_homefile(C, NULL);
+ wm_init_reports(C); /* reports cant be initialized before the wm */
+
UI_init();
// clear_matcopybuf(); /* XXX */
@@ -256,6 +275,8 @@ void WM_exit(bContext *C)
RNA_exit();
+ wm_free_reports(C);
+
CTX_free(C);
if(MEM_get_memory_blocks_in_use()!=0) {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index d7cac82ef90..4dbe26bb79f 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -165,7 +165,7 @@ char *WM_operator_pystring(wmOperator *op)
char *cstring, *buf;
int first_iter=1;
- BLI_dynstr_appendf(dynstr, "%s(", op->idname);
+ BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", op->idname);
iterprop= RNA_struct_iterator_property(op->ptr->type);
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index e91cbe6b204..36219cf3743 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -47,7 +47,7 @@ extern void wm_check(bContext *C);
extern void wm_clear_default_size(bContext *C);
/* register to windowmanager for redo or macro */
-void wm_operator_register(wmWindowManager *wm, wmOperator *op);
+void wm_operator_register(bContext *C, wmOperator *op);
extern void wm_report_free(wmReport *report);