This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/space_text/text_python.c

554 lines
14 KiB
C

/*
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/space_text/text_python.c
* \ingroup sptext
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
#include "BKE_suggestions.h"
#include "BKE_text.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "WM_types.h"
#include "text_intern.h"
int text_do_suggest_select(SpaceText *st, ARegion *ar)
{
SuggItem *item, *first, *last /* , *sel */ /* UNUSED */;
TextLine *tmp;
int l, x, y, w, h, i;
int tgti, *top;
int mval[2] = {0, 0};
if (!st || !st->text) return 0;
if (!texttool_text_is_active(st->text)) return 0;
first = texttool_suggest_first();
last = texttool_suggest_last();
/* sel = texttool_suggest_selected(); */ /* UNUSED */
top = texttool_suggest_top();
if (!last || !first)
return 0;
/* Count the visible lines to the cursor */
for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ;
if (l < 0) return 0;
text_update_character_width(st);
if (st->showlinenrs) {
x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4;
}
else {
x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4;
}
y = ar->winy - st->lheight * l - 2;
w = SUGG_LIST_WIDTH * st->cwidth + 20;
h = SUGG_LIST_SIZE * st->lheight + 8;
// XXX getmouseco_areawin(mval);
if (mval[0] < x || x + w < mval[0] || mval[1] < y - h || y < mval[1])
return 0;
/* Work out which of the items is at the top of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
/* Work out the target item index in the visible list */
tgti = (y - mval[1] - 4) / st->lheight;
if (tgti < 0 || tgti > SUGG_LIST_SIZE)
return 1;
for (i = tgti; i > 0 && item->next; i--, item = item->next) ;
if (item)
texttool_suggest_select(item);
return 1;
}
void text_pop_suggest_list(void)
{
SuggItem *item, *sel;
int *top, i;
item = texttool_suggest_first();
sel = texttool_suggest_selected();
top = texttool_suggest_top();
i = 0;
while (item && item != sel) {
item = item->next;
i++;
}
if (i > *top + SUGG_LIST_SIZE - 1)
*top = i - SUGG_LIST_SIZE + 1;
else if (i < *top)
*top = i;
}
static void get_suggest_prefix(Text *text, int offset)
{
int i, len;
char *line, tmp[256];
if (!text) return;
if (!texttool_text_is_active(text)) return;
line = text->curl->line;
for (i = text->curc - 1 + offset; i >= 0; i--)
if (!text_check_identifier(line[i]))
break;
i++;
len = text->curc - i + offset;
if (len > 255) {
printf("Suggestion prefix too long\n");
len = 255;
}
BLI_strncpy(tmp, line + i, len);
tmp[len] = '\0';
texttool_suggest_prefix(tmp);
}
static void confirm_suggestion(Text *text, int skipleft)
{
SuggItem *sel;
int i, over = 0;
char *line;
if (!text) return;
if (!texttool_text_is_active(text)) return;
sel = texttool_suggest_selected();
if (!sel) return;
line = text->curl->line;
i = text->curc - skipleft - 1;
while (i >= 0) {
if (!text_check_identifier(line[i]))
break;
over++;
i--;
}
for (i = 0; i < skipleft; i++)
txt_move_left(text, 0);
for (i = 0; i < over; i++)
txt_move_left(text, 1);
txt_insert_buf(text, sel->name);
for (i = 0; i < skipleft; i++)
txt_move_right(text, 0);
texttool_text_clear();
}
// XXX
#define L_MOUSE 0
#define M_MOUSE 0
#define R_MOUSE 0
#define LR_SHIFTKEY 0
#define LR_ALTKEY 0
#define LR_CTRLKEY 0
#define LR_OSKEY 0
// XXX
static int doc_scroll = 0;
static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned short evnt, short val)
{
ARegion *ar = NULL; // XXX
int qual = 0; // XXX
int draw = 0, tools = 0, swallow = 0, scroll = 1;
if (!texttool_text_is_active(st->text)) return 0;
if (!st->text || st->text->id.lib) return 0;
if (st->doplugins && texttool_text_is_active(st->text)) {
if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST;
if (texttool_docs_get()) tools |= TOOL_DOCUMENT;
}
if (ascii) {
if (tools & TOOL_SUGG_LIST) {
if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) {
confirm_suggestion(st->text, 0);
text_update_line_edited(st->text->curl);
}
else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) {
get_suggest_prefix(st->text, 0);
text_pop_suggest_list();
swallow = 1;
draw = 1;
}
}
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
}
else if (val == 1 && evnt) {
switch (evnt) {
case LEFTMOUSE:
if (text_do_suggest_select(st, ar))
swallow = 1;
else {
if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
}
draw = 1;
break;
case MIDDLEMOUSE:
if (text_do_suggest_select(st, ar)) {
confirm_suggestion(st->text, 0);
text_update_line_edited(st->text->curl);
swallow = 1;
}
else {
if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
}
draw = 1;
break;
case ESCKEY:
draw = swallow = 1;
if (tools & TOOL_SUGG_LIST) texttool_suggest_clear();
else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
else draw = swallow = 0;
break;
case RETKEY:
if (tools & TOOL_SUGG_LIST) {
confirm_suggestion(st->text, 0);
text_update_line_edited(st->text->curl);
swallow = 1;
draw = 1;
}
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
break;
case LEFTARROWKEY:
case BACKSPACEKEY:
if (tools & TOOL_SUGG_LIST) {
if (qual)
texttool_suggest_clear();
else {
/* Work out which char we are about to delete/pass */
if (st->text->curl && st->text->curc > 0) {
char ch = st->text->curl->line[st->text->curc - 1];
if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
get_suggest_prefix(st->text, -1);
text_pop_suggest_list();
}
else
texttool_suggest_clear();
}
else
texttool_suggest_clear();
}
}
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
break;
case RIGHTARROWKEY:
if (tools & TOOL_SUGG_LIST) {
if (qual)
texttool_suggest_clear();
else {
/* Work out which char we are about to pass */
if (st->text->curl && st->text->curc < st->text->curl->len) {
char ch = st->text->curl->line[st->text->curc + 1];
if ((ch == '_' || !ispunct(ch)) && !text_check_whitespace(ch)) {
get_suggest_prefix(st->text, 1);
text_pop_suggest_list();
}
else
texttool_suggest_clear();
}
else
texttool_suggest_clear();
}
}
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0;
break;
case PAGEDOWNKEY:
scroll = SUGG_LIST_SIZE - 1;
case WHEELDOWNMOUSE:
case DOWNARROWKEY:
if (tools & TOOL_DOCUMENT) {
doc_scroll++;
swallow = 1;
draw = 1;
break;
}
else if (tools & TOOL_SUGG_LIST) {
SuggItem *sel = texttool_suggest_selected();
if (!sel) {
texttool_suggest_select(texttool_suggest_first());
}
else {
while (sel && sel != texttool_suggest_last() && sel->next && scroll--) {
texttool_suggest_select(sel->next);
sel = sel->next;
}
}
text_pop_suggest_list();
swallow = 1;
draw = 1;
break;
}
case PAGEUPKEY:
scroll = SUGG_LIST_SIZE - 1;
case WHEELUPMOUSE:
case UPARROWKEY:
if (tools & TOOL_DOCUMENT) {
if (doc_scroll > 0) doc_scroll--;
swallow = 1;
draw = 1;
break;
}
else if (tools & TOOL_SUGG_LIST) {
SuggItem *sel = texttool_suggest_selected();
while (sel && sel != texttool_suggest_first() && sel->prev && scroll--) {
texttool_suggest_select(sel->prev);
sel = sel->prev;
}
text_pop_suggest_list();
swallow = 1;
draw = 1;
break;
}
case RIGHTSHIFTKEY:
case LEFTSHIFTKEY:
break;
default:
if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw = 1;
if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll = 0, draw = 1;
}
}
if (draw) {
// XXX redraw_alltext();
}
return swallow;
}
#if 0
#ifdef WITH_PYTHON
/* Run text plugin scripts if enabled */
if (st->doplugins && event && val)
{
if (BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, qual)) {
do_draw = 1;
}
}
#endif
if (do_draw)
; // XXX redraw_alltext();
#endif
static short UNUSED_FUNCTION(do_textmarkers) (SpaceText * st, char ascii, unsigned short evnt, short val)
{
Text *text;
TextMarker *marker, *mrk, *nxt;
int c, s, draw = 0, swallow = 0;
int qual = 0; // XXX
text = st->text;
if (!text || text->id.lib || text->curl != text->sell) return 0;
marker = txt_find_marker(text, text->sell, text->selc, 0, 0);
if (marker && (marker->start > text->curc || marker->end < text->curc))
marker = NULL;
if (!marker) {
/* Find the next temporary marker */
if (evnt == TABKEY) {
int lineno = txt_get_span(text->lines.first, text->curl);
mrk = text->markers.first;
while (mrk) {
if (!marker && (mrk->flags & TMARK_TEMP)) marker = mrk;
if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) {
marker = mrk;
break;
}
mrk = mrk->next;
}
if (marker) {
txt_move_to(text, marker->lineno, marker->start, 0);
txt_move_to(text, marker->lineno, marker->end, 1);
// XXX text_update_cursor_moved(C);
// XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
evnt = ascii = val = 0;
draw = 1;
swallow = 1;
}
}
else if (evnt == ESCKEY) {
if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow = 1;
else if (txt_clear_markers(text, 0, 0)) swallow = 1;
else return 0;
evnt = ascii = val = 0;
draw = 1;
}
if (!swallow) return 0;
}
if (ascii) {
if (marker->flags & TMARK_EDITALL) {
c = text->curc - marker->start;
s = text->selc - marker->start;
if (s < 0 || s > marker->end - marker->start) return 0;
mrk = txt_next_marker(text, marker);
while (mrk) {
nxt = txt_next_marker(text, mrk); /* mrk may become invalid */
txt_move_to(text, mrk->lineno, mrk->start + c, 0);
if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1);
if (st->overwrite) {
if (txt_replace_char(text, ascii))
text_update_line_edited(st->text->curl);
}
else {
if (txt_add_char(text, ascii)) {
text_update_line_edited(st->text->curl);
}
}
if (mrk == marker || mrk == nxt) break;
mrk = nxt;
}
swallow = 1;
draw = 1;
}
}
else if (val) {
switch (evnt) {
case BACKSPACEKEY:
if (marker->flags & TMARK_EDITALL) {
c = text->curc - marker->start;
s = text->selc - marker->start;
if (s < 0 || s > marker->end - marker->start) return 0;
mrk = txt_next_marker(text, marker);
while (mrk) {
nxt = txt_next_marker(text, mrk); /* mrk may become invalid */
txt_move_to(text, mrk->lineno, mrk->start + c, 0);
if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1);
txt_backspace_char(text);
text_update_line_edited(st->text->curl);
if (mrk == marker || mrk == nxt) break;
mrk = nxt;
}
swallow = 1;
draw = 1;
}
break;
case DELKEY:
if (marker->flags & TMARK_EDITALL) {
c = text->curc - marker->start;
s = text->selc - marker->start;
if (s < 0 || s > marker->end - marker->start) return 0;
mrk = txt_next_marker(text, marker);
while (mrk) {
nxt = txt_next_marker(text, mrk); /* mrk may become invalid */
txt_move_to(text, mrk->lineno, mrk->start + c, 0);
if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1);
txt_delete_char(text);
text_update_line_edited(st->text->curl);
if (mrk == marker || mrk == nxt) break;
mrk = nxt;
}
swallow = 1;
draw = 1;
}
break;
case TABKEY:
if (qual & LR_SHIFTKEY) {
nxt = marker->prev;
if (!nxt) nxt = text->markers.last;
}
else {
nxt = marker->next;
if (!nxt) nxt = text->markers.first;
}
if (marker->flags & TMARK_TEMP) {
if (nxt == marker) nxt = NULL;
BLI_freelinkN(&text->markers, marker);
}
mrk = nxt;
if (mrk) {
txt_move_to(text, mrk->lineno, mrk->start, 0);
txt_move_to(text, mrk->lineno, mrk->end, 1);
// XXX text_update_cursor_moved(C);
// XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text);
}
swallow = 1;
draw = 1;
break;
/* Events that should clear markers */
case UKEY: if (!(qual & LR_ALTKEY)) break;
case ZKEY: if (evnt == ZKEY && !(qual & LR_CTRLKEY)) break;
case RETKEY:
case ESCKEY:
if (marker->flags & (TMARK_EDITALL | TMARK_TEMP))
txt_clear_markers(text, marker->group, 0);
else
BLI_freelinkN(&text->markers, marker);
swallow = 1;
draw = 1;
break;
case RIGHTMOUSE: /* Marker context menu? */
case LEFTMOUSE:
break;
case FKEY: /* Allow find */
if (qual & LR_SHIFTKEY) swallow = 1;
break;
default:
if (qual != 0 && qual != LR_SHIFTKEY)
swallow = 1; /* Swallow all other shortcut events */
}
}
if (draw) {
// XXX redraw_alltext();
}
return swallow;
}