Page Menu
Home
Search
Configure Global Search
Log In
Files
F2134
drawstdout.c
Public
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Authored By
Jacques Beaurain (jbinto)
Nov 13 2013, 1:02 PM
Size
25 KB
Subscribers
None
drawstdout.c
View Options
/**
* $Id: drawtext.c,v 1.58 2006/03/05 19:56:31 themyers Exp $
*
* ***** BEGIN GPL/BL DUAL 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. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* 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.
*
* This is a new part of Blender.
*
* Contributor(s): Jacques Beaurain
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include
<stdlib.h>
#include
<math.h>
#include
<string.h>
#include
<ctype.h>
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#ifndef _WIN32
#include
<unistd.h>
#else
#include
"BLI_winstuff.h"
#include
<stdio.h>
#include
<io.h>
#include
<fcntl.h>
#include
<malloc.h>
#include
<memory.h>
#include
<tchar.h>
#endif
#include
<pthread.h>
#include
"MEM_guardedalloc.h"
#include
"PIL_time.h"
#include
"BMF_Api.h"
#include
"BLI_blenlib.h"
#include
"BLI_arithb.h"
#include
"DNA_text_types.h"
#include
"DNA_space_types.h"
#include
"DNA_screen_types.h"
#include
"DNA_userdef_types.h"
#include
"BKE_utildefines.h"
#include
"BKE_stdout.h"
#include
"BKE_global.h"
#include
"BKE_main.h"
#include
"BKE_object.h"
#include
"BIF_gl.h"
#include
"BIF_keyval.h"
#include
"BIF_interface.h"
#include
"BIF_drawstdout.h"
#include
"BIF_editfont.h"
#include
"BIF_spacetypes.h"
#include
"BIF_usiblender.h"
#include
"BIF_screen.h"
#include
"BIF_toolbox.h"
#include
"BIF_space.h"
#include
"BIF_mywindow.h"
#include
"BIF_resources.h"
#include
"BSE_filesel.h"
#include
"BPY_extern.h"
#include
"mydevice.h"
#include
"blendef.h"
#define TEXTXLOC 38
/* forward declarations */
void
drawstdoutspace
(
ScrArea
*
sa
,
void
*
spacedata
);
void
winqreadstdoutspace
(
struct
ScrArea
*
sa
,
void
*
spacedata
,
struct
BWinEvent
*
evt
);
void
txt_copy_selectbuffer
(
Text
*
text
);
void
txt_copy_clipboard
(
Text
*
text
);
/* blank on non Win32 */
static
void
*
last_txt_find_string
=
NULL
;
#define INITIAL_BUFF 256
static
int
stdwin_on
=
0
;
static
struct
Text
*
stdout_text
=
NULL
;
static
pthread_mutex_t
_std_lock_out
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
_std_lock_err
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_t
stdout_thread
,
stderr_thread
;
#ifdef WIN32
static
HANDLE
houtread
,
houtwrite
,
herrread
,
herrwrite
;
static
int
cfdout
,
cfderr
;
static
FILE
*
fout
=
NULL
,
*
ferr
=
NULL
;
#else
static
int
outpipe
[
2
],
errpipe
[
2
];
static
FILE
*
fiout
=
NULL
,
*
fierr
=
NULL
;
#endif
static
char
*
poutbuf
=
NULL
,
*
perrbuf
=
NULL
;
static
int
outsize
,
errsize
;
static
int
outpos
,
errpos
;
static
void
ensurebuffsize
(
int
req_wrksize
,
int
*
wrksize
,
char
**
ppbuf
)
{
int
new_size
;
char
*
new_buff
;
if
(
*
wrksize
<
req_wrksize
)
{
new_size
=
(((
req_wrksize
>>
8
)
+
1
)
<<
8
);
new_buff
=
malloc
(
new_size
);
memcpy
(
new_buff
,
*
ppbuf
,
*
wrksize
);
free
(
*
ppbuf
);
*
wrksize
=
new_size
;
*
ppbuf
=
new_buff
;
}
}
static
void
std_lock_thread_out
()
{
pthread_mutex_lock
(
&
_std_lock_out
);
}
void
std_unlock_thread_out
()
{
pthread_mutex_unlock
(
&
_std_lock_out
);
}
static
void
std_lock_thread_err
()
{
pthread_mutex_lock
(
&
_std_lock_err
);
}
void
std_unlock_thread_err
()
{
pthread_mutex_unlock
(
&
_std_lock_err
);
}
static
void
*
stdout_readthread
(
void
*
pinfo
)
{
#ifdef WIN32
DWORD
dw
;
#else
int
iget
;
#endif
char
ch
;
for
(
;;
)
{
#ifdef WIN32
if
(
!
ReadFile
((
HANDLE
)
pinfo
,
&
ch
,
1
,
&
dw
,
NULL
)
||
dw
==
0
)
break
;
#else
pthread_testcancel
();
iget
=
getc
((
FILE
*
)
pinfo
);
pthread_testcancel
();
if
(
iget
==
EOF
)
break
;
ch
=
(
char
)
iget
;
#endif
std_lock_thread_out
();
ensurebuffsize
(
outpos
+
1
,
&
outsize
,
&
poutbuf
);
poutbuf
[
outpos
]
=
ch
;
outpos
++
;
std_unlock_thread_out
();
/* Redraw on newline characters */
if
(
G
.
curscreen
&&
!
G
.
background
&&
(
ch
==
0x0A
||
ch
==
0x0D
))
allqueue
(
REDRAWSTDOUT
,
0
);
}
return
0
;
}
static
void
*
stderr_readthread
(
void
*
pinfo
)
{
#ifdef WIN32
DWORD
dw
;
#else
int
iget
;
#endif
char
ch
;
for
(
;;
)
{
#ifdef WIN32
if
(
!
ReadFile
((
HANDLE
)
pinfo
,
&
ch
,
1
,
&
dw
,
NULL
)
||
dw
==
0
)
break
;
#else
pthread_testcancel
();
iget
=
getc
((
FILE
*
)
pinfo
);
pthread_testcancel
();
if
(
iget
==
EOF
)
break
;
ch
=
(
char
)
iget
;
#endif
std_lock_thread_err
();
ensurebuffsize
(
errpos
+
1
,
&
errsize
,
&
perrbuf
);
perrbuf
[
errpos
]
=
ch
;
errpos
++
;
std_unlock_thread_err
();
/* Redraw on newline characters */
if
(
G
.
curscreen
&&
!
G
.
background
&&
(
ch
==
0x0A
||
ch
==
0x0D
))
allqueue
(
REDRAWSTDOUT
,
0
);
}
return
0
;
}
int
stdout_ison
()
{
return
stdwin_on
;
}
void
redraw_stdout_now
()
{
if
(
stdout_ison
())
{
ScrArea
*
tempsa
,
*
sa
;
if
(
!
during_script
(
)
&&
!
G
.
background
)
{
tempsa
=
curarea
;
sa
=
G
.
curscreen
->
areabase
.
first
;
while
(
sa
)
{
if
(
sa
->
spacetype
==
SPACE_STDOUT
)
{
scrarea_do_windraw
(
sa
);
if
(
sa
->
headwin
)
scrarea_do_headdraw
(
sa
);
}
sa
=
sa
->
next
;
}
if
(
curarea
!=
tempsa
)
areawinset
(
tempsa
->
win
);
if
(
curarea
)
{
/* is null if Blender is in bg mode */
if
(
curarea
->
headwin
)
scrarea_do_headdraw
(
curarea
);
screen_swapbuffers
(
);
}
}
}
}
void
std_clear_text
()
{
if
(
stdout_text
)
free_text
(
stdout_text
);
stdout_text
=
add_empty_text
();
}
struct
Text
*
std_text
()
{
if
(
!
stdout_text
)
stdout_text
=
add_empty_text
();
return
stdout_text
;
}
void
stdout_gettext
(
SpaceStdOut
*
st
)
{
int
i
;
int
added
=
0
;
if
(
stdwin_on
)
{
int
oldstate
=
txt_get_undostate
(
);
txt_set_undostate
(
1
);
fflush
(
stdout
);
std_lock_thread_out
();
for
(
i
=
0
;
i
<
outpos
;
i
++
)
{
added
=
1
;
txt_move_eof
(
std_text
(),
0
);
txt_add_char
(
std_text
(),
poutbuf
[
i
]);
}
outpos
=
0
;
std_unlock_thread_out
();
fflush
(
stderr
);
std_lock_thread_err
();
for
(
i
=
0
;
i
<
errpos
;
i
++
)
{
added
=
1
;
txt_move_eof
(
std_text
(),
0
);
/* Indicate error lines */
if
(((
TextLine
*
)
std_text
()
->
lines
.
last
)
->
len
==
0
)
{
txt_add_char
(
std_text
(),
'e'
);
txt_add_char
(
std_text
(),
'r'
);
txt_add_char
(
std_text
(),
'r'
);
txt_add_char
(
std_text
(),
'o'
);
txt_add_char
(
std_text
(),
'r'
);
txt_add_char
(
std_text
(),
':'
);
txt_add_char
(
std_text
(),
' '
);
}
txt_add_char
(
std_text
(),
perrbuf
[
i
]);
}
if
(
added
)
pop_space_stdout
(
st
);
errpos
=
0
;
std_unlock_thread_err
();
txt_set_undostate
(
oldstate
);
}
}
void
init_stdthreads
(
int
stdwin
)
{
#ifdef WIN32
SECURITY_ATTRIBUTES
sa
;
#endif
stdwin_on
=
stdwin
;
if
(
stdwin_on
)
{
outpos
=
0
;
outsize
=
INITIAL_BUFF
;
poutbuf
=
malloc
(
INITIAL_BUFF
);
errpos
=
0
;
errsize
=
INITIAL_BUFF
;
perrbuf
=
malloc
(
INITIAL_BUFF
);
#ifdef WIN32
sa
.
nLength
=
sizeof
(
SECURITY_ATTRIBUTES
);
sa
.
bInheritHandle
=
TRUE
;
sa
.
lpSecurityDescriptor
=
NULL
;
CreatePipe
(
&
houtread
,
&
houtwrite
,
&
sa
,
0
);
SetStdHandle
(
STD_OUTPUT_HANDLE
,
houtwrite
);
CreatePipe
(
&
herrread
,
&
herrwrite
,
&
sa
,
0
);
SetStdHandle
(
STD_ERROR_HANDLE
,
herrwrite
);
cfdout
=
_open_osfhandle
((
long
)
houtwrite
,
_O_TEXT
);
cfderr
=
_open_osfhandle
((
long
)
herrwrite
,
_O_TEXT
);
fout
=
_fdopen
(
cfdout
,
"w"
);
*
stdout
=
*
fout
;
ferr
=
_fdopen
(
cfderr
,
"w"
);
*
stderr
=
*
ferr
;
/* turn off buffering */
setvbuf
(
stdout
,
NULL
,
_IONBF
,
0
);
setvbuf
(
stderr
,
NULL
,
_IONBF
,
0
);
pthread_create
(
&
stdout_thread
,
NULL
,
stdout_readthread
,
(
void
*
)
houtread
);
pthread_create
(
&
stderr_thread
,
NULL
,
stderr_readthread
,
(
void
*
)
herrread
);
FreeConsole
();
#else
pipe
(
outpipe
);
pipe
(
errpipe
);
/* turn off buffering */
setvbuf
(
stdout
,
NULL
,
_IONBF
,
0
);
setvbuf
(
stderr
,
NULL
,
_IONBF
,
0
);
dup2
(
outpipe
[
1
],
fileno
(
stdout
));
dup2
(
errpipe
[
1
],
fileno
(
stderr
));
fiout
=
fdopen
(
outpipe
[
0
],
"r"
);
fierr
=
fdopen
(
errpipe
[
0
],
"r"
);
pthread_create
(
&
stdout_thread
,
NULL
,
stdout_readthread
,
(
void
*
)
fiout
);
pthread_create
(
&
stderr_thread
,
NULL
,
stderr_readthread
,
(
void
*
)
fierr
);
#endif
}
}
void
shutdown_stdthreads
()
{
if
(
stdwin_on
)
{
#ifdef WIN32
/* On Windows the ReadFile call is non-blocking in this case.
Closing the handles will allow the threads to finish */
fclose
(
fout
);
fclose
(
ferr
);
CloseHandle
(
houtread
);
CloseHandle
(
herrread
);
pthread_join
(
stdout_thread
,
0
);
pthread_join
(
stderr_thread
,
0
);
#else
/* On POSIX systems the read call is blocking (getch uses read internally).
We have to cancel the threads here first otherwise we never get out of here. */
pthread_cancel
(
stdout_thread
);
pthread_cancel
(
stderr_thread
);
close
(
outpipe
[
1
]);
close
(
errpipe
[
1
]);
/* Don't fclose the handles, it hangs on Macs for some reason */
/* We are exiting anyway so dangling handles will not matter. */
#endif
free
(
poutbuf
);
free
(
perrbuf
);
}
}
static
BMF_Font
*
spacestdout_get_font
(
SpaceStdOut
*
st
)
{
static
BMF_Font
*
scr12
=
NULL
;
static
BMF_Font
*
scr15
=
NULL
;
switch
(
st
->
font_id
)
{
default
:
case
0
:
if
(
!
scr12
)
scr12
=
BMF_GetFont
(
BMF_kScreen12
);
return
scr12
;
case
1
:
if
(
!
scr15
)
scr15
=
BMF_GetFont
(
BMF_kScreen15
);
return
scr15
;
}
}
static
int
spacestdout_get_fontwidth
(
SpaceStdOut
*
st
)
{
return
BMF_GetCharacterWidth
(
spacestdout_get_font
(
st
),
' '
);
}
static
char
*
temp_char_buf
=
NULL
;
static
int
*
temp_char_accum
=
NULL
;
static
int
temp_char_len
=
0
;
static
int
temp_char_pos
=
0
;
static
void
temp_char_write
(
char
c
,
int
accum
)
{
if
(
temp_char_len
==
0
||
temp_char_pos
>=
temp_char_len
)
{
char
*
nbuf
;
int
*
naccum
;
int
olen
=
temp_char_len
;
if
(
olen
)
temp_char_len
*=
2
;
else
temp_char_len
=
256
;
nbuf
=
MEM_mallocN
(
sizeof
(
*
temp_char_buf
)
*
temp_char_len
,
"temp_char_buf"
);
naccum
=
MEM_mallocN
(
sizeof
(
*
temp_char_accum
)
*
temp_char_len
,
"temp_char_accum"
);
if
(
olen
)
{
memcpy
(
nbuf
,
temp_char_buf
,
olen
);
memcpy
(
naccum
,
temp_char_accum
,
olen
);
MEM_freeN
(
temp_char_buf
);
MEM_freeN
(
temp_char_accum
);
}
temp_char_buf
=
nbuf
;
temp_char_accum
=
naccum
;
}
temp_char_buf
[
temp_char_pos
]
=
c
;
temp_char_accum
[
temp_char_pos
]
=
accum
;
if
(
c
==
0
)
temp_char_pos
=
0
;
else
temp_char_pos
++
;
}
void
free_std_data
(
void
)
{
if
(
last_txt_find_string
)
MEM_freeN
(
last_txt_find_string
);
if
(
temp_char_buf
)
MEM_freeN
(
temp_char_buf
);
if
(
temp_char_accum
)
MEM_freeN
(
temp_char_accum
);
}
static
int
render_string
(
char
*
in
)
{
int
r
=
0
;
while
(
*
in
)
{
temp_char_write
(
*
in
,
r
);
r
++
;
in
++
;
}
r
=
temp_char_pos
;
temp_char_write
(
0
,
0
);
return
r
;
}
static
int
stdout_draw
(
SpaceStdOut
*
st
,
char
*
str
,
int
cshift
,
int
maxwidth
,
int
draw
,
int
x
,
int
y
,
char
*
format
)
{
int
r
=
0
,
w
=
0
;
char
*
in
;
int
*
acc
;
w
=
render_string
(
str
);
if
(
w
<
cshift
)
return
0
;
/* String is shorter than shift */
in
=
temp_char_buf
+
cshift
;
acc
=
temp_char_accum
+
cshift
;
w
=
w
-
cshift
;
if
(
draw
)
{
glRasterPos2i
(
x
,
y
);
BMF_DrawString
(
spacestdout_get_font
(
st
),
in
);
}
else
{
while
(
w
--
&&
*
acc
++
<
maxwidth
)
{
r
+=
spacestdout_get_fontwidth
(
st
);
}
}
if
(
cshift
&&
r
==
0
)
return
0
;
else
return
r
+
TXT_OFFSET
;
}
static
void
set_cursor_to_pos
(
SpaceStdOut
*
st
,
int
x
,
int
y
,
int
sel
)
{
Text
*
text
;
TextLine
**
linep
;
int
*
charp
;
int
w
;
text
=
std_text
();
if
(
sel
)
{
linep
=
&
text
->
sell
;
charp
=
&
text
->
selc
;
}
else
{
linep
=
&
text
->
curl
;
charp
=
&
text
->
curc
;
}
y
=
(
curarea
->
winy
-
y
)
/
st
->
lheight
;
y
-=
txt_get_span
(
text
->
lines
.
first
,
*
linep
)
-
st
->
top
;
if
(
y
>
0
)
{
while
(
y
--
!=
0
)
if
((
*
linep
)
->
next
)
*
linep
=
(
*
linep
)
->
next
;
}
else
if
(
y
<
0
)
{
while
(
y
++
!=
0
)
if
((
*
linep
)
->
prev
)
*
linep
=
(
*
linep
)
->
prev
;
}
x
-=
TXT_OFFSET
;
if
(
x
<
0
)
x
=
0
;
x
=
(
x
/
spacestdout_get_fontwidth
(
st
))
+
st
->
left
;
w
=
render_string
((
*
linep
)
->
line
);
if
(
x
<
w
)
*
charp
=
temp_char_accum
[
x
];
else
*
charp
=
(
*
linep
)
->
len
;
if
(
!
sel
)
txt_pop_sel
(
text
);
}
static
void
draw_cursor
(
SpaceStdOut
*
st
)
{
int
h
,
x
,
i
;
Text
*
text
=
std_text
();
TextLine
*
linef
,
*
linel
;
int
charf
,
charl
;
if
(
text
->
curl
==
text
->
sell
&&
text
->
curc
==
text
->
selc
)
{
x
=
stdout_draw
(
st
,
text
->
curl
->
line
,
st
->
left
,
text
->
curc
,
0
,
0
,
0
,
NULL
);
if
(
x
)
{
h
=
txt_get_span
(
text
->
lines
.
first
,
text
->
curl
)
-
st
->
top
;
BIF_ThemeColor
(
TH_HILITE
);
glRecti
(
x
-1
,
curarea
->
winy
-
st
->
lheight
*
(
h
)
-2
,
x
+
1
,
curarea
->
winy
-
st
->
lheight
*
(
h
+
1
)
-2
);
}
}
else
{
int
span
=
txt_get_span
(
text
->
curl
,
text
->
sell
);
if
(
span
<
0
)
{
linef
=
text
->
sell
;
charf
=
text
->
selc
;
linel
=
text
->
curl
;
charl
=
text
->
curc
;
}
else
if
(
span
>
0
)
{
linef
=
text
->
curl
;
charf
=
text
->
curc
;
linel
=
text
->
sell
;
charl
=
text
->
selc
;
}
else
{
linef
=
linel
=
text
->
curl
;
if
(
text
->
curc
<
text
->
selc
)
{
charf
=
text
->
curc
;
charl
=
text
->
selc
;
}
else
{
charf
=
text
->
selc
;
charl
=
text
->
curc
;
}
}
/* Walk to the beginning of visible text */
h
=
txt_get_span
(
text
->
lines
.
first
,
linef
)
-
st
->
top
;
while
(
h
++<
-1
&&
linef
!=
linel
)
linef
=
linef
->
next
;
x
=
stdout_draw
(
st
,
linef
->
line
,
st
->
left
,
charf
,
0
,
0
,
0
,
NULL
);
BIF_ThemeColor
(
TH_SHADE2
);
if
(
!
x
)
x
=
TXT_OFFSET
-
14
;
while
(
linef
&&
linef
!=
linel
)
{
h
=
txt_get_span
(
text
->
lines
.
first
,
linef
)
-
st
->
top
;
if
(
h
>
st
->
viewlines
)
break
;
glRecti
(
x
,
curarea
->
winy
-
st
->
lheight
*
(
h
)
-2
,
curarea
->
winx
,
curarea
->
winy
-
st
->
lheight
*
(
h
+
1
)
-2
);
glRecti
(
TXT_OFFSET
-4
,
curarea
->
winy
-
st
->
lheight
*
(
h
+
1
)
-2
,
TXT_OFFSET
,
curarea
->
winy
-
st
->
lheight
*
(
h
+
2
)
-2
);
x
=
TXT_OFFSET
;
linef
=
linef
->
next
;
}
h
=
txt_get_span
(
text
->
lines
.
first
,
linef
)
-
st
->
top
;
i
=
stdout_draw
(
st
,
linel
->
line
,
st
->
left
,
charl
,
0
,
0
,
0
,
NULL
);
if
(
i
)
glRecti
(
x
,
curarea
->
winy
-
st
->
lheight
*
(
h
)
-2
,
i
,
curarea
->
winy
-
st
->
lheight
*
(
h
+
1
)
-2
);
}
BIF_ThemeColor
(
TH_TEXT
);
}
static
void
calc_stdout_rcts
(
SpaceStdOut
*
st
)
{
short
barheight
,
barstart
;
int
lbarstart
,
lbarh
,
ltexth
;
lbarstart
=
st
->
top
;
lbarh
=
st
->
viewlines
;
ltexth
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
lines
.
last
)
+
1
;
barheight
=
(
lbarh
*
(
curarea
->
winy
-4
))
/
ltexth
;
if
(
barheight
<
20
)
barheight
=
20
;
barstart
=
(
lbarstart
*
(
curarea
->
winy
-4
))
/
ltexth
+
8
;
st
->
txtbar
.
xmin
=
5
;
st
->
txtbar
.
xmax
=
17
;
st
->
txtbar
.
ymax
=
curarea
->
winy
-
barstart
;
st
->
txtbar
.
ymin
=
st
->
txtbar
.
ymax
-
barheight
;
CLAMP
(
st
->
txtbar
.
ymin
,
2
,
curarea
->
winy
-2
);
CLAMP
(
st
->
txtbar
.
ymax
,
2
,
curarea
->
winy
-2
);
st
->
pix_per_line
=
(
float
)
ltexth
/
curarea
->
winy
;
if
(
st
->
pix_per_line
<
.1
)
st
->
pix_per_line
=
.1f
;
lbarstart
=
MIN2
(
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
curl
),
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
sell
));
lbarh
=
abs
(
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
curl
)
-
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
sell
));
barheight
=
(
lbarh
*
(
curarea
->
winy
-4
))
/
ltexth
;
if
(
barheight
<
2
)
barheight
=
2
;
barstart
=
(
lbarstart
*
(
curarea
->
winy
-4
))
/
ltexth
+
8
;
st
->
txtscroll
.
xmin
=
5
;
st
->
txtscroll
.
xmax
=
17
;
st
->
txtscroll
.
ymax
=
curarea
->
winy
-
barstart
;
st
->
txtscroll
.
ymin
=
st
->
txtscroll
.
ymax
-
barheight
;
CLAMP
(
st
->
txtscroll
.
ymin
,
2
,
curarea
->
winy
-2
);
CLAMP
(
st
->
txtscroll
.
ymax
,
2
,
curarea
->
winy
-2
);
}
static
void
draw_stdoutscroll
(
SpaceStdOut
*
st
)
{
calc_stdout_rcts
(
st
);
BIF_ThemeColorShade
(
TH_SHADE1
,
-20
);
glRecti
(
2
,
2
,
20
,
curarea
->
winy
-6
);
uiEmboss
(
2
,
2
,
20
,
curarea
->
winy
-6
,
1
);
BIF_ThemeColor
(
TH_SHADE1
);
glRecti
(
st
->
txtbar
.
xmin
,
st
->
txtbar
.
ymin
,
st
->
txtbar
.
xmax
,
st
->
txtbar
.
ymax
);
BIF_ThemeColor
(
TH_SHADE2
);
glRecti
(
st
->
txtscroll
.
xmin
,
st
->
txtscroll
.
ymin
,
st
->
txtscroll
.
xmax
,
st
->
txtscroll
.
ymax
);
uiEmboss
(
st
->
txtbar
.
xmin
,
st
->
txtbar
.
ymin
,
st
->
txtbar
.
xmax
,
st
->
txtbar
.
ymax
,
st
->
flags
&
ST_SCROLL_SELECT
);
}
static
void
screen_skip
(
SpaceStdOut
*
st
,
int
lines
)
{
int
last
;
if
(
!
st
)
return
;
if
(
st
->
spacetype
!=
SPACE_STDOUT
)
return
;
st
->
top
+=
lines
;
last
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
lines
.
last
);
last
=
last
-
(
st
->
viewlines
/
2
);
if
(
st
->
top
>
last
)
st
->
top
=
last
;
if
(
st
->
top
<
0
)
st
->
top
=
0
;
}
/*
* mode 1 == view scroll
* mode 2 == scrollbar
*/
static
void
do_stdoutscroll
(
SpaceStdOut
*
st
,
int
mode
)
{
short
delta
[
2
]
=
{
0
,
0
};
short
mval
[
2
],
hold
[
2
],
old
[
2
];
calc_stdout_rcts
(
st
);
st
->
flags
|=
ST_SCROLL_SELECT
;
glDrawBuffer
(
GL_FRONT
);
uiEmboss
(
st
->
txtbar
.
xmin
,
st
->
txtbar
.
ymin
,
st
->
txtbar
.
xmax
,
st
->
txtbar
.
ymax
,
st
->
flags
&
ST_SCROLL_SELECT
);
glDrawBuffer
(
GL_BACK
);
getmouseco_areawin
(
mval
);
old
[
0
]
=
hold
[
0
]
=
mval
[
0
];
old
[
1
]
=
hold
[
1
]
=
mval
[
1
];
while
(
get_mbut
()
&
(
L_MOUSE
|
M_MOUSE
))
{
getmouseco_areawin
(
mval
);
if
(
old
[
0
]
!=
mval
[
0
]
||
old
[
1
]
!=
mval
[
1
])
{
if
(
mode
==
1
)
{
delta
[
0
]
=
(
hold
[
0
]
-
mval
[
0
])
/
spacestdout_get_fontwidth
(
st
);
delta
[
1
]
=
(
mval
[
1
]
-
hold
[
1
])
/
st
->
lheight
;
}
else
delta
[
1
]
=
(
hold
[
1
]
-
mval
[
1
])
*
st
->
pix_per_line
;
if
(
delta
[
0
]
||
delta
[
1
])
{
screen_skip
(
st
,
delta
[
1
]);
st
->
left
+=
delta
[
0
];
if
(
st
->
left
<
0
)
st
->
left
=
0
;
scrarea_do_windraw
(
curarea
);
screen_swapbuffers
();
hold
[
0
]
=
mval
[
0
];
hold
[
1
]
=
mval
[
1
];
}
old
[
0
]
=
mval
[
0
];
old
[
1
]
=
mval
[
1
];
}
else
{
BIF_wait_for_statechange
();
}
}
st
->
flags
^=
ST_SCROLL_SELECT
;
glDrawBuffer
(
GL_FRONT
);
uiEmboss
(
st
->
txtbar
.
xmin
,
st
->
txtbar
.
ymin
,
st
->
txtbar
.
xmax
,
st
->
txtbar
.
ymax
,
st
->
flags
&
ST_SCROLL_SELECT
);
glDrawBuffer
(
GL_BACK
);
}
static
void
do_selection
(
SpaceStdOut
*
st
,
int
selecting
)
{
short
mval
[
2
],
old
[
2
];
int
sell
,
selc
;
int
linep2
,
charp2
;
int
first
=
1
;
getmouseco_areawin
(
mval
);
old
[
0
]
=
mval
[
0
];
old
[
1
]
=
mval
[
1
];
if
(
!
selecting
)
{
int
curl
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
curl
);
int
curc
=
std_text
()
->
curc
;
int
linep2
,
charp2
;
set_cursor_to_pos
(
st
,
mval
[
0
],
mval
[
1
],
0
);
linep2
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
curl
);
charp2
=
std_text
()
->
selc
;
if
(
curl
!=
linep2
||
curc
!=
charp2
)
txt_undo_add_toop
(
std_text
(),
UNDO_CTO
,
curl
,
curc
,
linep2
,
charp2
);
}
sell
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
sell
);
selc
=
std_text
()
->
selc
;
while
(
get_mbut
()
&
L_MOUSE
)
{
getmouseco_areawin
(
mval
);
if
(
mval
[
1
]
<
0
||
mval
[
1
]
>
curarea
->
winy
)
{
int
d
=
(
old
[
1
]
-
mval
[
1
])
*
st
->
pix_per_line
;
if
(
d
)
screen_skip
(
st
,
d
);
set_cursor_to_pos
(
st
,
mval
[
0
],
mval
[
1
]
<
0
?
0
:
curarea
->
winy
,
1
);
scrarea_do_windraw
(
curarea
);
screen_swapbuffers
();
}
else
if
(
mval
[
0
]
<
0
||
mval
[
0
]
>
curarea
->
winx
)
{
if
(
mval
[
0
]
>
curarea
->
winx
)
st
->
left
++
;
else
if
(
mval
[
0
]
<
0
&&
st
->
left
>
0
)
st
->
left
--
;
set_cursor_to_pos
(
st
,
mval
[
0
],
mval
[
1
],
1
);
scrarea_do_windraw
(
curarea
);
screen_swapbuffers
();
PIL_sleep_ms
(
10
);
}
else
if
(
first
||
old
[
0
]
!=
mval
[
0
]
||
old
[
1
]
!=
mval
[
1
])
{
set_cursor_to_pos
(
st
,
mval
[
0
],
mval
[
1
],
1
);
scrarea_do_windraw
(
curarea
);
screen_swapbuffers
();
old
[
0
]
=
mval
[
0
];
old
[
1
]
=
mval
[
1
];
first
=
1
;
}
else
{
BIF_wait_for_statechange
();
}
}
linep2
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
sell
);
charp2
=
std_text
()
->
selc
;
if
(
sell
!=
linep2
||
selc
!=
charp2
)
txt_undo_add_toop
(
std_text
(),
UNDO_STO
,
sell
,
selc
,
linep2
,
charp2
);
}
void
drawstdoutspace
(
ScrArea
*
sa
,
void
*
spacedata
)
{
SpaceStdOut
*
st
=
curarea
->
spacedata
.
first
;
Text
*
text
;
int
i
;
TextLine
*
tmp
;
float
col
[
3
];
int
linecount
=
0
;
BIF_GetThemeColor3fv
(
TH_BACK
,
col
);
glClearColor
(
col
[
0
],
col
[
1
],
col
[
2
],
0.0
);
glClear
(
GL_COLOR_BUFFER_BIT
);
myortho2
(
-0.375
,
(
float
)(
sa
->
winx
)
-0.375
,
-0.375
,
(
float
)(
sa
->
winy
)
-0.375
);
draw_area_emboss
(
sa
);
if
(
st
->
lheight
)
st
->
viewlines
=
(
int
)
curarea
->
winy
/
st
->
lheight
;
else
st
->
viewlines
=
0
;
stdout_gettext
(
st
);
text
=
std_text
();
/* Make sure all the positional pointers exist */
if
(
!
text
->
curl
||
!
text
->
sell
||
!
text
->
lines
.
first
||
!
text
->
lines
.
last
)
txt_clean_text
(
text
);
BIF_ThemeColor
(
TH_TEXT
);
draw_cursor
(
st
);
tmp
=
text
->
lines
.
first
;
for
(
i
=
0
;
i
<
st
->
top
&&
tmp
;
i
++
)
{
tmp
=
tmp
->
next
;
linecount
++
;
}
for
(
i
=
0
;
i
<
st
->
viewlines
&&
tmp
;
i
++
,
tmp
=
tmp
->
next
)
{
if
(
strncmp
(
tmp
->
line
,
"error: "
,
7
)
!=
0
)
BIF_ThemeColor
(
TH_TEXT
);
else
BIF_ThemeColor
(
TH_SYNTAX_B
);
stdout_draw
(
st
,
tmp
->
line
,
st
->
left
,
0
,
1
,
TXT_OFFSET
,
curarea
->
winy
-
st
->
lheight
*
(
i
+
1
),
tmp
->
format
);
}
draw_stdoutscroll
(
st
);
curarea
->
win_swap
=
WIN_BACK_OK
;
}
void
pop_space_stdout
(
SpaceStdOut
*
st
)
{
int
i
,
x
;
if
(
!
st
)
return
;
if
(
!
std_text
()
->
curl
)
return
;
i
=
txt_get_span
(
std_text
()
->
lines
.
first
,
std_text
()
->
curl
);
if
(
st
->
top
+
st
->
viewlines
<=
i
||
st
->
top
>
i
)
{
st
->
top
=
i
-
st
->
viewlines
/
2
;
}
x
=
stdout_draw
(
st
,
std_text
()
->
curl
->
line
,
st
->
left
,
std_text
()
->
curc
,
0
,
0
,
0
,
NULL
);
if
(
x
==
0
||
x
>
curarea
->
winx
)
{
st
->
left
=
std_text
()
->
curc
-0.5
*
(
curarea
->
winx
)
/
spacestdout_get_fontwidth
(
st
);
}
if
(
st
->
top
<
0
)
st
->
top
=
0
;
if
(
st
->
left
<
0
)
st
->
left
=
0
;
}
void
free_stdoutspace
(
SpaceStdOut
*
st
)
{
if
(
!
st
)
return
;
stdout_text
=
NULL
;
}
/*
* again==0 show find panel or find
* again==1 find text again */
void
std_find_panel
(
SpaceStdOut
*
st
,
int
again
)
{
Text
*
text
=
std_text
();
char
*
findstr
=
last_txt_find_string
;
if
(
again
==
0
)
{
findstr
=
txt_sel_to_buf
(
text
);
}
else
if
(
again
==
1
)
{
char
buf
[
256
];
if
(
findstr
&&
strlen
(
findstr
)
<
(
sizeof
(
buf
)
-1
))
strcpy
(
buf
,
findstr
);
else
buf
[
0
]
=
0
;
if
(
sbutton
(
buf
,
0
,
sizeof
(
buf
)
-1
,
"Find: "
)
&&
buf
[
0
])
findstr
=
BLI_strdup
(
buf
);
else
findstr
=
NULL
;
}
if
(
findstr
!=
last_txt_find_string
)
{
if
(
last_txt_find_string
)
MEM_freeN
(
last_txt_find_string
);
last_txt_find_string
=
findstr
;
}
if
(
findstr
)
{
if
(
txt_find_string
(
text
,
findstr
))
pop_space_stdout
(
st
);
else
error
(
"Not found: %s"
,
findstr
);
}
}
static
void
set_tabs
(
Text
*
text
)
{
SpaceText
*
st
=
curarea
->
spacedata
.
first
;
st
->
currtab_set
=
setcurr_tab
(
text
);
}
void
winqreadstdoutspace
(
ScrArea
*
sa
,
void
*
spacedata
,
BWinEvent
*
evt
)
{
unsigned
short
event
=
evt
->
event
;
short
val
=
evt
->
val
;
char
ascii
=
evt
->
ascii
;
SpaceStdOut
*
st
=
curarea
->
spacedata
.
first
;
Text
*
text
=
std_text
();
int
do_draw
=
0
,
p
;
/* smartass code to prevent the CTRL/ALT events below from not working! */
if
(
!
ispunct
(
ascii
))
if
(
!
isprint
(
ascii
)
||
(
G
.
qual
&
~
LR_SHIFTKEY
))
ascii
=
0
;
if
(
event
==
LEFTMOUSE
)
{
if
(
val
)
{
short
mval
[
2
];
set_tabs
(
text
);
getmouseco_areawin
(
mval
);
if
(
mval
[
0
]
>
2
&&
mval
[
0
]
<
20
&&
mval
[
1
]
>
2
&&
mval
[
1
]
<
curarea
->
winy
-2
)
{
do_stdoutscroll
(
st
,
2
);
}
else
{
do_selection
(
st
,
G
.
qual
&
LR_SHIFTKEY
);
do_draw
=
1
;
}
}
}
else
if
(
event
==
MIDDLEMOUSE
)
{
if
(
val
)
{
do_stdoutscroll
(
st
,
1
);
}
}
else
if
(
val
)
{
switch
(
event
)
{
case
AKEY
:
if
(
G
.
qual
&
LR_ALTKEY
)
{
txt_move_bol
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
do_draw
=
1
;
pop_space_stdout
(
st
);
}
else
if
(
G
.
qual
&
LR_CTRLKEY
)
{
txt_sel_all
(
text
);
do_draw
=
1
;
}
break
;
/* BREAK A */
case
CKEY
:
if
(
G
.
qual
&
LR_ALTKEY
||
G
.
qual
&
LR_CTRLKEY
)
{
if
(
G
.
qual
&
LR_SHIFTKEY
)
txt_copy_clipboard
(
text
);
else
txt_copy_sel
(
text
);
do_draw
=
1
;
}
break
;
/* BREAK C */
case
EKEY
:
if
(
G
.
qual
==
(
LR_ALTKEY
|
LR_SHIFTKEY
))
{
switch
(
pupmenu
(
"Edit %t|Copy %x1"
))
{
case
0
:
txt_copy_sel
(
text
);
do_draw
=
1
;
break
;
}
}
else
if
(
G
.
qual
==
LR_CTRLKEY
||
G
.
qual
==
(
LR_CTRLKEY
|
LR_SHIFTKEY
))
{
txt_move_eol
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
do_draw
=
1
;
pop_space_stdout
(
st
);
}
break
;
/* BREAK E */
case
FKEY
:
if
(
G
.
qual
==
LR_ALTKEY
)
{
if
(
txt_has_sel
(
text
))
{
std_find_panel
(
st
,
0
);
do_draw
=
1
;
}
}
else
if
(
G
.
qual
==
(
LR_ALTKEY
|
LR_CTRLKEY
))
{
/* always search button */
std_find_panel
(
st
,
1
);
do_draw
=
1
;
}
break
;
/* BREAK F */
case
QKEY
:
if
(
okee
(
"Quit Blender"
))
exit_usiblender
();
break
;
/* BREAK Q */
case
SKEY
:
if
(
G
.
qual
==
(
LR_ALTKEY
|
LR_SHIFTKEY
))
{
p
=
pupmenu
(
"Select %t|"
"Select All %x0|"
"Select Line %x1"
);
switch
(
p
)
{
case
0
:
txt_sel_all
(
text
);
do_draw
=
1
;
break
;
case
1
:
txt_sel_line
(
text
);
do_draw
=
1
;
break
;
}
}
break
;
/* BREAK S */
case
VKEY
:
if
(
G
.
qual
==
(
LR_ALTKEY
|
LR_SHIFTKEY
))
{
switch
(
pupmenu
(
"View %t|Top of Output %x0|Bottom of Output %x1|Page Up %x2|Page Down %x3"
))
{
case
0
:
txt_move_bof
(
text
,
0
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
1
:
txt_move_eof
(
text
,
0
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
2
:
screen_skip
(
st
,
-
st
->
viewlines
);
do_draw
=
1
;
break
;
case
3
:
screen_skip
(
st
,
st
->
viewlines
);
do_draw
=
1
;
break
;
}
}
break
;
/* BREAK V */
case
DOWNARROWKEY
:
txt_move_down
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
set_tabs
(
text
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
LEFTARROWKEY
:
txt_move_left
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
set_tabs
(
text
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
RIGHTARROWKEY
:
txt_move_right
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
set_tabs
(
text
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
UPARROWKEY
:
txt_move_up
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
set_tabs
(
text
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
PAGEDOWNKEY
:
screen_skip
(
st
,
st
->
viewlines
);
do_draw
=
1
;
break
;
case
PAGEUPKEY
:
screen_skip
(
st
,
-
st
->
viewlines
);
do_draw
=
1
;
break
;
case
HOMEKEY
:
txt_move_bol
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
ENDKEY
:
txt_move_eol
(
text
,
G
.
qual
&
LR_SHIFTKEY
);
do_draw
=
1
;
pop_space_stdout
(
st
);
break
;
case
WHEELUPMOUSE
:
screen_skip
(
st
,
-
U
.
wheellinescroll
);
do_draw
=
1
;
break
;
case
WHEELDOWNMOUSE
:
screen_skip
(
st
,
U
.
wheellinescroll
);
do_draw
=
1
;
break
;
}
}
if
(
do_draw
)
{
ScrArea
*
sa
;
for
(
sa
=
G
.
curscreen
->
areabase
.
first
;
sa
;
sa
=
sa
->
next
)
{
SpaceStdOut
*
st
=
sa
->
spacedata
.
first
;
if
(
st
&&
st
->
spacetype
==
SPACE_STDOUT
)
{
scrarea_queue_redraw
(
sa
);
}
}
}
}
File Metadata
Details
Mime Type
text/x-c
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
a0/b2/cd2e137babc520103db5ae47a549
Event Timeline
Log In to Comment