Sys.Signals module for a Variant type of signals (and a set_signal function that...
[ocaml.git] / win32caml / editbuffer.c
blob480d22d86ab676239eb6f26d737b29512a8b8cfd
1 /***********************************************************************/
2 /* */
3 /* Objective Caml */
4 /* */
5 /* Developed by Jacob Navia. */
6 /* Copyright 2001 Institut National de Recherche en Informatique et */
7 /* en Automatique. All rights reserved. This file is distributed */
8 /* under the terms of the GNU Library General Public License, with */
9 /* the special exception on linking described in file ../LICENSE. */
10 /* */
11 /***********************************************************************/
13 /***********************************************************************/
14 /* Changes made by Chris Watford to enhance the source editor */
15 /* Began 14 Sept 2003 - watford@uiuc.edu */
16 /***********************************************************************/
18 #include <string.h>
19 #include <stdlib.h>
20 #include "inriares.h"
21 #include "inria.h"
23 /*------------------------------------------------------------------------
24 Procedure: editbuffer_addline ID:1
25 Author: Chris Watford watford@uiuc.edu
26 Purpose: Adds a line to the current edit buffer
27 Input: Line of text to append to the end
28 Output:
29 Errors:
30 --------------------------------------------------------------------------
31 Edit History:
32 18 Sept 2003 - Chris Watford watford@uiuc.edu
33 - Corrected doubly linked list issue
34 ------------------------------------------------------------------------*/
35 BOOL editbuffer_addline(EditBuffer* edBuf, char* line)
37 LineList *tail = NULL; //head of the edit buffer line list
38 LineList *newline = NULL;
40 // sanity check
41 if(edBuf == NULL)
43 return FALSE;
46 // perform edit buffer sanity checks
47 if((edBuf->LineCount < 0) || (edBuf->Lines == NULL))
49 edBuf->LineCount = 0;
52 // move to the end of the line list in the edit buffer
53 if((tail = edBuf->Lines) != NULL)
54 for( ; tail->Next != NULL; tail = tail->Next);
56 // create the new line entry
57 newline = (LineList*)SafeMalloc(sizeof(LineList));
58 newline->Next = NULL;
59 newline->Prev = tail;
60 newline->Text = (char*)SafeMalloc(strlen(line)+1);
61 strncpy(newline->Text, line, strlen(line)+1);
62 newline->Text[strlen(line)] = '\0';
64 // add it to the list as the head or the tail
65 if(tail != NULL)
67 tail->Next = newline;
68 } else {
69 edBuf->Lines = newline;
72 // update the number of lines in the buffer
73 edBuf->LineCount++;
75 return TRUE;
78 /*------------------------------------------------------------------------
79 Procedure: editbuffer_updateline ID:1
80 Author: Chris Watford watford@uiuc.edu
81 Purpose: Updates the edit buffer's internal contents for a line
82 Input: idx - Line index
83 line - String to add
84 Output: if the line was updated or not
85 Errors:
86 ------------------------------------------------------------------------*/
87 BOOL editbuffer_updateline(EditBuffer* edBuf, int idx, char* line)
89 LineList *update = edBuf->Lines; //head of the edit buffer line list
90 LineList *newline = NULL;
91 int i;
93 // sanity checks
94 if(edBuf == NULL)
96 return FALSE;
97 } else if( (edBuf->LineCount == 0) ||
98 (edBuf->Lines == NULL) ||
99 (idx >= edBuf->LineCount) ||
100 (idx < 0) ) {
101 return FALSE;
104 // move to the index in the line list
105 // i left in update != NULL as a sanity check
106 for(i = 0; ((update != NULL) && (i != idx)); update = update->Next, i++);
108 // did things mess up?
109 if( (update == NULL) || (i != idx) )
111 return FALSE;
114 // get rid of the old line
115 free(update->Text);
117 // get the new line updated
118 update->Text = (char*)SafeMalloc(strlen(line)+1);
119 strncpy(update->Text, line, strlen(line)+1);
120 update->Text[strlen(line)] = '\0';
122 return TRUE;
125 /*------------------------------------------------------------------------
126 Procedure: editbuffer_updateoraddline ID:1
127 Author: Chris Watford watford@uiuc.edu
128 Purpose: Updates the edit buffer's internal contents for a line
129 Input: idx - Line index
130 line - String to add
131 Output: if the line was updated or not
132 Errors:
133 ------------------------------------------------------------------------*/
134 BOOL editbuffer_updateoraddline(EditBuffer* edBuf, int idx, char* line)
136 LineList *update;
138 // sanity checks
139 if(edBuf == NULL)
141 return FALSE;
142 } else if((idx > edBuf->LineCount) || (idx < 0)) {
143 return FALSE;
146 update = edBuf->Lines; //head of the edit buffer line list
148 // do we update or add?
149 if((idx < edBuf->LineCount) && (edBuf->Lines != NULL))
150 { //interior line, update
151 return editbuffer_updateline(edBuf, idx, line);
152 } else {
153 //fence line, add
154 return editbuffer_addline(edBuf, line);
158 /*------------------------------------------------------------------------
159 Procedure: editbuffer_removeline ID:1
160 Author: Chris Watford watford@uiuc.edu
161 Purpose: Removes a line from the edit buffer
162 Input: idx - Line index to remove
163 Output: if the line was removed or not
164 Errors:
165 --------------------------------------------------------------------------
166 Edit History:
167 18 Sept 2003 - Chris Watford watford@uiuc.edu
168 - Added to allow backspace and delete support
169 - Corrected doubly linked list issue
170 ------------------------------------------------------------------------*/
171 BOOL editbuffer_removeline(EditBuffer* edBuf, int idx)
173 LineList *update = NULL;
174 int i = 0;
176 // sanity checks
177 if(edBuf == NULL)
179 return FALSE;
180 } else if( (edBuf->LineCount == 0) ||
181 (edBuf->Lines == NULL) ||
182 (idx >= edBuf->LineCount) ||
183 (idx < 0) ) {
184 return FALSE;
187 // move to the index in the line list
188 // i left in update != NULL as a sanity check
189 for(i = 0, update = edBuf->Lines; ((update != NULL) && (i != idx)); update = update->Next, i++);
191 // remove this line
192 if(update != NULL)
194 // break links, removing our line
195 if(update->Prev != NULL)
197 // we're not the first so just break the link
198 update->Prev->Next = update->Next;
200 // fix the prev check
201 if(update->Next != NULL)
202 update->Next->Prev = update->Prev;
203 } else {
204 // we're the first, attach the next guy to lines
205 edBuf->Lines = update->Next;
208 // one less line to worry about
209 edBuf->LineCount--;
211 // get rid of the text
212 if(update->Text != NULL)
213 free(update->Text);
215 // get rid of us
216 free(update);
218 return TRUE;
221 return FALSE;
224 /*------------------------------------------------------------------------
225 Procedure: editbuffer_getasline ID:1
226 Author: Chris Watford watford@uiuc.edu
227 Purpose: Returns the edit buffer as one big line, \n's and \t's
228 become spaces.
229 Input:
230 Output:
231 Errors:
232 ------------------------------------------------------------------------*/
233 char* editbuffer_getasline(EditBuffer* edBuf)
235 LineList *line = NULL; //head of the edit buffer line list
236 char* retline = (char*)realloc(NULL, 1);
237 unsigned int i = 0;
239 // fix retline bug
240 retline[0] = '\0';
242 // sanity checks
243 if(edBuf == NULL)
245 return NULL;
246 } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
247 // fix any possible errors that may come from this
248 edBuf->LineCount = 0;
249 edBuf->Lines = NULL;
250 return NULL;
253 // get the big line
254 for(line = edBuf->Lines; line != NULL; line = line->Next)
256 if(line->Text != NULL)
258 retline = (char*)realloc(retline, (strlen(retline) + strlen(line->Text) + (strlen(retline) > 0 ? 2 : 1)));
260 if(strlen(retline) > 0)
261 retline = strcat(retline, " ");
263 retline = strcat(retline, line->Text);
265 //concat in the hoouuusssseee!
269 // now we have the big line, so lets ditch all \n's \t's and \r's
270 for(i = 0; i < strlen(retline); i++)
272 switch(retline[i])
274 case '\n':
275 case '\t':
276 case '\r':
277 retline[i] = ' ';
281 return retline;
284 /*------------------------------------------------------------------------
285 Procedure: editbuffer_getasbuffer ID:1
286 Author: Chris Watford watford@uiuc.edu
287 Purpose: Returns the edit buffer as one big line, \n's and \t's
288 become spaces.
289 Input:
290 Output:
291 Errors:
292 ------------------------------------------------------------------------*/
293 char* editbuffer_getasbuffer(EditBuffer* edBuf)
295 LineList *line = NULL; //head of the edit buffer line list
296 char* retbuf = (char*)realloc(NULL, 1);
297 unsigned int i = 0;
299 // fix retline bug
300 retbuf[0] = '\0';
302 // sanity checks
303 if(edBuf == NULL)
305 return NULL;
306 } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
307 // fix any possible errors that may come from this
308 edBuf->LineCount = 0;
309 edBuf->Lines = NULL;
310 return NULL;
313 // get the big line
314 for(line = edBuf->Lines; line != NULL; line = line->Next)
316 if(line->Text != NULL)
318 int len = strlen(retbuf);
319 len += strlen(line->Text) + (len > 0 ? 3 : 1);
321 retbuf = (char*)realloc(retbuf, len);
323 if(strlen(retbuf) > 0)
324 retbuf = strcat(retbuf, "\r\n");
326 retbuf = strcat(retbuf, line->Text);
328 retbuf[len-1] = '\0';
330 //concat in the hoouuusssseee!
334 return retbuf;
337 /*------------------------------------------------------------------------
338 Procedure: editbuffer_lastline ID:1
339 Author: Chris Watford watford@uiuc.edu
340 Purpose: Returns the last line in the edit buffer
341 Input:
342 Output:
343 Errors:
344 ------------------------------------------------------------------------*/
345 char* editbuffer_lastline(EditBuffer* edBuf)
347 LineList *line = NULL; //head of the edit buffer line list
349 // sanity checks
350 if(edBuf == NULL)
352 return NULL;
353 } else if (edBuf->LineCount == 0 || edBuf->Lines == NULL) {
354 // fix any possible errors that may come from this
355 edBuf->LineCount = 0;
356 edBuf->Lines = NULL;
357 return NULL;
360 // go to the last line
361 for(line = edBuf->Lines; line->Next != NULL; line = line->Next);
363 return line->Text;
366 /*------------------------------------------------------------------------
367 Procedure: editbuffer_copy ID:1
368 Author: Chris Watford watford@uiuc.edu
369 Purpose: Makes an exact copy of an edit buffer
370 Input:
371 Output:
372 Errors:
373 --------------------------------------------------------------------------
374 Edit History:
375 16 Sept 2003 - Chris Watford watford@uiuc.edu
376 - Added to make copies of history entries
377 18 Sept 2003 - Chris Watford watford@uiuc.edu
378 - Corrected doubly linked list issue
379 06 Oct 2003 - Chris Watford watford@uiuc.edu
380 - Added isCorrect flag
381 ------------------------------------------------------------------------*/
382 EditBuffer* editbuffer_copy(EditBuffer* edBuf)
384 // sanity checks
385 if(edBuf == NULL)
387 return NULL;
388 } else {
389 EditBuffer* copy = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
390 LineList* lines = edBuf->Lines;
391 LineList* lastLine = NULL;
393 // clear its initial values
394 copy->LineCount = 0;
395 copy->Lines = NULL;
396 copy->isCorrect = FALSE;
398 // well we don't have to copy much
399 if((lines == NULL) || (edBuf->LineCount <= 0))
401 return copy;
404 // get if its correct
405 copy->isCorrect = edBuf->isCorrect;
407 // go through each line, malloc it and add it
408 for( ; lines != NULL; lines = lines->Next)
410 LineList* curline = (LineList*)SafeMalloc(sizeof(LineList));
411 curline->Next = NULL;
412 curline->Prev = NULL;
414 // if there was a last line, link them to us
415 if(lastLine != NULL)
417 lastLine->Next = curline;
418 curline->Prev = lastLine;
421 // are we the first line? add us to the edit buffer as the first
422 if(copy->Lines == NULL)
424 copy->Lines = curline;
427 // check if there is text on the line
428 if(lines->Text == NULL)
429 { // no text, make it blankz0r
430 curline->Text = (char*)SafeMalloc(sizeof(char));
431 curline->Text[0] = '\0';
432 } else {
433 // there is text, copy it and null-terminate
434 curline->Text = (char*)SafeMalloc(strlen(lines->Text) + 1);
435 strncpy(curline->Text, lines->Text, strlen(lines->Text));
436 curline->Text[strlen(lines->Text)] = '\0';
439 // up the line count and make us the last line
440 copy->LineCount++;
441 lastLine = curline;
444 // return our new copy
445 return copy;
449 /*------------------------------------------------------------------------
450 Procedure: editbuffer_destroy ID:1
451 Author: Chris Watford watford@uiuc.edu
452 Purpose: Destroys an edit buffer
453 Input:
454 Output:
455 Errors:
456 ------------------------------------------------------------------------*/
457 void editbuffer_destroy(EditBuffer* edBuf)
459 // sanity checks
460 if(edBuf == NULL)
461 { // nothing to do
462 return;
463 } else if(edBuf->Lines != NULL) {
464 LineList* lastline = NULL;
466 // loop through each line free'ing its text
467 for( ; edBuf->Lines != NULL; edBuf->Lines = edBuf->Lines->Next)
469 if(edBuf->Lines->Text != NULL)
470 free(edBuf->Lines->Text);
472 // if there was a line before us, free it
473 if(lastline != NULL)
475 free(lastline);
476 lastline = NULL;
479 lastline = edBuf->Lines;
482 // free the last line
483 free(lastline);
486 // free ourself
487 free(edBuf);
490 /*------------------------------------------------------------------------
491 Procedure: editbuffer_new ID:1
492 Author: Chris Watford watford@uiuc.edu
493 Purpose: Creates an edit buffer
494 Input:
495 Output:
496 Errors:
497 --------------------------------------------------------------------------
498 Edit History:
499 06 Oct 2003 - Chris Watford watford@uiuc.edu
500 - Added isCorrect flag
501 ------------------------------------------------------------------------*/
502 EditBuffer* editbuffer_new(void)
504 // create a new one
505 EditBuffer *edBuf = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
507 // default vals
508 edBuf->LineCount = 0;
509 edBuf->Lines = NULL;
510 edBuf->isCorrect = FALSE;
512 // return it
513 return edBuf;