]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ocaml/contrib/win32caml/editbuffer.c
update
[l4.git] / l4 / pkg / ocaml / contrib / win32caml / editbuffer.c
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 /***********************************************************************/
12
13 /***********************************************************************/
14 /* Changes made by Chris Watford to enhance the source editor          */
15 /* Began 14 Sept 2003 - watford@uiuc.edu                               */
16 /***********************************************************************/
17
18 #include <string.h>
19 #include <stdlib.h>
20 #include "inriares.h"
21 #include "inria.h"
22
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)
36 {
37         LineList *tail = NULL; //head of the edit buffer line list
38         LineList *newline = NULL;
39
40         // sanity check
41         if(edBuf == NULL)
42         {
43                 return FALSE;
44         }
45
46         // perform edit buffer sanity checks
47         if((edBuf->LineCount < 0) || (edBuf->Lines == NULL))
48         {
49                 edBuf->LineCount = 0;
50         }
51
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);
55
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';
63
64         // add it to the list as the head or the tail
65         if(tail != NULL)
66         {
67                 tail->Next = newline;
68         } else {
69                 edBuf->Lines = newline;
70         }
71
72         // update the number of lines in the buffer
73         edBuf->LineCount++;
74
75         return TRUE;
76 }
77
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)
88 {
89         LineList *update = edBuf->Lines; //head of the edit buffer line list
90         LineList *newline = NULL;
91         int i;
92
93         // sanity checks
94         if(edBuf == NULL)
95         {
96                 return FALSE;
97         } else if(      (edBuf->LineCount == 0) ||
98                                 (edBuf->Lines == NULL) ||
99                                 (idx >= edBuf->LineCount) ||
100                                 (idx < 0) ) {
101                 return FALSE;
102         }
103
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++);
107
108         // did things mess up?
109         if( (update == NULL) || (i != idx) )
110         {
111                 return FALSE;
112         }
113
114         // get rid of the old line
115         free(update->Text);
116
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';
121
122         return TRUE;
123 }
124
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)
135 {
136         LineList *update;
137
138         // sanity checks
139         if(edBuf == NULL)
140         {
141                 return FALSE;
142         } else if((idx > edBuf->LineCount) || (idx < 0)) {
143                 return FALSE;
144         }
145
146         update = edBuf->Lines; //head of the edit buffer line list
147
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);
155         }
156 }
157
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)
172 {
173         LineList *update = NULL;
174         int i = 0;
175
176         // sanity checks
177         if(edBuf == NULL)
178         {
179                 return FALSE;
180         } else if(      (edBuf->LineCount == 0) ||
181                                 (edBuf->Lines == NULL) ||
182                                 (idx >= edBuf->LineCount) ||
183                                 (idx < 0) ) {
184                 return FALSE;
185         }
186         
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++);
190
191         // remove this line
192         if(update != NULL)
193         {
194                 // break links, removing our line
195                 if(update->Prev != NULL)
196                 {
197                         // we're not the first so just break the link
198                         update->Prev->Next = update->Next;
199                         
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;
206                 }
207
208                 // one less line to worry about
209                 edBuf->LineCount--;
210
211                 // get rid of the text
212                 if(update->Text != NULL)
213                         free(update->Text);
214
215                 // get rid of us
216                 free(update);
217
218                 return TRUE;
219         }
220
221         return FALSE;
222 }
223
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)
234 {
235         LineList *line = NULL; //head of the edit buffer line list
236         char* retline = (char*)realloc(NULL, 1);
237         unsigned int i = 0;
238
239         // fix retline bug
240         retline[0] = '\0';
241
242         // sanity checks
243         if(edBuf == NULL)
244         {
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;
251         }
252
253         // get the big line
254         for(line = edBuf->Lines; line != NULL; line = line->Next)
255         {
256                 if(line->Text != NULL)
257                 {
258                         retline = (char*)realloc(retline, (strlen(retline) + strlen(line->Text) + (strlen(retline) > 0 ? 2 : 1)));
259
260                         if(strlen(retline) > 0)
261                                 retline = strcat(retline, " ");
262
263                         retline = strcat(retline, line->Text);
264
265                         //concat in the hoouuusssseee!
266                 }
267         }
268
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++)
271         {
272                 switch(retline[i])
273                 {
274                         case '\n':
275                         case '\t':
276                         case '\r':
277                                 retline[i] = ' ';
278                 }
279         }
280
281         return retline;
282 }
283
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)
294 {
295         LineList *line = NULL; //head of the edit buffer line list
296         char* retbuf = (char*)realloc(NULL, 1);
297         unsigned int i = 0;
298
299         // fix retline bug
300         retbuf[0] = '\0';
301
302         // sanity checks
303         if(edBuf == NULL)
304         {
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;
311         }
312
313         // get the big line
314         for(line = edBuf->Lines; line != NULL; line = line->Next)
315         {
316                 if(line->Text != NULL)
317                 {
318                         int len = strlen(retbuf);
319                         len += strlen(line->Text) + (len > 0 ? 3 : 1);
320
321                         retbuf = (char*)realloc(retbuf, len);
322
323                         if(strlen(retbuf) > 0)
324                                 retbuf = strcat(retbuf, "\r\n");
325
326                         retbuf = strcat(retbuf, line->Text);
327
328                         retbuf[len-1] = '\0';
329
330                         //concat in the hoouuusssseee!
331                 }
332         }
333
334         return retbuf;
335 }
336
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)
346 {
347         LineList *line = NULL; //head of the edit buffer line list
348
349         // sanity checks
350         if(edBuf == NULL)
351         {
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;
358         }
359
360         // go to the last line
361         for(line = edBuf->Lines; line->Next != NULL; line = line->Next);
362
363         return line->Text;
364 }
365
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)
383 {
384         // sanity checks
385         if(edBuf == NULL)
386         {
387                 return NULL;
388         } else {
389                 EditBuffer* copy = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
390                 LineList* lines = edBuf->Lines;
391                 LineList* lastLine = NULL;
392
393                 // clear its initial values
394                 copy->LineCount = 0;
395                 copy->Lines = NULL;
396                 copy->isCorrect = FALSE;
397
398                 // well we don't have to copy much
399                 if((lines == NULL) || (edBuf->LineCount <= 0))
400                 {
401                         return copy;
402                 }
403
404                 // get if its correct
405                 copy->isCorrect = edBuf->isCorrect;
406
407                 // go through each line, malloc it and add it
408                 for( ; lines != NULL; lines = lines->Next)
409                 {
410                         LineList* curline = (LineList*)SafeMalloc(sizeof(LineList));
411                         curline->Next = NULL;
412                         curline->Prev = NULL;
413
414                         // if there was a last line, link them to us
415                         if(lastLine != NULL)
416                         {
417                                 lastLine->Next = curline;
418                                 curline->Prev = lastLine;
419                         }
420
421                         // are we the first line? add us to the edit buffer as the first
422                         if(copy->Lines == NULL)
423                         {
424                                 copy->Lines = curline;
425                         }
426
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';
437                         }
438
439                         // up the line count and make us the last line
440                         copy->LineCount++;
441                         lastLine = curline;
442                 }
443
444                 // return our new copy
445                 return copy;
446         }
447 }
448
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)
458 {
459         // sanity checks
460         if(edBuf == NULL)
461         {       // nothing to do
462                 return;
463         } else if(edBuf->Lines != NULL) {
464                 LineList* lastline = NULL;
465
466                 // loop through each line free'ing its text
467                 for( ; edBuf->Lines != NULL; edBuf->Lines = edBuf->Lines->Next)
468                 {
469                         if(edBuf->Lines->Text != NULL)
470                                 free(edBuf->Lines->Text);
471
472                         // if there was a line before us, free it
473                         if(lastline != NULL)
474                         {
475                                 free(lastline);
476                                 lastline = NULL;
477                         }
478
479                         lastline = edBuf->Lines;
480                 }
481
482                 // free the last line
483                 free(lastline);
484         }
485
486         // free ourself
487         free(edBuf);
488 }
489
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)
503 {
504         // create a new one
505         EditBuffer *edBuf = (EditBuffer*)SafeMalloc(sizeof(EditBuffer));
506         
507         // default vals
508         edBuf->LineCount = 0;
509         edBuf->Lines = NULL;
510         edBuf->isCorrect = FALSE;
511         
512         // return it
513         return edBuf;
514 }