Blender  V2.59
text_python.c
Go to the documentation of this file.
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