Blender V2.61 - r43446

text_python.c

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