X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fdrv%2Fvterm_2d.c;h=086c2b4f37190aa9e4e4e450b1bbcf7f105c3d02;hb=2238e69eea50d2274553926f3f294822c1972ff0;hp=3994525f66b34efc37212fc95e13d92362573133;hpb=e7a76b0d8a0cc6aa77966509780973a6f8216ef7;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/drv/vterm_2d.c b/KernelLand/Kernel/drv/vterm_2d.c index 3994525f..086c2b4f 100644 --- a/KernelLand/Kernel/drv/vterm_2d.c +++ b/KernelLand/Kernel/drv/vterm_2d.c @@ -14,16 +14,16 @@ void VT_int_SetCursorBitmap(tVTerm *Term, int W, int H); size_t VT_int_FillCursorBitmap(tVTerm *Term, size_t DataOfs, size_t Length, const void *Data); int VT_int_2DCmd_SetCursorPos(void *Handle, size_t Offset, size_t Length, const void *Data); int VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, const void *Data); + int VT_int_2DCmd_SendData(void *Handle, size_t Offset, size_t Length, const void *Data); // === CODE === void VT_int_SetCursorPos(tVTerm *Term, int X, int Y) { if( Term->Mode == PTYBUFFMT_TEXT ) { - if(Term->Flags & VT_FLAG_ALTBUF) - Term->AltWritePos = X + Y * Term->TextWidth; - else - Term->WritePos = X + Y * Term->TextWidth + Term->ViewPos; + tVT_Pos *wrpos = VT_int_GetWritePosPtr(Term); + wrpos->Row = X; + wrpos->Col = Y + (Term->Flags & VT_FLAG_ALTBUF ? 0 : Term->ViewTopRow); VT_int_UpdateCursor(Term, 0); } else @@ -103,18 +103,15 @@ int VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, con Length -= ret; Data = (const char*)Data + ret; Offset += ret; - if( Length == 0 ) - return -ret; } + + ASSERTC(Offset, >=, sizeof(cmd)); - - if( Offset < sizeof(cmd) ) { - // oops? - return ret; + if( Length > 0 ) + { + ret += VT_int_FillCursorBitmap(Handle, Offset - sizeof(cmd), Length, Data); } - ret += VT_int_FillCursorBitmap(Handle, Offset - sizeof(cmd), Length, Data); - LOG("%i + %i ==? %i", ret, Offset, term->Cmd2D.CurrentSize); if( ret + Offset >= term->Cmd2D.CurrentSize ) return ret; @@ -122,6 +119,46 @@ int VT_int_2DCmd_SetCursorBitmap(void *Handle, size_t Offset, size_t Length, con return -ret; } +int VT_int_2DCmd_SendData(void *Handle, size_t Offset, size_t Length, const void *Data) +{ + tVTerm *term = Handle; + struct ptycmd_senddata cmd; + size_t ret = 0; + + if( Offset == 0 ) + { + if( Length < sizeof(cmd) ) + return 0; + memcpy(&cmd, Data, sizeof(cmd)); + + ret = sizeof(cmd); + Offset += ret; + Length -= ret; + Data = (const char*)Data + ret; + + term->Cmd2D.CmdInfo.Push.Offset = cmd.ofs*4; + } + + ASSERTC(Offset, >=, sizeof(cmd)); + + if( Length > 0 ) + { + size_t bytes = MIN(term->Width*term->Height*4 - term->Cmd2D.CmdInfo.Push.Offset, Length); + LOG("bytes = %i (0x%x), Length = %i", bytes, bytes, Length); + + VT_int_PutFBData(term, term->Cmd2D.CmdInfo.Push.Offset, bytes, Data ); + term->Cmd2D.CmdInfo.Push.Offset += bytes; + ret += bytes; + + LOG("bytes(%i) ==? 0 || ret(%i) + Offset(%i) ==? %i", + bytes, ret, Offset, term->Cmd2D.CurrentSize); + if( bytes == 0 || ret + Offset >= term->Cmd2D.CurrentSize ) + return ret; + } + + return -ret; +} + // > 0: Command complete // = 0: Not enough data to start // < 0: Ate -n bytes, still need more @@ -129,6 +166,7 @@ typedef int (*tVT_2DCmdHandler)(void *Handle, size_t Offset, size_t Length, cons tVT_2DCmdHandler gVT_2DCmdHandlers[] = { [PTY2D_CMD_SETCURSORPOS] = VT_int_2DCmd_SetCursorPos, [PTY2D_CMD_SETCURSORBMP] = VT_int_2DCmd_SetCursorBitmap, + [PTY2D_CMD_SEND] = VT_int_2DCmd_SendData, }; const int ciVT_Num2DCmdHandlers = sizeof(gVT_2DCmdHandlers)/sizeof(gVT_2DCmdHandlers[0]); @@ -138,7 +176,7 @@ void VT_int_Handle2DCmd(void *Handle, size_t Length, const void *Data) tVTerm *term = Handle; LOG("Length = 0x%x", Length); - // If a command terminated early, we have to clean up its data + // If a command didn't consume all the data it said it would, we have to clean up _eat: if( term->Cmd2D.PreEat ) { @@ -165,7 +203,10 @@ _eat: } // else begin a new command else - { + { + // If the new data would fit in the cache, or the cache is already populated + // use the cache + // - The cache should fit the header for every command, so all good if( Length < cachesize || term->Cmd2D.CachePos != 0 ) { adjust = term->Cmd2D.CachePos; @@ -175,25 +216,33 @@ _eat: dataptr = (void*)term->Cmd2D.Cache; len = term->Cmd2D.CachePos; } - else { + else + { dataptr = (void*)bdata; len = Length; adjust = 0; } const struct ptycmd_header *hdr = dataptr; - if( len < sizeof(*hdr) ) { + // If there's not enough for the common header, wait for more + if( len < sizeof(*hdr) ) + { return ; } + // Parse header term->Cmd2D.Offset = 0; term->Cmd2D.Current = hdr->cmd; term->Cmd2D.CurrentSize = (hdr->len_low | (hdr->len_hi << 8)) * 4; - if( term->Cmd2D.CurrentSize == 0 ) + if( term->Cmd2D.CurrentSize == 0 ) { + Log_Warning("VTerm", "Command size too small (==0)"); term->Cmd2D.CurrentSize = 2; + } LOG("Started %i with %s data", term->Cmd2D.Current, (dataptr == bdata ? "direct" : "cache")); } + + // Sanity check if( term->Cmd2D.Current >= ciVT_Num2DCmdHandlers || !gVT_2DCmdHandlers[term->Cmd2D.Current] ) { Log_Notice("VTerm", "2D Comand %i not handled", term->Cmd2D.Current); @@ -204,42 +253,60 @@ _eat: term->Cmd2D.PreEat = term->Cmd2D.CurrentSize; goto _eat; } - else + + const tVT_2DCmdHandler* handler = &gVT_2DCmdHandlers[term->Cmd2D.Current]; + #if 0 + if( term->Cmd2D.Offset == 0 ) { - int rv = gVT_2DCmdHandlers[term->Cmd2D.Current](Handle, term->Cmd2D.Offset, len, dataptr); - LOG("2DCmd %i: rv=%i", term->Cmd2D.Current, rv); - if( rv == 0 && term->Cmd2D.Offset == 0 ) { - // 0: Not enough data for header - ASSERT( term->Cmd2D.CachePos != cachesize ); - // Clear current command because this command hasn't started yet - term->Cmd2D.Current = 0; - // Return, restart happens once all data is ready + if( len < handler->HeaderLength ) { return ; } - size_t used_bytes = (rv < 0 ? -rv : rv) - adjust; - Length -= used_bytes; - bdata += used_bytes; - term->Cmd2D.CachePos = 0; - if( rv < 0 ) { - ASSERT( -rv <= len ); - LOG(" Incomplete"); - term->Cmd2D.Offset += -rv; - continue ; - } - ASSERT(rv <= len); + rv = handler->Header(Handle, len, dataptr); + } + else + { + rv = hander->Body(Handle, term->Cmd2D.Offset, len, dataptr); + } + #endif + + // Call Handler + int rv = (*handler)(Handle, term->Cmd2D.Offset, len, dataptr); + LOG("2DCmd %i: rv=%i", term->Cmd2D.Current, rv); + + // If it returned 0 on the first call, it lacks space for the header + if( rv == 0 && term->Cmd2D.Offset == 0 ) + { + ASSERT( term->Cmd2D.CachePos != cachesize ); + // Clear current command because this command hasn't started yet term->Cmd2D.Current = 0; + // Return, restart happens once all data is ready + return ; + } - // Eat up any uneaten data - // - TODO: Need to eat across writes - ASSERT( term->Cmd2D.Offset + rv <= term->Cmd2D.CurrentSize ); - if( term->Cmd2D.Offset + rv < term->Cmd2D.CurrentSize ) - { - size_t diff = term->Cmd2D.CurrentSize - (term->Cmd2D.Offset + rv); - LOG("Left %i bytes", diff); - term->Cmd2D.PreEat = diff; - goto _eat; - } - LOG("Done (%i bytes left)", Length); + // Consume the byte count returned (adjust is the number of bytes that were already cached) + size_t used_bytes = (rv < 0 ? -rv : rv) - adjust; + Length -= used_bytes; + bdata += used_bytes; + term->Cmd2D.CachePos = 0; + // If a negative count was returned, more data is expected + if( rv < 0 ) { + ASSERT( -rv <= len ); + LOG(" Incomplete"); + term->Cmd2D.Offset += -rv; + continue ; + } + ASSERT(rv <= len); + term->Cmd2D.Current = 0; + + // Eat up any uneaten data + ASSERT( term->Cmd2D.Offset + rv <= term->Cmd2D.CurrentSize ); + if( term->Cmd2D.Offset + rv < term->Cmd2D.CurrentSize ) + { + size_t diff = term->Cmd2D.CurrentSize - (term->Cmd2D.Offset + rv); + LOG("Left %i bytes", diff); + term->Cmd2D.PreEat = diff; + goto _eat; } + LOG("Done (%i bytes left)", Length); } }