|
Blender
V2.59
|
00001 /* 00002 * $Id: text_python.c 36644 2011-05-12 16:47:36Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * 00024 * Contributor(s): Blender Foundation 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <ctype.h> 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 00038 #include "DNA_screen_types.h" 00039 #include "DNA_space_types.h" 00040 #include "DNA_text_types.h" 00041 00042 #include "BKE_suggestions.h" 00043 #include "BKE_text.h" 00044 00045 #include "BLI_blenlib.h" 00046 00047 #include "WM_types.h" 00048 00049 #include "text_intern.h" 00050 00051 int text_do_suggest_select(SpaceText *st, ARegion *ar) 00052 { 00053 SuggItem *item, *first, *last, *sel; 00054 TextLine *tmp; 00055 int l, x, y, w, h, i; 00056 int tgti, *top; 00057 int mval[2] = {0, 0}; 00058 00059 if(!st || !st->text) return 0; 00060 if(!texttool_text_is_active(st->text)) return 0; 00061 00062 first = texttool_suggest_first(); 00063 last = texttool_suggest_last(); 00064 sel = texttool_suggest_selected(); 00065 top = texttool_suggest_top(); 00066 00067 if(!last || !first) 00068 return 0; 00069 00070 /* Count the visible lines to the cursor */ 00071 for(tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); 00072 if(l<0) return 0; 00073 00074 text_update_character_width(st); 00075 00076 if(st->showlinenrs) { 00077 x = st->cwidth*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; 00078 } 00079 else { 00080 x = st->cwidth*(st->text->curc-st->left) + TXT_OFFSET - 4; 00081 } 00082 y = ar->winy - st->lheight*l - 2; 00083 00084 w = SUGG_LIST_WIDTH*st->cwidth + 20; 00085 h = SUGG_LIST_SIZE*st->lheight + 8; 00086 00087 // XXX getmouseco_areawin(mval); 00088 00089 if(mval[0]<x || x+w<mval[0] || mval[1]<y-h || y<mval[1]) 00090 return 0; 00091 00092 /* Work out which of the items is at the top of the visible list */ 00093 for(i=0, item=first; i<*top && item->next; i++, item=item->next); 00094 00095 /* Work out the target item index in the visible list */ 00096 tgti = (y-mval[1]-4) / st->lheight; 00097 if(tgti<0 || tgti>SUGG_LIST_SIZE) 00098 return 1; 00099 00100 for(i=tgti; i>0 && item->next; i--, item=item->next); 00101 if(item) 00102 texttool_suggest_select(item); 00103 return 1; 00104 } 00105 00106 void text_pop_suggest_list(void) 00107 { 00108 SuggItem *item, *sel; 00109 int *top, i; 00110 00111 item= texttool_suggest_first(); 00112 sel= texttool_suggest_selected(); 00113 top= texttool_suggest_top(); 00114 00115 i= 0; 00116 while(item && item != sel) { 00117 item= item->next; 00118 i++; 00119 } 00120 if(i > *top+SUGG_LIST_SIZE-1) 00121 *top= i-SUGG_LIST_SIZE+1; 00122 else if(i < *top) 00123 *top= i; 00124 } 00125 00126 static void get_suggest_prefix(Text *text, int offset) 00127 { 00128 int i, len; 00129 char *line, tmp[256]; 00130 00131 if(!text) return; 00132 if(!texttool_text_is_active(text)) return; 00133 00134 line= text->curl->line; 00135 for(i=text->curc-1+offset; i>=0; i--) 00136 if(!text_check_identifier(line[i])) 00137 break; 00138 i++; 00139 len= text->curc-i+offset; 00140 if(len > 255) { 00141 printf("Suggestion prefix too long\n"); 00142 len = 255; 00143 } 00144 BLI_strncpy(tmp, line+i, len); 00145 tmp[len]= '\0'; 00146 texttool_suggest_prefix(tmp); 00147 } 00148 00149 static void confirm_suggestion(Text *text, int skipleft) 00150 { 00151 SuggItem *sel; 00152 int i, over=0; 00153 char *line; 00154 00155 if(!text) return; 00156 if(!texttool_text_is_active(text)) return; 00157 00158 sel = texttool_suggest_selected(); 00159 if(!sel) return; 00160 00161 line= text->curl->line; 00162 i=text->curc-skipleft-1; 00163 while(i>=0) { 00164 if(!text_check_identifier(line[i])) 00165 break; 00166 over++; 00167 i--; 00168 } 00169 00170 for(i=0; i<skipleft; i++) 00171 txt_move_left(text, 0); 00172 for(i=0; i<over; i++) 00173 txt_move_left(text, 1); 00174 00175 txt_insert_buf(text, sel->name); 00176 00177 for(i=0; i<skipleft; i++) 00178 txt_move_right(text, 0); 00179 00180 texttool_text_clear(); 00181 } 00182 00183 // XXX 00184 #define L_MOUSE 0 00185 #define M_MOUSE 0 00186 #define R_MOUSE 0 00187 #define LR_SHIFTKEY 0 00188 #define LR_ALTKEY 0 00189 #define LR_CTRLKEY 0 00190 #define LR_OSKEY 0 00191 00192 // XXX 00193 static int doc_scroll= 0; 00194 00195 static short do_texttools(SpaceText *st, char ascii, unsigned short evnt, short val) 00196 { 00197 ARegion *ar= NULL; // XXX 00198 int qual= 0; // XXX 00199 int draw=0, tools=0, swallow=0, scroll=1; 00200 if(!texttool_text_is_active(st->text)) return 0; 00201 if(!st->text || st->text->id.lib) return 0; 00202 00203 if(st->doplugins && texttool_text_is_active(st->text)) { 00204 if(texttool_suggest_first()) tools |= TOOL_SUGG_LIST; 00205 if(texttool_docs_get()) tools |= TOOL_DOCUMENT; 00206 } 00207 00208 if(ascii) { 00209 if(tools & TOOL_SUGG_LIST) { 00210 if((ascii != '_' && ascii != '*' && ispunct(ascii)) || text_check_whitespace(ascii)) { 00211 confirm_suggestion(st->text, 0); 00212 text_update_line_edited(st->text->curl); 00213 } 00214 else if((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { 00215 get_suggest_prefix(st->text, 0); 00216 text_pop_suggest_list(); 00217 swallow= 1; 00218 draw= 1; 00219 } 00220 } 00221 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; 00222 00223 } 00224 else if(val==1 && evnt) { 00225 switch (evnt) { 00226 case LEFTMOUSE: 00227 if(text_do_suggest_select(st, ar)) 00228 swallow= 1; 00229 else { 00230 if(tools & TOOL_SUGG_LIST) texttool_suggest_clear(); 00231 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; 00232 } 00233 draw= 1; 00234 break; 00235 case MIDDLEMOUSE: 00236 if(text_do_suggest_select(st, ar)) { 00237 confirm_suggestion(st->text, 0); 00238 text_update_line_edited(st->text->curl); 00239 swallow= 1; 00240 } 00241 else { 00242 if(tools & TOOL_SUGG_LIST) texttool_suggest_clear(); 00243 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; 00244 } 00245 draw= 1; 00246 break; 00247 case ESCKEY: 00248 draw= swallow= 1; 00249 if(tools & TOOL_SUGG_LIST) texttool_suggest_clear(); 00250 else if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; 00251 else draw= swallow= 0; 00252 break; 00253 case RETKEY: 00254 if(tools & TOOL_SUGG_LIST) { 00255 confirm_suggestion(st->text, 0); 00256 text_update_line_edited(st->text->curl); 00257 swallow= 1; 00258 draw= 1; 00259 } 00260 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; 00261 break; 00262 case LEFTARROWKEY: 00263 case BACKSPACEKEY: 00264 if(tools & TOOL_SUGG_LIST) { 00265 if(qual) 00266 texttool_suggest_clear(); 00267 else { 00268 /* Work out which char we are about to delete/pass */ 00269 if(st->text->curl && st->text->curc > 0) { 00270 char ch= st->text->curl->line[st->text->curc-1]; 00271 if((ch=='_' || !ispunct(ch)) && !text_check_whitespace(ch)) { 00272 get_suggest_prefix(st->text, -1); 00273 text_pop_suggest_list(); 00274 } 00275 else 00276 texttool_suggest_clear(); 00277 } 00278 else 00279 texttool_suggest_clear(); 00280 } 00281 } 00282 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; 00283 break; 00284 case RIGHTARROWKEY: 00285 if(tools & TOOL_SUGG_LIST) { 00286 if(qual) 00287 texttool_suggest_clear(); 00288 else { 00289 /* Work out which char we are about to pass */ 00290 if(st->text->curl && st->text->curc < st->text->curl->len) { 00291 char ch= st->text->curl->line[st->text->curc+1]; 00292 if((ch=='_' || !ispunct(ch)) && !text_check_whitespace(ch)) { 00293 get_suggest_prefix(st->text, 1); 00294 text_pop_suggest_list(); 00295 } 00296 else 00297 texttool_suggest_clear(); 00298 } 00299 else 00300 texttool_suggest_clear(); 00301 } 00302 } 00303 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; 00304 break; 00305 case PAGEDOWNKEY: 00306 scroll= SUGG_LIST_SIZE-1; 00307 case WHEELDOWNMOUSE: 00308 case DOWNARROWKEY: 00309 if(tools & TOOL_DOCUMENT) { 00310 doc_scroll++; 00311 swallow= 1; 00312 draw= 1; 00313 break; 00314 } 00315 else if(tools & TOOL_SUGG_LIST) { 00316 SuggItem *sel = texttool_suggest_selected(); 00317 if(!sel) { 00318 texttool_suggest_select(texttool_suggest_first()); 00319 } 00320 else while(sel && sel!=texttool_suggest_last() && sel->next && scroll--) { 00321 texttool_suggest_select(sel->next); 00322 sel= sel->next; 00323 } 00324 text_pop_suggest_list(); 00325 swallow= 1; 00326 draw= 1; 00327 break; 00328 } 00329 case PAGEUPKEY: 00330 scroll= SUGG_LIST_SIZE-1; 00331 case WHEELUPMOUSE: 00332 case UPARROWKEY: 00333 if(tools & TOOL_DOCUMENT) { 00334 if(doc_scroll>0) doc_scroll--; 00335 swallow= 1; 00336 draw= 1; 00337 break; 00338 } 00339 else if(tools & TOOL_SUGG_LIST) { 00340 SuggItem *sel = texttool_suggest_selected(); 00341 while(sel && sel!=texttool_suggest_first() && sel->prev && scroll--) { 00342 texttool_suggest_select(sel->prev); 00343 sel= sel->prev; 00344 } 00345 text_pop_suggest_list(); 00346 swallow= 1; 00347 draw= 1; 00348 break; 00349 } 00350 case RIGHTSHIFTKEY: 00351 case LEFTSHIFTKEY: 00352 break; 00353 default: 00354 if(tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw= 1; 00355 if(tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; 00356 } 00357 } 00358 00359 if(draw) 00360 {}; // XXX redraw_alltext(); 00361 00362 return swallow; 00363 } 00364 00365 #if 0 00366 #ifdef WITH_PYTHON 00367 /* Run text plugin scripts if enabled */ 00368 if(st->doplugins && event && val) { 00369 if(BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, qual)) { 00370 do_draw= 1; 00371 } 00372 } 00373 #endif 00374 if(do_draw) 00375 ; // XXX redraw_alltext(); 00376 #endif 00377 00378 static short do_textmarkers(SpaceText *st, char ascii, unsigned short evnt, short val) 00379 { 00380 Text *text; 00381 TextMarker *marker, *mrk, *nxt; 00382 int c, s, draw=0, swallow=0; 00383 int qual= 0; // XXX 00384 00385 text= st->text; 00386 if(!text || text->id.lib || text->curl != text->sell) return 0; 00387 00388 marker= txt_find_marker(text, text->sell, text->selc, 0, 0); 00389 if(marker && (marker->start > text->curc || marker->end < text->curc)) 00390 marker= NULL; 00391 00392 if(!marker) { 00393 /* Find the next temporary marker */ 00394 if(evnt==TABKEY) { 00395 int lineno= txt_get_span(text->lines.first, text->curl); 00396 mrk= text->markers.first; 00397 while(mrk) { 00398 if(!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; 00399 if((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { 00400 marker= mrk; 00401 break; 00402 } 00403 mrk= mrk->next; 00404 } 00405 if(marker) { 00406 txt_move_to(text, marker->lineno, marker->start, 0); 00407 txt_move_to(text, marker->lineno, marker->end, 1); 00408 // XXX text_update_cursor_moved(C); 00409 // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); 00410 evnt= ascii= val= 0; 00411 draw= 1; 00412 swallow= 1; 00413 } 00414 } 00415 else if(evnt==ESCKEY) { 00416 if(txt_clear_markers(text, 0, TMARK_TEMP)) swallow= 1; 00417 else if(txt_clear_markers(text, 0, 0)) swallow= 1; 00418 else return 0; 00419 evnt= ascii= val= 0; 00420 draw= 1; 00421 } 00422 if(!swallow) return 0; 00423 } 00424 00425 if(ascii) { 00426 if(marker->flags & TMARK_EDITALL) { 00427 c= text->curc-marker->start; 00428 s= text->selc-marker->start; 00429 if(s<0 || s>marker->end-marker->start) return 0; 00430 00431 mrk= txt_next_marker(text, marker); 00432 while(mrk) { 00433 nxt=txt_next_marker(text, mrk); /* mrk may become invalid */ 00434 txt_move_to(text, mrk->lineno, mrk->start+c, 0); 00435 if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); 00436 if(st->overwrite) { 00437 if(txt_replace_char(text, ascii)) 00438 text_update_line_edited(st->text->curl); 00439 } 00440 else { 00441 if(txt_add_char(text, ascii)) { 00442 text_update_line_edited(st->text->curl); 00443 } 00444 } 00445 00446 if(mrk==marker || mrk==nxt) break; 00447 mrk=nxt; 00448 } 00449 swallow= 1; 00450 draw= 1; 00451 } 00452 } 00453 else if(val) { 00454 switch(evnt) { 00455 case BACKSPACEKEY: 00456 if(marker->flags & TMARK_EDITALL) { 00457 c= text->curc-marker->start; 00458 s= text->selc-marker->start; 00459 if(s<0 || s>marker->end-marker->start) return 0; 00460 00461 mrk= txt_next_marker(text, marker); 00462 while(mrk) { 00463 nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ 00464 txt_move_to(text, mrk->lineno, mrk->start+c, 0); 00465 if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); 00466 txt_backspace_char(text); 00467 text_update_line_edited(st->text->curl); 00468 if(mrk==marker || mrk==nxt) break; 00469 mrk= nxt; 00470 } 00471 swallow= 1; 00472 draw= 1; 00473 } 00474 break; 00475 case DELKEY: 00476 if(marker->flags & TMARK_EDITALL) { 00477 c= text->curc-marker->start; 00478 s= text->selc-marker->start; 00479 if(s<0 || s>marker->end-marker->start) return 0; 00480 00481 mrk= txt_next_marker(text, marker); 00482 while(mrk) { 00483 nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ 00484 txt_move_to(text, mrk->lineno, mrk->start+c, 0); 00485 if(s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); 00486 txt_delete_char(text); 00487 text_update_line_edited(st->text->curl); 00488 if(mrk==marker || mrk==nxt) break; 00489 mrk= nxt; 00490 } 00491 swallow= 1; 00492 draw= 1; 00493 } 00494 break; 00495 case TABKEY: 00496 if(qual & LR_SHIFTKEY) { 00497 nxt= marker->prev; 00498 if(!nxt) nxt= text->markers.last; 00499 } 00500 else { 00501 nxt= marker->next; 00502 if(!nxt) nxt= text->markers.first; 00503 } 00504 if(marker->flags & TMARK_TEMP) { 00505 if(nxt==marker) nxt= NULL; 00506 BLI_freelinkN(&text->markers, marker); 00507 } 00508 mrk= nxt; 00509 if(mrk) { 00510 txt_move_to(text, mrk->lineno, mrk->start, 0); 00511 txt_move_to(text, mrk->lineno, mrk->end, 1); 00512 // XXX text_update_cursor_moved(C); 00513 // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); 00514 } 00515 swallow= 1; 00516 draw= 1; 00517 break; 00518 00519 /* Events that should clear markers */ 00520 case UKEY: if(!(qual & LR_ALTKEY)) break; 00521 case ZKEY: if(evnt==ZKEY && !(qual & LR_CTRLKEY)) break; 00522 case RETKEY: 00523 case ESCKEY: 00524 if(marker->flags & (TMARK_EDITALL | TMARK_TEMP)) 00525 txt_clear_markers(text, marker->group, 0); 00526 else 00527 BLI_freelinkN(&text->markers, marker); 00528 swallow= 1; 00529 draw= 1; 00530 break; 00531 case RIGHTMOUSE: /* Marker context menu? */ 00532 case LEFTMOUSE: 00533 break; 00534 case FKEY: /* Allow find */ 00535 if(qual & LR_SHIFTKEY) swallow= 1; 00536 break; 00537 00538 default: 00539 if(qual!=0 && qual!=LR_SHIFTKEY) 00540 swallow= 1; /* Swallow all other shortcut events */ 00541 } 00542 } 00543 00544 if(draw) 00545 {}; // XXX redraw_alltext(); 00546 00547 return swallow; 00548 } 00549