Fixed capitalisation typo.
[AROS.git] / rom / devs / console / stdconclass.c
blob545ccb1c6efaf9d873ff89893b99d14eb08dbf66
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Code for CONU_STANDARD console units.
6 Lang: english
7 */
8 #include <string.h>
10 #include <proto/graphics.h>
11 #include <proto/intuition.h>
12 #include <intuition/intuition.h>
13 #include <graphics/rastport.h>
14 #include <exec/rawfmt.h>
15 #include <aros/asmcall.h>
17 #define SDEBUG 0
18 #define DEBUG 0
19 #include <aros/debug.h>
21 #include "console_gcc.h"
22 #include "consoleif.h"
25 struct stdcondata
27 struct DrawInfo *dri;
28 WORD rendercursorcount;
29 BOOL cursorvisible;
31 /* Libraries */
32 struct Library *scd_GfxBase;
36 #undef ConsoleDevice
37 #define ConsoleDevice ((struct ConsoleBase *)cl->cl_UserData)
39 /*********** StdCon::New() **********************/
41 static Object *stdcon_new(Class *cl, Object *o, struct opSet *msg)
43 EnterFunc(bug("StdCon::New()\n"));
44 o = (Object *)DoSuperMethodA(cl, o, (Msg)msg);
45 if (o)
47 struct stdcondata *data = INST_DATA(cl, o);
48 ULONG dispmid = OM_DISPOSE;
49 /* Clear for checking inside dispose() whether stuff was allocated.
50 Basically this is bug-prevention.
52 memset(data, 0, sizeof (struct stdcondata));
54 data->scd_GfxBase = TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS);
55 if (data->scd_GfxBase) {
56 data->dri = GetScreenDrawInfo(CU(o)->cu_Window->WScreen);
57 if (data->dri)
59 CU(o)->cu_BgPen = data->dri->dri_Pens[BACKGROUNDPEN];
60 CU(o)->cu_FgPen = data->dri->dri_Pens[TEXTPEN];
62 data->cursorvisible = TRUE;
63 Console_RenderCursor(o);
65 ReturnPtr("StdCon::New", Object *, o);
68 CoerceMethodA(cl, o, (Msg)&dispmid);
70 ReturnPtr("StdCon::New", Object *, NULL);
74 /*********** StdCon::Dispose() **************************/
76 static VOID stdcon_dispose(Class *cl, Object *o, Msg msg)
78 struct stdcondata *data= INST_DATA(cl, o);
80 if (data->scd_GfxBase)
81 CloseLibrary(data->scd_GfxBase);
83 if (data->dri)
84 FreeScreenDrawInfo(CU(o)->cu_Window->WScreen, data->dri);
86 /* Let superclass free its allocations */
87 DoSuperMethodA(cl, o, msg);
89 return;
92 VOID setabpen(struct Library *GfxBase, struct RastPort *rp, UBYTE tflags, UBYTE FgPen, UBYTE BgPen)
94 UBYTE fg = FgPen, bg = BgPen;
95 UBYTE style = JAM2;
97 if (tflags & CON_TXTFLAGS_CONCEALED)
98 fg = bg;
99 else if (tflags & CON_TXTFLAGS_REVERSED)
100 style |= INVERSVID;
101 SetABPenDrMd(rp, fg, bg, style);
104 static void setstyle(struct Library *GfxBase, struct RastPort *rp, Object *o)
106 UBYTE tflags = CU(o)->cu_TxFlags;
107 setabpen(GfxBase, rp, tflags, CU(o)->cu_FgPen, CU(o)->cu_BgPen);
108 SetSoftStyle(rp, tflags, CON_TXTFLAGS_MASK);
111 /********* StdCon::DoCommand() ****************************/
113 static VOID stdcon_docommand(Class *cl, Object *o, struct P_Console_DoCommand *msg)
116 struct Window *w = CU(o)->cu_Window;
117 struct RastPort *rp = w->RPort;
118 IPTR *params = msg->Params;
119 struct stdcondata *data = INST_DATA(cl, o);
120 struct Library *GfxBase = data->scd_GfxBase;
122 EnterFunc(bug("StdCon::DoCommand(o=%p, cmd=%d, params=%p)\n",
123 o, msg->Command, params));
125 switch (msg->Command)
127 case C_NIL:
128 /* do nothing */
129 break;
131 case C_ASCII:
133 D(bug("Writing char %c at (%d, %d)\n",
134 params[0], CP_X(o), CP_Y(o) + rp->Font->tf_Baseline));
136 Console_UnRenderCursor(o);
138 setstyle(GfxBase, rp, o);
139 Move(rp,CP_X(o),CP_Y(o)+rp->Font->tf_Baseline);
141 UBYTE c = params[0];
142 Text(rp, &c,1);
145 Console_Right(o, 1);
147 /* Rerender the cursor */
148 Console_RenderCursor(o);
150 break;
152 case C_ASCII_STRING:
154 D(bug("Writing string %.*s at (%d, %d)\n",
155 (int)params[1], (char *)params[0], CP_X(o), CP_Y(o) + rp->Font->tf_Baseline));
157 Console_UnRenderCursor(o);
159 setstyle(GfxBase, rp, o);
162 ULONG len = params[1];
163 STRPTR str = (STRPTR)params[0];
165 while (len)
167 ULONG remaining_space = CHAR_XMAX(o)+1-XCCP;
168 ULONG line_len = len < remaining_space ? len : remaining_space;
170 Move(rp, CP_X(o), CP_Y(o) + rp->Font->tf_Baseline);
171 Text(rp, str, line_len);
173 Console_Right(o, line_len);
175 len -= line_len;
176 str += line_len;
180 /* Rerender the cursor */
181 Console_RenderCursor(o);
183 break;
184 case C_FORMFEED:
186 /* Clear the console */
188 UBYTE oldpen = rp->FgPen;
189 IPTR newcurpos[2] = {0,0};
191 Console_UnRenderCursor(o);
193 SetAPen( rp, CU(o)->cu_BgPen );
194 RectFill(rp
195 ,CU(o)->cu_XROrigin
196 ,CU(o)->cu_YROrigin
197 ,CU(o)->cu_XRExtant
198 ,CU(o)->cu_YRExtant);
200 SetAPen(rp, oldpen);
202 Console_DoCommand(o, C_CURSOR_POS, 2, newcurpos);
204 Console_RenderCursor(o);
206 break;
209 case C_BELL:
210 /* !!! maybe trouble with LockLayers() here !!! */
211 // DisplayBeep(CU(o)->cu_Window->WScreen);
212 break;
214 case C_BACKSPACE:
215 Console_UnRenderCursor(o);
216 Console_Left(o, 1);
217 Console_RenderCursor(o);
218 break;
220 case C_CURSOR_BACKWARD:
221 Console_UnRenderCursor(o);
222 Console_Left(o, params[0]);
223 Console_RenderCursor(o);
224 break;
226 case C_CURSOR_FORWARD:
227 Console_UnRenderCursor(o);
228 Console_Right(o, params[0]);
229 Console_RenderCursor(o);
230 break;
232 case C_DELETE_CHAR: /* FIXME: can it have params!? */
234 UBYTE oldpen = rp->FgPen;
235 Console_UnRenderCursor(o);
236 SetAPen(rp, CU(o)->cu_BgPen);
237 ScrollRaster(rp,
238 XRSIZE,
240 GFX_X(o, XCP),
241 GFX_Y(o, YCP),
242 GFX_XMAX(o),
243 GFX_Y(o, YCP+1));
244 SetAPen(rp, oldpen);
245 Console_RenderCursor(o);
247 break;
248 Console_RenderCursor(o);
249 break;
251 case C_HTAB:
253 WORD x = XCCP, i = 0;
255 while( (CU(o)->cu_TabStops[i] != (UWORD)-1) &&
256 (CU(o)->cu_TabStops[i] <= x) )
258 i++;
260 if (CU(o)->cu_TabStops[i] != (UWORD)-1)
262 Console_UnRenderCursor(o);
263 Console_Right(o, CU(o)->cu_TabStops[i] - x);
264 Console_RenderCursor(o);
266 break;
269 case C_CURSOR_HTAB:
271 WORD i = params[0];
275 IPTR dummy;
277 Console_DoCommand(o, C_HTAB, 0, &dummy);
279 } while (--i > 0);
280 break;
283 case C_CURSOR_BACKTAB:
285 WORD count = params[0];
287 Console_UnRenderCursor(o);
291 WORD x = XCCP, i = 0;
293 while( (CU(o)->cu_TabStops[i] != (UWORD)-1) &&
294 (CU(o)->cu_TabStops[i] < x) )
296 i++;
299 i--;
301 if (i >= 0) if (CU(o)->cu_TabStops[i] != (UWORD)-1)
303 Console_Left(o, x - CU(o)->cu_TabStops[i]);
306 } while (--count > 0);
308 Console_RenderCursor(o);
310 break;
313 case C_LINEFEED:
314 D(bug("Got linefeed command\n"));
315 /*Console_ClearCell(o, XCCP, YCCP);*/
316 Console_UnRenderCursor(o);
318 Console_Down(o, 1);
320 /* Check for linefeed mode (LF or LF+CR) */
322 D(bug("conflags: %d\n", ICU(o)->conFlags));
324 /* if (ICU(o)->conFlags & CF_LF_MODE_ON) */
325 if (CHECK_MODE(o, M_LNM))
327 CU(o)->cu_XCP = CHAR_XMIN(o);
328 CU(o)->cu_XCCP = CHAR_XMIN(o);
330 Console_RenderCursor(o);
331 break;
333 case C_CURSOR_PREV_LINE:
334 Console_UnRenderCursor(o);
335 CU(o)->cu_XCP = CHAR_XMIN(o);
336 CU(o)->cu_XCCP = CHAR_XMIN(o);
337 Console_Up(o, 1);
338 Console_RenderCursor(o);
339 break;
341 case C_CURSOR_UP:
342 case C_VTAB:
343 Console_UnRenderCursor(o);
344 Console_Up(o, 1);
345 Console_RenderCursor(o);
346 break;
348 case C_CURSOR_NEXT_LINE:
349 Console_UnRenderCursor(o);
350 CU(o)->cu_XCP = CHAR_XMIN(o);
351 CU(o)->cu_XCCP = CHAR_XMIN(o);
352 Console_Down(o, 1);
353 Console_RenderCursor(o);
354 break;
356 case C_CURSOR_DOWN:
357 Console_UnRenderCursor(o);
358 Console_Down(o, 1);
359 Console_RenderCursor(o);
360 break;
362 case C_CARRIAGE_RETURN:
363 /* Goto start of line */
365 Console_UnRenderCursor(o);
366 CU(o)->cu_XCP = CHAR_XMIN(o);
367 CU(o)->cu_XCCP = CHAR_XMIN(o);
368 Console_RenderCursor(o);
369 break;
372 case C_INDEX:
373 Console_Down(o, 1);
374 break;
376 case C_NEXT_LINE:
377 D(bug("Got NEXT LINE cmd\n"));
378 Console_Down(o, 1);
379 Console_Left(o, XCP);
380 break;
382 case C_REVERSE_IDX:
383 Console_Up(o, 1);
384 break;
386 case C_CURSOR_POS:
388 WORD y = ((WORD)params[0]) - 1;
389 WORD x = ((WORD)params[1]) - 1;
391 if (x < CHAR_XMIN(o))
393 x = CHAR_XMIN(o);
395 else if (x > CHAR_XMAX(o))
397 x = CHAR_XMAX(o);
400 if (y < CHAR_YMIN(o))
402 y = CHAR_YMIN(o);
404 else if (y > CHAR_YMAX(o))
406 y = CHAR_YMAX(o);
409 Console_UnRenderCursor(o);
411 XCCP = XCP = x;
412 YCCP = YCP = y;
414 Console_RenderCursor(o);
415 break;
418 case C_ERASE_IN_LINE:
420 /*UBYTE param = 1;*/
421 UBYTE oldpen = rp->FgPen;
423 Console_UnRenderCursor(o);
425 /* Clear till EOL */
427 SetAPen( rp, CU(o)->cu_BgPen );
428 SetDrMd( rp, JAM2);
430 RectFill(rp
431 ,CU(o)->cu_XROrigin + XCP * XRSIZE
432 ,CU(o)->cu_YROrigin + YCP * YRSIZE
433 ,CU(o)->cu_XRExtant
434 ,CU(o)->cu_YROrigin + (YCP + 1) * YRSIZE - 1);
437 SetAPen(rp, oldpen);
439 Console_RenderCursor(o);
441 } break;
443 case C_ERASE_IN_DISPLAY:
445 IPTR param = 1;
446 UBYTE oldpen = rp->FgPen;
448 /* Clear till EOL */
449 Console_DoCommand(o, C_ERASE_IN_LINE, 1, &param);
451 /* Clear rest of area */
453 Console_UnRenderCursor(o);
455 SetAPen( rp, CU(o)->cu_BgPen );
456 SetDrMd( rp, JAM2);
458 RectFill(rp
459 ,CU(o)->cu_XROrigin
460 ,CU(o)->cu_YROrigin + (YCP + 1) * YRSIZE
461 ,CU(o)->cu_XRExtant
462 ,CU(o)->cu_YRExtant);
464 SetAPen(rp, oldpen);
466 Console_RenderCursor(o);
468 break;
471 case C_INSERT_CHAR:
473 UBYTE oldpen = rp->FgPen;
474 Console_UnRenderCursor(o);
475 SetAPen(rp, CU(o)->cu_BgPen);
476 ScrollRaster(rp,
477 -XRSIZE,
479 GFX_X(o, XCP),
480 GFX_Y(o, YCP),
481 GFX_XMAX(o),
482 GFX_Y(o, YCP+1));
483 SetAPen(rp, oldpen);
484 Console_RenderCursor(o);
486 break;
487 case C_INSERT_LINE:
489 UBYTE oldpen = rp->FgPen;
491 Console_UnRenderCursor(o);
492 SetAPen(rp, CU(o)->cu_BgPen);
494 ScrollRaster(rp,
496 -YRSIZE,
497 GFX_XMIN(o),
498 GFX_Y(o, YCP),
499 GFX_XMAX(o),
500 GFX_YMAX(o));
502 SetAPen(rp, oldpen);
504 Console_RenderCursor(o);
505 break;
508 case C_DELETE_LINE:
510 UBYTE oldpen = rp->FgPen;
512 Console_UnRenderCursor(o);
513 SetAPen(rp, CU(o)->cu_BgPen);
515 ScrollRaster(rp,
517 YRSIZE,
518 GFX_XMIN(o),
519 GFX_Y(o, YCP),
520 GFX_XMAX(o),
521 GFX_YMAX(o));
523 SetAPen(rp, oldpen);
525 Console_RenderCursor(o);
526 break;
529 case C_SCROLL_UP:
531 UBYTE oldpen = rp->FgPen;
533 D(bug("C_SCROLL_UP area (%d, %d) to (%d, %d), %d\n",
534 GFX_XMIN(o), GFX_YMIN(o), GFX_XMAX(o), GFX_YMAX(o), YRSIZE * params[0]));
536 Console_UnRenderCursor(o);
538 SetAPen( rp, CU(o)->cu_BgPen );
539 /* FIXME: LockLayers problem here ? */
540 ScrollRaster(rp
542 , YRSIZE * params[0]
543 , GFX_XMIN(o)
544 , GFX_YMIN(o)
545 , GFX_XMAX(o)
546 , GFX_YMAX(o) );
547 SetAPen(rp, oldpen);
549 Console_RenderCursor(o);
551 break;
554 case C_SCROLL_DOWN:
556 UBYTE oldpen = rp->FgPen;
558 D(bug("C_SCROLL_DOWN area (%d, %d) to (%d, %d), %d\n",
559 GFX_XMIN(o), GFX_YMIN(o), GFX_XMAX(o), GFX_YMAX(o), YRSIZE * params[0]));
561 Console_UnRenderCursor(o);
563 SetAPen( rp, CU(o)->cu_BgPen );
564 /* FIXME: LockLayers problem here ? */
565 ScrollRaster(rp
567 , -YRSIZE * params[0]
568 , GFX_XMIN(o)
569 , GFX_YMIN(o)
570 , GFX_XMAX(o)
571 , GFX_YMAX(o) );
572 SetAPen(rp, oldpen);
574 Console_RenderCursor(o);
576 break;
579 case C_CURSOR_VISIBLE:
580 if (!data->cursorvisible)
582 data->cursorvisible = TRUE;
583 data->rendercursorcount--;
584 Console_RenderCursor(o);
586 break;
588 case C_CURSOR_INVISIBLE:
589 if (data->cursorvisible)
591 Console_UnRenderCursor(o);
592 data->cursorvisible = FALSE;
593 data->rendercursorcount++;
595 break;
597 case C_SET_TOP_OFFSET:
598 Console_UnRenderCursor(o);
599 CU(o)->cu_YROrigin = params[0];
600 CU(o)->cu_YMax = (w->Height - (CU(o)->cu_YROrigin + w->BorderBottom)) / CU(o)->cu_YRSize - 1;
601 Console_RenderCursor(o);
602 Console_NewWindowSize(o);
603 break;
605 case C_SET_PAGE_LENGTH:
606 Console_UnRenderCursor(o);
607 CU(o)->cu_YMax = params[0];
608 // FIXME: Need to set something that prevents NewWindowSize to change YMax
609 Console_RenderCursor(o);
610 Console_NewWindowSize(o);
611 break;
613 case C_WINDOW_STATUS_REQUEST:
615 UBYTE reply[32];
616 NewRawDoFmt("\x9b""1;1;%d;%d r", RAWFMTFUNC_STRING, reply, CU(o)->cu_YMax, CU(o)->cu_XMax);
617 con_inject((struct ConsoleBase *)cl->cl_UserData, CU(o), reply, -1);
618 break;
621 case C_DEVICE_STATUS_REPORT:
623 UBYTE reply[32];
624 NewRawDoFmt("\x9b""%d;%dR", RAWFMTFUNC_STRING, reply, CU(o)->cu_YCP, CU(o)->cu_XCP);
625 con_inject((struct ConsoleBase *)cl->cl_UserData, CU(o), reply, -1);
626 break;
629 default:
630 DoSuperMethodA(cl, o, (Msg)msg);
631 break;
634 ReturnVoid("StdCon::DoCommand");
637 /********* StdCon::RenderCursor() ****************************/
638 static VOID stdcon_rendercursor(Class *cl, Object *o, struct P_Console_RenderCursor *msg)
640 struct RastPort *rp = RASTPORT(o);
641 struct stdcondata *data = INST_DATA(cl, o);
642 struct Library *GfxBase = data->scd_GfxBase;
644 /* SetAPen(rp, data->dri->dri_Pens[FILLPEN]); */
646 data->rendercursorcount++;
648 if (data->cursorvisible && (data->rendercursorcount == 1))
650 SetDrMd(rp, COMPLEMENT);
651 RectFill(rp
652 , CP_X(o)
653 , CP_Y(o)
654 , CP_X(o) + XRSIZE - 1
655 , CP_Y(o) + YRSIZE - 1
657 SetDrMd(rp, JAM2);
661 /********* StdCon::UnRenderCursor() ****************************/
662 static VOID stdcon_unrendercursor(Class *cl, Object *o, struct P_Console_UnRenderCursor *msg)
664 struct RastPort *rp = RASTPORT(o);
665 struct stdcondata *data = INST_DATA(cl, o);
666 struct Library *GfxBase = data->scd_GfxBase;
668 data->rendercursorcount--;
670 /* SetAPen(rp, data->dri->dri_Pens[FILLPEN]); */
672 if (data->cursorvisible && (data->rendercursorcount == 0))
674 SetDrMd(rp, COMPLEMENT);
675 RectFill(rp
676 , CP_X(o)
677 , CP_Y(o)
678 , CP_X(o) + XRSIZE - 1
679 , CP_Y(o) + YRSIZE - 1
681 SetDrMd(rp, JAM2);
685 /**************************
686 ** StdCon::ClearCell() **
687 **************************/
688 static VOID stdcon_clearcell(Class *cl, Object *o, struct P_Console_ClearCell *msg)
690 struct RastPort *rp = RASTPORT(o);
691 struct stdcondata *data = INST_DATA(cl, o);
692 struct Library *GfxBase = data->scd_GfxBase;
694 SetAPen(rp, data->dri->dri_Pens[BACKGROUNDPEN]);
695 SetDrMd(rp, JAM1);
696 RectFill(rp
697 , GFX_X(o, msg->X)
698 , GFX_Y(o, msg->Y)
699 , GFX_X(o, msg->X) + XRSIZE - 1
700 , GFX_Y(o, msg->Y) + YRSIZE - 1
704 /*******************************
705 ** StdCon::NewWindowSize() **
706 *******************************/
707 static VOID stdcon_newwindowsize(Class *cl, Object *o, struct P_Console_NewWindowSize *msg)
709 struct RastPort *rp = RASTPORT(o);
710 struct stdcondata *data = INST_DATA(cl, o);
711 struct Library *GfxBase = data->scd_GfxBase;
712 WORD old_xmax = CHAR_XMAX(o);
713 WORD old_ymax = CHAR_YMAX(o);
714 WORD old_xcp = XCP;
715 WORD old_ycp = YCP;
717 WORD x1, y1, x2, y2;
719 DoSuperMethodA(cl, o, (Msg)msg);
721 if (CHAR_XMAX(o) < old_xmax)
723 x1 = GFX_XMAX(o) + 1;
724 y1 = GFX_YMIN(o);
725 x2 = GFX_XMAX(o);
726 y2 = GFX_YMAX(o) -1;
728 if ((x2 >= x1) && (y2 >= y1))
730 SetAPen(rp, 0);
731 SetDrMd(rp, JAM2),
732 RectFill(rp, x1, y1, x2, y2);
736 if (CHAR_YMAX(o) < old_ymax)
738 x1 = GFX_XMIN(o);
739 y1 = GFX_YMAX(o) + 1;
740 x2 = WINDOW(o)->Width - WINDOW(o)->BorderRight - 1;
741 y2 = WINDOW(o)->Height - WINDOW(o)->BorderBottom - 1;
743 if ((x2 >= x1) && (y2 >= y1))
745 SetAPen(rp, 0);
746 SetDrMd(rp, JAM2),
747 RectFill(rp, x1, y1, x2, y2);
751 if ((old_xcp != XCP) || (old_ycp != YCP))
753 SetAPen(rp, 0);
754 SetDrMd(rp, JAM2);
755 RectFill(rp, GFX_XMIN(o), GFX_YMIN(o), GFX_XMAX(o), GFX_YMAX(o));
756 data->rendercursorcount--;
757 Console_RenderCursor(o);
759 return;
764 AROS_UFH3S(IPTR, dispatch_stdconclass,
765 AROS_UFHA(Class *, cl, A0),
766 AROS_UFHA(Object *, o, A2),
767 AROS_UFHA(Msg, msg, A1)
770 AROS_USERFUNC_INIT
772 IPTR retval = 0UL;
774 switch (msg->MethodID)
776 case OM_NEW:
777 retval = (IPTR)stdcon_new(cl, o, (struct opSet *)msg);
778 break;
780 case OM_DISPOSE:
781 stdcon_dispose(cl, o, msg);
782 break;
784 case M_Console_DoCommand:
785 stdcon_docommand(cl, o, (struct P_Console_DoCommand *)msg);
786 break;
788 case M_Console_RenderCursor:
789 stdcon_rendercursor(cl, o, (struct P_Console_RenderCursor *)msg);
790 break;
792 case M_Console_UnRenderCursor:
793 stdcon_unrendercursor(cl, o, (struct P_Console_UnRenderCursor *)msg);
794 break;
796 case M_Console_ClearCell:
797 stdcon_clearcell(cl, o, (struct P_Console_ClearCell *)msg);
798 break;
800 case M_Console_NewWindowSize:
801 stdcon_newwindowsize(cl, o, (struct P_Console_NewWindowSize *)msg);
802 break;
804 default:
805 retval = DoSuperMethodA(cl, o, msg);
806 break;
809 return retval;
811 AROS_USERFUNC_EXIT
814 #undef ConsoleDevice
816 Class *makeStdConClass(struct ConsoleBase *ConsoleDevice)
819 Class *cl;
821 cl = MakeClass(NULL, NULL ,CONSOLECLASSPTR , sizeof(struct stdcondata), 0UL);
822 if (cl)
824 cl->cl_Dispatcher.h_Entry = (APTR)dispatch_stdconclass;
825 cl->cl_Dispatcher.h_SubEntry = NULL;
827 cl->cl_UserData = (IPTR)ConsoleDevice;
829 return (cl);
831 return (NULL);