1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Naba Kumar
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <libanjuta/anjuta-debug.h>
22 #include "aneditor-priv.h"
24 bool AnEditor::StartCallTip_new() {
25 TMTagAttrType attrs
[] =
27 tm_tag_attr_name_t
, tm_tag_attr_type_t
, tm_tag_attr_none_t
31 int current
= GetCaretInLine();
32 call_tip_node
.start_pos
= SendEditor(SCI_GETCURRENTPOS
);
33 call_tip_node
.call_tip_start_pos
= current
;
38 while (current
> 0 && (braces
|| linebuf
[current
- 1] != '(')) {
39 if (linebuf
[current
- 1] == '(')
41 else if (linebuf
[current
- 1] == ')')
44 call_tip_node
.start_pos
--;
48 call_tip_node
.start_pos
--;
51 while (current
> 0 && isspace(linebuf
[current
- 1])) {
53 call_tip_node
.start_pos
--;
55 } while (current
> 0 &&
56 !calltipWordCharacters
.contains(linebuf
[current
- 1]));
61 call_tip_node
.startCalltipWord
= current
-1;
63 while (call_tip_node
.startCalltipWord
> 0 &&
64 calltipWordCharacters
.contains(linebuf
[call_tip_node
.startCalltipWord
- 1]))
65 call_tip_node
.startCalltipWord
--;
67 linebuf
.change(current
, '\0');
68 call_tip_node
.rootlen
= current
- call_tip_node
.startCalltipWord
;
70 call_tip_node
.max_def
= 0;
71 call_tip_node
.def_index
= 0;
73 const GPtrArray
*tags
= tm_workspace_find(linebuf
.c_str() +
74 call_tip_node
.startCalltipWord
,
77 tm_tag_macro_with_arg_t
,
79 if (tags
&& (tags
->len
> 0))
81 call_tip_node
.max_def
= (tags
->len
< 20)? tags
->len
:20;
82 printf ("Number of calltips found %d\n", tags
->len
);
83 for (unsigned int i
= 0; (i
< tags
->len
) && (i
< 20); i
++) {
84 TMTag
*tag
= (TMTag
*) tags
->pdata
[0];
85 GString
* tmp
= g_string_new(NVL(tag
->atts
.entry
.type_ref
[1], ""));
86 for (unsigned int j
= 0; j
< tag
->atts
.entry
.pointerOrder
; j
++)
87 g_string_append(tmp
, "*");
88 g_string_append_printf(tmp
, " %s%s", tag
->name
,
89 NVL(tag
->atts
.entry
.arglist
, ""));
90 call_tip_node
.functionDefinition
[i
] = tmp
->str
;
91 g_string_free(tmp
, TRUE
);
94 if (call_tip_node
.max_def
> 1)
95 real_tip
= g_strconcat ("\002",
96 call_tip_node
.functionDefinition
[0].c_str(),
99 real_tip
= g_strdup (call_tip_node
.functionDefinition
[0].c_str());
101 SendEditorString(SCI_CALLTIPSHOW
, call_tip_node
.start_pos
-
102 call_tip_node
.rootlen
+ 1, real_tip
);
104 ContinueCallTip_new();
109 static bool IsCallTipSeparator(char ch
) {
110 return (ch
== ',') || (ch
== ';');
113 void AnEditor::ContinueCallTip_new() {
116 unsigned current
= GetCaretInLine();
119 for (unsigned i
= call_tip_node
.call_tip_start_pos
; i
< current
; i
++) {
121 unsigned char ch
= linebuf
[i
];
123 // check whether the are some other functions nested.
124 // if found we'll skip them to evitate commas problems
127 for (unsigned k
= i
+1; k
< linebuf
.length(); k
++ ) {
128 if ( linebuf
[k
] == '(' ) {
132 if ( linebuf
[k
] == ')' ) {
142 if (IsCallTipSeparator(ch
))
147 int startHighlight
= 0;
149 while (call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] &&
150 call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] != '(')
153 if (call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] == '(') {
157 // printf(const char*, ...
160 while (call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] &&
162 if (IsCallTipSeparator(call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] ) ||
163 call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] == ')')
168 if (IsCallTipSeparator(call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
]) ||
169 call_tip_node
.functionDefinition
[call_tip_node
.def_index
][startHighlight
] == ')')
172 int endHighlight
= startHighlight
;
174 if (call_tip_node
.functionDefinition
[call_tip_node
.def_index
][endHighlight
])
177 while (call_tip_node
.functionDefinition
[call_tip_node
.def_index
][endHighlight
] &&
178 !IsCallTipSeparator(call_tip_node
.functionDefinition
[call_tip_node
.def_index
][endHighlight
])
179 && call_tip_node
.functionDefinition
[call_tip_node
.def_index
][endHighlight
] != ')')
182 SendEditor(SCI_CALLTIPSETHLT
, startHighlight
, endHighlight
);
185 //------------------------------------------------------------------------------
186 // we're going to save the current status of call_tip_node in call_tip_node_list
187 // to let another *new* call_tip to show up
190 void AnEditor::SaveCallTip() {
192 CallTipNode
*ctn
= new CallTipNode
;
193 // g_message( "***saving calltip..." );
195 ctn
->startCalltipWord
= call_tip_node
.startCalltipWord
;
196 ctn
->def_index
= call_tip_node
.def_index
;
197 ctn
->max_def
= call_tip_node
.max_def
;
198 for (int i
= 0; i
< ctn
->max_def
; i
++) {
199 ctn
->functionDefinition
[i
] = call_tip_node
.functionDefinition
[i
];
201 ctn
->start_pos
= call_tip_node
.start_pos
;
202 ctn
->rootlen
= call_tip_node
.rootlen
;
203 ctn
->call_tip_start_pos
= call_tip_node
.call_tip_start_pos
;
206 g_queue_push_tail( call_tip_node_queue
, ctn
);
208 SetCallTipDefaults();
211 void AnEditor::ResumeCallTip(bool pop_from_stack
) {
213 if (pop_from_stack
) {
214 if (g_queue_is_empty (call_tip_node_queue
)) {
219 CallTipNode_ptr tmp_node
;
221 // set up next CallTipNode parameters in AnEditor::call_tip_node
222 tmp_node
= (CallTipNode_ptr
)g_queue_pop_tail( call_tip_node_queue
);
224 g_return_if_fail( tmp_node
!= NULL
);
226 call_tip_node
.startCalltipWord
= tmp_node
->startCalltipWord
;
227 call_tip_node
.def_index
= tmp_node
->def_index
;
228 call_tip_node
.max_def
= tmp_node
->max_def
;
229 for (int i
= 0; i
< call_tip_node
.max_def
; i
++)
230 call_tip_node
.functionDefinition
[i
] =
231 tmp_node
->functionDefinition
[i
];
232 call_tip_node
.start_pos
= tmp_node
->start_pos
;
233 call_tip_node
.rootlen
= tmp_node
->rootlen
;
234 call_tip_node
.call_tip_start_pos
= tmp_node
->call_tip_start_pos
;
236 // in response to g_malloc on SaveCallTip
239 if (call_tip_node
.max_def
> 1 &&
240 call_tip_node
.def_index
== 0) {
243 real_tip
= g_strconcat ("\002",
244 call_tip_node
.functionDefinition
[call_tip_node
.def_index
].c_str(),
246 SendEditorString(SCI_CALLTIPSHOW
, call_tip_node
.start_pos
-
247 call_tip_node
.rootlen
+ 1, real_tip
);
249 } else if (call_tip_node
.max_def
> 1 &&
250 call_tip_node
.def_index
== (call_tip_node
.max_def
- 1)) {
252 real_tip
= g_strconcat ("\001",
253 call_tip_node
.functionDefinition
[call_tip_node
.def_index
].c_str(),
255 SendEditorString(SCI_CALLTIPSHOW
, call_tip_node
.start_pos
-
256 call_tip_node
.rootlen
+ 1, real_tip
);
258 } else if (call_tip_node
.max_def
> 1) {
260 real_tip
= g_strconcat ("\001\002",
261 call_tip_node
.functionDefinition
[call_tip_node
.def_index
].c_str(),
263 SendEditorString(SCI_CALLTIPSHOW
, call_tip_node
.start_pos
-
264 call_tip_node
.rootlen
+ 1, real_tip
);
267 SendEditorString(SCI_CALLTIPSHOW
, call_tip_node
.start_pos
-
268 call_tip_node
.rootlen
+ 1,
269 call_tip_node
.functionDefinition
[call_tip_node
.def_index
].c_str());
273 //------------------------------------------------------------------------------
276 void AnEditor::ShutDownCallTip() {
278 // g_message( "***shutdowncalltip: length %d", g_queue_get_length( call_tip_node_queue ));
280 while ( g_queue_is_empty( call_tip_node_queue
) != TRUE
) {
281 CallTipNode_ptr tmp_node
;
283 tmp_node
= (CallTipNode_ptr
)g_queue_pop_tail( call_tip_node_queue
);
285 // in response to g_malloc on SaveCallTip
289 SetCallTipDefaults();
292 //------------------------------------------------------------------------------
294 void AnEditor::SetCallTipDefaults( ) {
296 // we're going to set the default values to this.call_tip_node struct
297 call_tip_node
.def_index
= 0;
298 call_tip_node
.max_def
= 0;
299 call_tip_node
.start_pos
= 0;
300 call_tip_node
.rootlen
= 0;
301 call_tip_node
.startCalltipWord
= 0;
302 call_tip_node
.call_tip_start_pos
= 0;
305 //------------------------------------------------------------------------------
306 // gives a list of calltips which match the word on the current caret and display
309 void AnEditor::CompleteCallTip() {
311 TMTagAttrType attrs
[] = {tm_tag_attr_name_t
, tm_tag_attr_type_t
, tm_tag_attr_none_t
};
312 int caret_position
= SendEditor(SCI_GETCURRENTPOS
);
314 if (SendEditor(SCI_CALLTIPACTIVE
))
317 // get the current word
318 GetWordAtPosition(expr
, sizeof(expr
), caret_position
);
319 DEBUG_PRINT("completecalltip: on word %s and caret_position %d", expr
, caret_position
);
321 const GPtrArray
*tags
= tm_workspace_find(expr
,
324 tm_tag_macro_with_arg_t
,
327 // we'll provide a function calltip
328 if (tags
&& (tags
->len
> 0))
330 TMTag
*tag
= (TMTag
*) tags
->pdata
[0];
334 tmp
= g_strdup_printf("%s %s%s", NVL(tag
->atts
.entry
.type_ref
[1], ""),
335 tag
->name
, NVL(tag
->atts
.entry
.arglist
, ""));
340 real_tip
= g_strdup (definition
.c_str());
342 SendEditorString(SCI_CALLTIPSHOW
, caret_position
, real_tip
);