6 #include "../localuser/localuserchannel.h"
14 int hed_is_valid_filename(const char *fname
)
17 if (strlen(fname
) < 1 || strlen(fname
) > (64 - 1))
20 for (i
=0;i
< 64 && fname
[i
] != '\0';i
++)
21 if (!isalnum(fname
[i
]))
27 helpmod_editor
*hed_open(huser
*husr
, const char *fname
)
29 helpmod_editor
*editor
;
31 char fname_buffer
[128];
35 if (hed_get(fname
) != NULL
)
36 return hed_get(fname
);
38 if (!hed_is_valid_filename(fname
))
41 sprintf(fname_buffer
, HELPMOD_TEXT_DIR
"/%s" ,fname
);
42 file
= fopen(fname_buffer
, "rwt");
46 editor
= (helpmod_editor
*)malloc(sizeof (helpmod_editor
));
49 strcpy(editor
->filename
, fname
);
53 editor
->state
= HED_COMMAND
;
54 editor
->last_error
= HED_ERR_NO_ERROR
;
57 editor
->free_lines
= &editor
->buffers
[0];
58 editor
->clipboard
= NULL
;
60 for (ptr
= editor
->free_lines
,i
= 1;i
< HED_BUFFER_LINES
;i
++,ptr
= ptr
->next
)
62 ptr
->next
= &editor
->buffers
[i
];
67 for(i
= 0;!feof(file
) && i
< HED_BUFFER_LINES
;i
++)
69 char *str
= hed_add_line(editor
, i
);
70 if (!fgets(str
, 384, file
))
71 { /* If the input ran out, the last line added has to be removed */
72 hed_del_line(editor
, i
);
73 hed_clear_clipboard(editor
);
76 strchr(str
, '\n')[0] = '\0';
82 editor
->flags
= HED_FLAGS_DEFAULT
;
84 editor
->next
= helpmod_editors
;
85 helpmod_editors
= editor
;
90 helpmod_editor
*hed_write(helpmod_editor
*editor
)
93 char fname_buffer
[128];
96 sprintf(fname_buffer
, HELPMOD_TEXT_DIR
"/%s" ,editor
->filename
);
97 if ((file
= fopen(fname_buffer
, "wt")) == NULL
);
99 for (ptr
= editor
->start
;ptr
!= NULL
;ptr
= ptr
->next
)
100 fprintf(file
, "%s\n", ptr
->line
);
106 helpmod_editor
*hed_close(helpmod_editor
*editor
)
108 helpmod_editor
**ptr
= &helpmod_editors
;
113 for (;*ptr
;ptr
= &(*ptr
)->next
)
116 helpmod_editor
*tmp
= editor
->next
;
117 editor
->user
->editor
= NULL
;
126 int hed_byte_count(helpmod_editor
*editor
)
128 hed_line
*ptr
= editor
->start
;
131 for (;ptr
&& ptr
->line
[0] != '\0';ptr
= ptr
->next
)
132 count
+= strlen(ptr
->line
);
137 int hed_line_count(helpmod_editor
*editor
)
139 hed_line
*ptr
= editor
->start
;
142 for (;ptr
&& ptr
!= NULL
;ptr
= ptr
->next
)
148 /* Get by filename */
149 helpmod_editor
*hed_get(const char *fname
)
151 helpmod_editor
*tmp
= helpmod_editors
;
152 for (;tmp
!= NULL
;tmp
= tmp
->next
)
153 if (!strcmp(tmp
->filename
, fname
))
158 void hed_command (huser
*sender
, channel
* returntype
, char* ostr
, int argc
, char *argv
[])
160 helpmod_editor
*editor
= sender
->editor
;
161 assert (editor
!= NULL
);
163 if (editor
->state
== HED_COMMAND
)
165 int i
, start
= editor
->line
+ 1, stop
= editor
->line
+ 1, target
= editor
->line
+ 1, nread
;
171 editor
->last_error
= HED_ERR_NO_COMMAND
;
175 if (strlen(argv
[0]) > 64)
177 editor
->last_error
= HED_ERR_SYNTAX_ERROR
;
181 if (!strcmp(argv
[0], "wq"))
184 helpmod_reply(sender
, returntype
, "Ged: %d", hed_byte_count(editor
));
189 { /* Handle replacements */
191 for (i
=0,j
=0;argv
[0][i
] != '\0' && replaces
;i
++)
197 sprintf(&buffer
[j
], "%d%n", editor
->line
+ 1, &nread
);
201 sprintf(&buffer
[j
], "%d%n", hed_line_count(editor
) + 0, &nread
);
206 sprintf(&buffer
[j
], "%d%n", editor
->line
+ 0, &nread
);
210 sprintf(&buffer
[j
], "%d%n", editor
->line
+ 2, &nread
);
214 buffer
[j
++] = argv
[0][i
];
221 /* parse the command */
222 if (strchr(buffer
, ',') != NULL
)
224 if (sscanf(buffer
, "%d,%d%c%d%n", &start
, &stop
, &command
, &target
, &nread
) == 4 && (nread
== strlen(argv
[0])));
225 else if (sscanf(buffer
, "%d,%d%c%n", &start
, &stop
, &command
, &nread
) == 3 && (nread
== strlen(argv
[0])));
228 editor
->last_error
= HED_ERR_SYNTAX_ERROR
;
232 else if (strnumcount(buffer
) > 0)
234 if (sscanf(buffer
, "%d%n", &start
, &nread
) == 1 && nread
== strlen(argv
[0]))
236 else if (sscanf(buffer
, "%d%c%n", &start
, &command
, &nread
) == 2 && nread
== strlen(argv
[0]));
237 else if (sscanf(buffer
, "%d%c%d%n", &start
, &command
, &target
, &nread
) == 3 && nread
== strlen(argv
[0]));
240 editor
->last_error
= HED_ERR_SYNTAX_ERROR
;
247 if (sscanf(buffer
, "%c%n", &command
, &nread
) == 1 && nread
== strlen(argv
[0]));
250 editor
->last_error
= HED_ERR_SYNTAX_ERROR
;
255 /* Change to internal presentation */
260 /* Handle the command */
263 case 'a': /* Append */
264 if (hed_line_count(editor
) == HED_BUFFER_LINES
)
266 editor
->last_error
= HED_ERR_BUFFER_FULL
;
269 if (start
< 0 || stop
> hed_line_count(editor
) || start
> stop
)
271 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
274 editor
->state
= HED_INPUT_APPEND
;
276 case 'i': /* Insert */
277 if (hed_line_count(editor
) == HED_BUFFER_LINES
)
279 editor
->last_error
= HED_ERR_BUFFER_FULL
;
282 if (start
< 0 || stop
>= hed_line_count(editor
) || start
> stop
)
284 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
287 editor
->state
= HED_INPUT_INSERT
;
289 case 'c': /* Replace */
290 if (start
< 0 || stop
>= hed_line_count(editor
) || start
> stop
)
292 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
296 hed_del_line(editor
, start
);
297 editor
->state
= HED_INPUT_INSERT
;
300 case 'd': /* Delete */
301 if (start
< 0 || stop
>= hed_line_count(editor
) || start
> stop
)
303 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
307 for (i
= 0;i
<= stop
- start
;i
++)
308 hed_del_line(editor
, start
);
311 case 'e': /* Open file for editing */
312 case 'E': /* Uncondititional e */
313 editor
->last_error
= HED_ERR_COMMAND_NOT_SUPPORTED
;
316 case 'f': /* View (or set) the filename */
317 helpmod_reply(sender
, returntype
, "Ged: %s", editor
->filename
);
319 case 'h': /* Last error */
320 helpmod_reply(sender
, returntype
, "Ged: %s", hed_error_text(editor
->last_error
));
323 editor
->flags
^= HED_FLAG_VERBOSE_ERRORS
;
325 case 'j': /* Join lines */
326 if ((start
< 0 || start
>= hed_line_count(editor
)) ||
327 (stop
< 0 || stop
>= hed_line_count(editor
)) ||
330 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
334 if (strlen(hed_get_line(editor
, start
)) + strlen(hed_get_line(editor
, stop
)) > 384 - 2)
336 editor
->last_error
= HED_ERR_LINE_TOO_LONG
;
340 strcat(hed_get_line(editor
, start
), hed_get_line(editor
, stop
));
341 hed_del_line(editor
, stop
);
344 case 'l': /* Print */
346 case 'n': /* Print with line numbers */
347 if (start
< 0 || stop
>= hed_line_count(editor
))
349 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
353 for (i
=start
;i
<= stop
;i
++)
355 helpmod_reply(sender
, returntype
, "Ged: %-8d %s", i
+1, hed_get_line(editor
, i
));
357 helpmod_reply(sender
, returntype
, "Ged: %s", hed_get_line(editor
, i
));
360 if (start
< 0 || stop
>= hed_line_count(editor
) || start
> stop
)
362 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
365 if (target
< 0 || target
>= hed_line_count(editor
) - (stop
- start
) ||
366 (target
>= start
&& target
<= stop
))
368 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
372 target
-= (stop
- start
);
374 for (i
= 0;i
<= stop
- start
;i
++)
375 hed_del_line(editor
, start
);
377 hed_paste(editor
, target
);
380 if (editor
->flags
& HED_FLAG_UNSAVED
)
382 editor
->flags
&=~HED_FLAG_UNSAVED
;
383 editor
->last_error
= HED_ERR_UNSAVED
;
392 case 'Q': /* Unconditional quit */
395 case 'r': /* Read from file */
396 editor
->last_error
= HED_ERR_COMMAND_NOT_SUPPORTED
;
399 case 'w': /* Write file */
401 editor
->flags
&=~HED_FLAG_UNSAVED
;
402 helpmod_reply(sender
, returntype
, "Ged: %d", hed_byte_count(editor
));
404 case 'x': /* Paste */
405 if (start
< 0 || start
>= hed_line_count(editor
))
407 editor
->last_error
= HED_ERR_INVALID_ARGUMENT
;
410 if (editor
->clipboard
== NULL
)
412 editor
->last_error
= HED_ERR_CLIPBOARD_EMPTY
;
415 hed_paste(editor
, start
);
417 case '=': /* Current line */
418 helpmod_reply(sender
, returntype
, "Ged: %d", editor
->line
+ 1);
421 editor
->last_error
= HED_ERR_UNKNOWN_COMMAND
;
425 editor
->line
= start
;
434 /* return to command mode */
435 if (!strcmp(ostr
, "."))
437 editor
->state
= HED_COMMAND
;
441 if (hed_line_count(editor
) >= HED_BUFFER_LINES
)
443 editor
->last_error
= HED_ERR_BUFFER_FULL
;
444 editor
->state
= HED_COMMAND
;
448 if (strlen(ostr
) > 384 - 2)
450 editor
->last_error
= HED_ERR_LINE_TOO_LONG
;
454 switch (editor
->state
)
456 case HED_INPUT_INSERT
:
457 str
= hed_add_line(editor
, editor
->line
);
460 case HED_INPUT_APPEND
:
461 /* the last line is handled specially */
462 if (editor
->line
== HED_BUFFER_LINES
- 1)
464 str
= hed_add_line(editor
, editor
->line
+ 1);
474 editor
->last_error
= HED_ERR_NO_ERROR
;
477 if (editor
->flags
& HED_FLAG_VERBOSE_ERRORS
)
478 helpmod_reply(sender
, returntype
, "Ged: %s", hed_error_text(editor
->last_error
));
480 helpmod_reply(sender
, returntype
, "Ged: ?");
483 const char *hed_error_text(hed_error err
)
487 case HED_ERR_NO_ERROR
:
489 case HED_ERR_NO_COMMAND
:
490 return "No command given";
491 case HED_ERR_SYNTAX_ERROR
:
492 return "Syntax error";
493 case HED_ERR_UNKNOWN_COMMAND
:
494 return "Unknown command";
495 case HED_ERR_COMMAND_NOT_SUPPORTED
:
496 return "Unsupported command";
497 case HED_ERR_INVALID_ARGUMENT
:
498 return "Invalid argument";
499 case HED_ERR_LINE_TOO_LONG
:
500 return "Line exceeds 384 characters";
501 case HED_ERR_BUFFER_FULL
:
502 return "Buffer full";
503 case HED_ERR_CLIPBOARD_EMPTY
:
504 return "Nothing to paste";
505 case HED_ERR_UNSAVED
:
506 return "File unsaved, q again to quit";
508 return "Error, please contact strutsi";
512 char* hed_add_line(helpmod_editor
*editor
, int position
)
514 hed_line
**pos
, *tmp
;
515 hed_clear_clipboard(editor
);
517 assert(position
>= 0 && position
< HED_BUFFER_LINES
);
518 assert(hed_line_count(editor
) < HED_BUFFER_LINES
);
519 assert(editor
->free_lines
!= NULL
);
521 editor
->flags
|= HED_FLAG_UNSAVED
;
523 for (pos
= &editor
->start
;*pos
!= NULL
&& position
;pos
= &(*pos
)->next
, position
--);
525 tmp
= editor
->free_lines
;
526 editor
->free_lines
= editor
->free_lines
->next
;
536 void hed_del_line(helpmod_editor
*editor
, int position
)
538 hed_line
**ptr
, **ptr_free
, *tmp
;
539 assert(position
>= 0 && position
< hed_line_count(editor
));
541 editor
->flags
|= HED_FLAG_UNSAVED
;
543 for (ptr
= &editor
->start
;position
;ptr
= &(*ptr
)->next
, position
--);
548 for (ptr_free
= &editor
->clipboard
;*ptr_free
;ptr_free
= &(*ptr_free
)->next
);
554 char* hed_get_line(helpmod_editor
*editor
, int position
)
557 assert(position
>= 0 && position
< hed_line_count(editor
));
559 for (ptr
= editor
->start
;position
--;ptr
= ptr
->next
);
563 void hed_clear_clipboard(helpmod_editor
*editor
)
566 for (ptr
= &editor
->clipboard
;*ptr
!= NULL
;ptr
= &(*ptr
)->next
);
567 (*ptr
) = editor
->free_lines
;
568 editor
->free_lines
= editor
->clipboard
;
569 editor
->clipboard
= NULL
;
572 void hed_paste(helpmod_editor
*editor
, int position
)
574 hed_line
**ptr
, **ptr_clipboard
;
576 assert(position
>= 0 && position
<= hed_line_count(editor
));
577 editor
->flags
|= HED_FLAG_UNSAVED
;
579 for (ptr
= &editor
->start
;position
;ptr
= &(*ptr
)->next
, position
--);
580 for (ptr_clipboard
= &editor
->clipboard
;*ptr_clipboard
!= NULL
;ptr_clipboard
= &(*ptr_clipboard
)->next
);
582 *ptr_clipboard
= *ptr
;
583 *ptr
= editor
->clipboard
;
585 editor
->clipboard
= NULL
;