+ int *iData = Data;
+ int ret;
+ tVTerm *term = Node->ImplPtr;
+ ENTER("pNode iId pData", Node, Id, Data);
+
+ if(Id >= DRV_IOCTL_LOOKUP) {
+ // Only root can fiddle with graphics modes
+ // TODO: Remove this and replace with user ownership
+ if( Threads_GetUID() != 0 ) return -1;
+ }
+
+ switch(Id)
+ {
+ // --- Core Defined
+ case DRV_IOCTL_TYPE:
+ LEAVE('i', DRV_TYPE_TERMINAL);
+ return DRV_TYPE_TERMINAL;
+ case DRV_IOCTL_IDENT:
+ memcpy(Data, "VT\0\0", 4);
+ LEAVE('i', 0);
+ return 0;
+ case DRV_IOCTL_VERSION:
+ LEAVE('x', VERSION);
+ return VERSION;
+ case DRV_IOCTL_LOOKUP:
+ LEAVE('i', 0);
+ return 0;
+
+ // Get/Set the mode (and apply any changes)
+ case TERM_IOCTL_MODETYPE:
+ if(Data != NULL)
+ {
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ Log_Log("VTerm", "VTerm %i mode set to %i", (int)Node->Inode, *iData);
+
+ // Update mode if needed
+ if( term->Mode != *iData
+ || term->Width != term->NewWidth
+ || term->Height != term->NewHeight)
+ {
+ VT_int_ChangeMode(term, *iData, term->NewWidth, term->NewHeight);
+ }
+
+ // Update the screen dimensions
+ if(Node->Inode == giVT_CurrentTerminal)
+ VT_SetTerminal( giVT_CurrentTerminal );
+ }
+ LEAVE('i', term->Mode);
+ return term->Mode;
+
+ // Get/set the terminal width
+ case TERM_IOCTL_WIDTH:
+ if(Data != NULL) {
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ term->NewWidth = *iData;
+ }
+ if( term->NewWidth )
+ ret = term->NewWidth;
+ else if( term->Mode == TERM_MODE_TEXT )
+ ret = term->TextWidth;
+ else
+ ret = term->Width;
+ LEAVE('i', ret);
+ return ret;
+
+ // Get/set the terminal height
+ case TERM_IOCTL_HEIGHT:
+ if(Data != NULL) {
+ if( CheckMem(Data, sizeof(int)) == 0 ) {
+ LEAVE('i', -1);
+ return -1;
+ }
+ term->NewHeight = *iData;
+ }
+ if( term->NewHeight )
+ ret = term->NewHeight;
+ else if( term->Mode == TERM_MODE_TEXT )
+ ret = term->TextHeight = *iData;
+ else
+ ret = term->Height;
+ LEAVE('i', ret);
+ return ret;
+
+ case TERM_IOCTL_FORCESHOW:
+ Log_Log("VTerm", "Thread %i forced VTerm %i to be shown",
+ Threads_GetTID(), (int)Node->Inode);
+ VT_SetTerminal( Node->Inode );
+ LEAVE('i', 1);
+ return 1;
+ }
+ LEAVE('i', -1);
+ return -1;
+}
+
+void VT_SetResolution(int Width, int Height)
+{
+ tVideo_IOCtl_Mode mode = {0};
+ int tmp;
+ int i;
+
+ // Create the video mode
+ mode.width = Width;
+ mode.height = Height;
+ mode.bpp = 32;
+ mode.flags = 0;
+
+ // Set video mode
+ VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode );
+ tmp = mode.id;
+ if( Width != mode.width || Height != mode.height )
+ {
+ Log_Warning("VTerm",
+ "Selected resolution (%ix%i is not supported) by the device, using (%ix%i)",
+ giVT_RealWidth, giVT_RealHeight,
+ mode.width, mode.height
+ );
+ }
+ VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &tmp );
+
+ // Resize text terminals if needed
+ if( giVT_RealWidth != mode.width || giVT_RealHeight != mode.height )
+ {
+ int newBufSize = (giVT_RealWidth/giVT_CharWidth)
+ *(giVT_RealHeight/giVT_CharHeight)
+ *(giVT_Scrollback+1);
+ //tVT_Char *tmp;
+ // Resize the text terminals
+ giVT_RealWidth = mode.width;
+ giVT_RealHeight = mode.height;
+ for( i = 0; i < NUM_VTS; i ++ )
+ {
+ if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue;
+
+ gVT_Terminals[i].Text = realloc(
+ gVT_Terminals[i].Text,
+ newBufSize*sizeof(tVT_Char)
+ );
+ }
+ }
+}
+
+void VT_SetMode(int Mode)
+{
+ VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &Mode );