/* $Header: /users/server/students/cs522/project/sharedraw/RCS/view.c,v 1.3 1992/11/02 18:41:27 chow Exp chow $ */ #include "view.h" #include "dialogbox.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* #include */ #include #include /* The UNIX domain socket from the UA has the following path name /tmp/cs522..UA2Gui where is the loginname of the user. since each machine has its own /tmp file, instances of sharedraw on different machines create UNIX domain sockets at different physical files. The UNIX domain socket to the UA has the following path name /tmp/cs522..Gui2UA where is the loginname of the user. If the program did not exit normally, it may leave the socket path filename in the /tmp directory. Next time before you run this program or UA, remember to remove the file names by executing the following command rm /tmp/cs522* This naming scheme is intended to avoid the situation where two different users using the same socket path name. */ extern "C" { struct hostent* gethostbyname(char*); char* getlogin(); }; declare(IOCallback, View); implement(IOCallback, View); static char arrowPat[] = { 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xec, 0x00, 0xc4, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void printmsg(char* msg, int cc) { int i; printf("Got Message:%s\n", msg); for (i= 0; iwidth = round(15*cm); shape->height = round(10*cm); remotePainter = new Painter(); Color* red = new Color(255, 0, 0); remotePainter->SetBrush(new Brush(1)); remotePainter->SetColors(red, remotePainter->GetBgColor()); bgoutput = new Painter(); bgoutput->SetBrush(new Brush(1)); bgoutput->SetColors(bgoutput->GetBgColor(), bgoutput->GetBgColor()); /* create socket from which to read */ socketFromUA = socket(AF_UNIX, SOCK_DGRAM, 0); if (socketFromUA < 0) { perror("opening datagram socket"); exit(1); } /* create name structure with wildcard using INADDR_ANY */ from.sun_family = AF_UNIX; char fromUASocketName[40]; sprintf(fromUASocketName, "/tmp/cs522.%s.UA2Gui", getlogin()); strcpy(from.sun_path, fromUASocketName); printf("socket from UA-->%s\n", fromUASocketName); if (bind(socketFromUA, &from, sizeof(struct sockaddr_un))) { perror("binding name to datagram socket"); exit(1); } /* create socket on which to sent */ socketToUA = socket(AF_UNIX, SOCK_DGRAM, 0); if (socketToUA < 0) { perror("opening datagram socket"); exit(1); } toSocket.sun_family = AF_UNIX; char toUASocketName[40]; sprintf(toUASocketName, "/tmp/cs522.%s.Gui2UA", getlogin()); strcpy(toSocket.sun_path, toUASocketName); printf("socket to UA-->%s\n", toUASocketName); ipcCB = new IOCallback(View)(this, nil, View::ReadChannel, nil, nil); Dispatcher::instance().link(socketFromUA, Dispatcher::ReadMask, ipcCB); Listen(sensor); pic = p; CreateRemoteCursor(); } void View::SaveRaster() { fprintf(stderr, "SaveRaster: (rcX,rcY) =(%d, %d).\n", rcX, rcY); /* int w, h; w = canvas->Width(); h = canvas->Height(); fprintf(stderr, "SaveRaster: cavas (w,h) =(%d, %d).\n", w, h); raster = new Raster(canvas, rcX, rcY, 16, 16); fprintf(stderr, "SaveRaster: after creating raster.\n"); */ /* and also draw the remote cursor */ // output->Stencil(canvas, rcX, rcY, rcBitmap); } void View::CreateRemoteCursor() { rcBitmap = new Bitmap(arrowPat, 16, 16); rcX = -100; rcY = 100; } int View::ReadChannel(int socket) { int n, flag=0; Bitmap* bm; bzero(&(r.pr.msgType), sizeof(r)); n = recv(socket, &(r.pr.msgType), 1024, flag); printf("received msgType=%d, msgLength=%d\n", r.pr.msgType, n); printmsg((char*) &(r.pr.msgType), n); switch (r.pr.msgType) { case BOB: bm = new Bitmap(r.bbr.x_bits, r.bbr.Length*8, 1); remotePainter->Stencil(canvas, 0, r.bbr.H-1, bm); delete bm; break; case NOB: bm = new Bitmap(r.nbr.x_bits, r.nbr.Length*8, 1); remotePainter->Stencil(canvas, 0, r.nbr.LineNo, bm); delete bm; break; case PEN: remotePainter->FillRect(canvas, r.pr.X, r.pr.Y, r.pr.X+r.pr.size-1, r.pr.Y-r.pr.size+1); break; case ERASER: output->ClearRect(canvas, r.er.X, r.er.Y, r.er.X+r.er.size-1, r.er.Y-r.er.size+1); break; case CURSOR: /* painting the remote cursor */ if (rcX == -100) { /* This is the first time remote user send cursor position */ /* save the image on which remote cursor will be drawn */ rcX = r.cr.X; rcY = r.cr.Y; /* raster = new Raster(canvas, rcX, rcY, 16, 16); */ output->Stencil(canvas, rcX, rcY, rcBitmap, rcBitmap); } else { /* patch the previous raster image under old remote cursor position back */ /* output->RasterRect(canvas, rcX, rcY, raster); */ bgoutput->Stencil(canvas, rcX, rcY, rcBitmap, rcBitmap); /* save the raster image under which new remote cursor will be drawn */ rcX = r.cr.X; rcY = r.cr.Y; /* Raster* newRaster = new Raster(canvas, rcX, rcY, 16, 16); */ output->Stencil(canvas, rcX, rcY, rcBitmap, rcBitmap); /* delete raster; raster = newRaster; */ } break; case TEXT: output->Text(canvas, r.tr.buf, r.tr.size, r.tr.X, r.tr.Y); break; case CLEAN: output->ClearRect(canvas, 0, 0, canvas->Width()-1, canvas->Height()-1); break; case DISC: char DISCMsg[128]; sprintf(DISCMsg, "The session is disconnected by the remote user!"); Messager* DISCmsger = new Messager(this, (const char *) DISCMsg); DISCmsger->Display(); delete DISCmsger; break; case CONN: char requestMsg[128]; sprintf(requestMsg, "You got a connection request from %s.", r.nr.originator); Confirmer* request = new Confirmer(this, (const char *) requestMsg); char answer = request->Confirm(); if (answer == 'y') { output->ClearRect(canvas, 0, 0, canvas->Width()-1, canvas->Height()-1); struct ACKRecord ar; ar.msgType = ACK; strcpy(ar.originator, r.nr.originator); strcpy(ar.userLogin, r.nr.name); /* hostname and portId field is not used between GUI and UA */ printf("sending ack record, ar.originator=%s, ar.userLogin=%s\n", ar.originator, ar.userLogin); if (sendto(socketToUA, (char *) &ar, sizeof(struct ACKRecord), 0, &(toSocket), sizeof(struct sockaddr_un)) < 0) perror("ACCEPT: sending datagram message"); } else { struct NAKRecord nakr; nakr.msgType = NAK; strcpy(nakr.originator, r.nr.originator); strcpy(nakr.userLogin, r.nr.name); strcpy(nakr.reason, "reject"); /* hostname and portId field is not used between GUI and UA */ printf("sending nak record, nakr.originator=%s, nakr.userLogin=%s\n", nakr.originator, nakr.userLogin); if (sendto(socketToUA,(char *)&nakr, sizeof(struct NAKRecord), 0, &(toSocket), sizeof(struct sockaddr_un)) < 0) perror("REJECT: sending datagram message"); } delete request; break; case ACK: char ACKMsg[128]; sprintf(ACKMsg, "The connection to %s is established.", r.ackr.userLogin); Messager* ACKmsger = new Messager(this, (const char *) ACKMsg); ACKmsger->Display(); delete ACKmsger; break; case NAK: char NAKMsg[128]; sprintf(NAKMsg, "The connection to %s is rejected, the reason is %s.", r.nakr.originator, r.nakr.reason); Messager* NAKmsger = new Messager(this, (const char *) NAKMsg); NAKmsger->Display(); delete NAKmsger; break; default: printf("undefined msg type.\n"); break; } return(0); } void View::Handle (Event& e) { /* if (e.eventType == ChannelEvent) { printf("got message from channel\n"); if (e.channel & (1 << socketFromUA)) { printf("sockFromUA bit is set, there is message from UA\n"); ReadChannel(socketFromUA); } } */ if (e.eventType == DownEvent) { switch (e.button) { case LEFTMOUSE: Manipulate(e); break; case MIDDLEMOUSE: break; case RIGHTMOUSE: break; } } } void View::InitRubberband ( Rubberband* r ) { r->SetPainter(new Painter); r->SetCanvas(canvas); } void View::Manipulate (Event& e) { Tool* tool = sharedraw->CurrentTool(); tool->Setup(e); Listen(allEvents); do { Read(e); /* if (e.eventType == ChannelEvent) { printf("got message from channel\n"); if (e.channel & (1 << socketFromUA)) { printf("sockFromUA bit is set, there is message from UA\n"); ReadChannel(socketFromUA); } } */ } while (tool->Manipulating(e)); Listen(sensor); tool->DoIt(e); } void View::Add (Graphic* g) { Picture* pict = GetPicture(); Transformer* t = pict->GetTransformer(); Transformer* corrected; if (t != nil) { corrected = new Transformer(t); corrected->Invert(); g->SetTransformer(corrected); } pict->Append(g); Update(); } void View::Clear () { Picture* pict = GetPicture(); Graphic* cur; while (!pict->IsEmpty()) { cur = pict->First(); pict->Remove(cur); delete cur; } Update(); } void View::Move ( Graphic* g, float dx, float dy ) { float mag = GetMagnification(); dx /= mag; // correct for current zoom dy /= mag; g->Translate(dx, dy); Update(); } void View::Rotate ( Graphic* g, float angle ) { float cx, cy; g->GetCenter(cx, cy); g->Rotate(angle, cx, cy); Update(); } u_short View::ByteSwap(u_short us) { u_short lb, ub; lb = us & 255; ub = us >> 8; printf("ub=%x, lb=%x\n", ub, lb); return lb*256+ub; } void View::Tick(long, long) { }