📄 event.c
字号:
static int Process1Event__(EVENT event){ unsigned long *termKeys,*k; GCLASS c[100],class; int n; WINDOW w; if (event->type == NoEvent && event->object != NULL) n = 3;#ifdef DEBUGEVENT PrintEvent(event); #endif /* First we get the object class hierarchy in the array 'c' */ c[0] = NULL; n = 0; if (event->type != NoEvent && event->object != NULL) { class = event->object->classCur; /* Get the class hierarchy in the c array */ if (event->type == Del) c[n] = class; else { c[n] = class; while (c[n]->fatherClass != NULL) { c[n+1] = c[n]->fatherClass; n++; } } } /* Set the cliprect */ if (event->type != NoEvent && event->object != NULL && event->type != Draw && event->type != Del && event->type != Resize) { w = GetWin(event->object); if (((GOBJECT) w) != event->object) WSetClipRect(w,event->object->x,event->object->y,event->object->w,event->object->h); else WSetClipRect(w,0,0,event->object->w,event->object->h); } /* Process any binding associated to this event (loop on the father classes) */ while (1) { if (event->type != NoEvent && event->object != NULL) { event->object->classCur = c[n]; } termKeys = DoBinding(event); n--; /* Should we print some keys on the terminal ? */ if (termKeys != NULL) for (k=termKeys;*k != 0;k++) TermBufferPushKey(*k); if (n < 0) break; } /* If No event then return */ if (event->type == NoEvent || event->type & DelayEvent || event->type & TimeEvent) return(NoEvent); /* Process KeyDown1 event in the terminal window */ if (event->type == KeyDown1 && event->object == NULL) { Add1Event(); return(KeyDown1); TermBufferPushKey(event->key); Add1Event(); return(event->type); } /* If a delete event we must check whether the variables "objButton", "objLast" are pointing to it */ if (event->type == Del) { if (objLast == event->object) objLast = NULL; if (objButton == event->object) objButton = NULL; /* ?? The following line should be improved there is a big danger !! if the object deleted is in the past events of toplevelCur->lastEvent */ if (toplevelCur->lastEvent && toplevelCur->lastEvent->object == event->object) toplevelCur->lastEvent = NULL; } return(event->type);}/* * Extern function for sending a draw/delete event directly from a C function */void SendEvent(EVENT event) { Process1Event__(event);}/* * Subroutine called by 'Process1Event' only that processes the event 'event' * that was received from the main event queue * It processes all events except refresh/delete and resize of windows. These events * were prcoessed by the 'Process1Event_' function * Moreover it takes care of the 'Enter/Leave' events and the fact that when a button * is pushed in a gobject it is grabbed by this gobject until it is realeased. */static int Process1Event_(EVENT event){ GOBJECT o,*obj1,objArray[100]; int d,depthCur; char flag1,flag2,flag3,flag4; LWFLOAT x,y; struct event event1; depthCur = 0; if (event->type & DelayEvent || event->type & TimeEvent) return(Process1Event__(event)); /* if a button up is detected and no button down then just ignore it */ if (event->type == ButtonUp && objButton == NULL) event->type = NoEvent; /* * Case a button is being grabbed by a gobject * All the coordinates must be computed acording to that gobject and no enter/leave events are sent */ if (event->type & (ButtonUp+MouseMotion) && objButton != NULL) { Global2Local(objButton,event->i,event->j,&x,&y); event->x = x; event->y = y; event->object = objButton; objButton->classCur = objButton->gclass; if (objLast != objButton) { objLast = objButton; depthLast = 0; for(o = objLast;o != NULL;o=(GOBJECT) (o->father),depthLast++); } xLast = event->x; yLast = event->y; iLast = event->i; jLast = event->j; if (event->type == ButtonUp) objButton = NULL; return(Process1Event__(event)); } /* * Case no button is being grabbed by a gobject and an event (!= NoEvent) was received */ if (event->type != NoEvent) { /* Finds which object the mouse is in and where ? */ if (event->object != NULL) { d = (int) IsInGObject(event->object,&o,event->i,event->j); if (d < 0 || o == NULL) o = event->object; Global2Local(o,event->i,event->j,&x,&y); event->object = o; o->classCur = o->gclass; event->x = x; event->y = y; /* Compute the depth of the current object */ if (event->object == objLast) depthCur = depthLast; else { depthCur = 0; for(o = event->object;o != NULL;o=(GOBJECT) (o->father),depthCur++); } } /* * There are four cases between objLast and event->object for managing enter/leave events * * 1- (flag1 == YES) They are the same (no event to be sent) * 2- (flag2 == YES) objLast is an ancestor of event->object (just enter events) * 3- (flag3 == YES) event->object is an ancestor of objLast (just leave events) * 4- (flag4 == YES) all the other cases (whole bunch of enter and leave events) * */ flag1 = flag2 = flag3 = flag4 = NO; /* Case 1 ? */ if (objLast == event->object) flag1 = YES; else { /* Case 2 ? */ for (o = event->object, d = depthCur;o != NULL && o != objLast && d >= depthLast;o = (GOBJECT) (o->father),d--); if (o == objLast && o != NULL) flag2 = YES; /* Case 3 ? */ for (o = objLast, d = depthLast;o != NULL && o != event->object && d >= depthCur;o = (GOBJECT) (o->father),d--); if (o == event->object && o != NULL) flag3 = YES; /* Case 4 ? */ if (!flag2 && !flag3) flag4 = YES; } /* Send some leave events ? */ if ((flag3 || flag4) && objLast != NULL) { for (o = objLast;o != NULL && o != event->object; o = (GOBJECT) (o->father)) { event1.type = Leave; event1.object = o; event1.object->classCur = event1.object->gclass; Process1Event__(&event1); } } /* Send an enter event */ if ((flag2 || flag4) && event->object != NULL) { obj1 = objArray; for (o=event->object; o != NULL && o != objLast; o = (GOBJECT) (o->father)) { *obj1 = o; obj1++; } obj1--; event1.m = 1; for (;obj1 >= objArray;obj1--) { event1.type = Enter; event1.object = *obj1; event1.object->classCur = event1.object->gclass; event1.i = event->i; event1.j = event->j; Global2Local(*obj1,event->i,event->j,&(event1.x),&(event1.y)); Process1Event__(&event1); event1.m = 0; } } objLast = event->object; depthLast = depthCur; xLast = event->x; yLast = event->y; iLast = event->i; jLast = event->j; if (event->type == Enter || event->type == Leave) event->type = NoEvent; } if (event->type == ButtonDown) { objButton = event->object; } return(Process1Event__(event));} /* * Subroutine called by 'ProcessNextEvent' only that processes the event 'event' * that was received from the main event queue * It processes refresh/delete and resize of windows. All the other events * are sent to 'Process1Event_' */static int Process1Event(EVENT event){ char *str; unsigned long key; switch(event->type) { case Draw : /* Process refresh event if asked */ if (((WINDOW) (event->object))->flag == WindowFlagNoUpdate) ((WINDOW) (event->object))->flag = WindowNoFlag; else DrawGObject(event->object,event->i,event->j,event->m,event->n,NO); break; case Del : /* Process delete window if asked */ DeleteGObject((GOBJECT) event->object); break; case Resize : /* Process resize window if asked */ if (event->object->x == event->i && event->object->y == event->j && event->object->w == event->m && event->object->h == event->n) { DrawGObject(event->object,0,0,event->m,event->n,NO); break; } ((WINDOW) (event->object))->flag = WindowFlagNoChangeFrame; MoveResizeDrawGObject((GOBJECT) event->object,event->i,event->j,event->m,event->n); ((WINDOW) (event->object))->flag = WindowNoFlag; break; case NoEvent : break; case Leave : // ?????? event->object = NULL; default : Process1Event_(event); } // Case of a key event in the terminal window or a NoEvent ?????? // We must pull each key of the terminal buffer and insert it in the terminal if (toplevelCur->termMode == CommandTMode && (event->type == KeyDown1 && event->object == NULL || event->type == NoEvent)) { while((key = PullBuffer(_StdinStream->buffer))) { if (key == DeleteKC) TermDeleteNChars(1,YES); else if (key != EofKC) { str = KeyCode2Str(key,YES); TermInsertStr(str); } else return(0); } } return(1);}//// Process the LastWave event 'e'// returns 1 or 0 depending if an error occurred or not//// If the event is NoEvent, we process what needs to be processed (for now just terminal input buffer)//// Let us note that LastWave could quit in this function//extern void NotifyError2Terminal();extern void ProcessTerminalEvent(int flagGoOn);int ProcessNextEvent(EVENT e){ // The buffer used to remember terminal key events when LastWave is processing, i.e., when events are blocked (IsEventBlocked()). // (the terminal key events are not sent right away -> they are sent when processing is over, i.e., when prompt us displayed) // The buffer is emptied when NULL events are sent and events are not blocked. // In that case 2 is returned as long as the buffer is not empty then 1 is returned static BUFFER terminalBuffer = NULL; static int oldi = -10; static int oldj = -10; int val; int flagGoOn; struct event event; // Default answer when all goes well // If ans = 0 ==> error // If ans = 2 ==> event is NULL and buffer not empty yet int ans = 1; // Buffer allocation if necessary if (terminalBuffer == NULL) terminalBuffer = NewBuffer(1000); // we copy the event (safer!) if (e == NULL) { event.type = NoEvent; event.object = NULL; } else event = *e; // If event are blocked and a terminal event <is received ==> we put it in the buffer and return if (IsEventBlocked() && event.type != NoEvent && event.object == NULL) { PushBuffer(terminalBuffer,event.key); return(1); } // If event are not blocked and event is NULL, we must empty the termBuffer if (event.type == NoEvent && event.object == NULL && !IsEventBlocked() && (event.key = PullBuffer(terminalBuffer)) != 0) { event.type = KeyDown1; ans = 2; } // // A simple test in case the mouse did not really move from last time // if (event.type == MouseMotion) { if (oldi == event.i+event.object->x && oldj == event.j+event.object->y) { event.type = NoEvent; return(1); } else { oldi = event.i+event.object->x; oldj = event.j+event.object->y; } } // Reset the current class of the gobject if (event.type != NoEvent && event.object != NULL) event.object->classCur = event.object->gclass; // // Let's process the event ! // if ((val = setjmp(toplevelCur->environment)) == 0) { // We process it flagGoOn = Process1Event(&event); // In case the event is not a terminal event --> we are done if (event.type != NoEvent && event.object != NULL) return(1); // Case of a terminal event --> We must execute the command if any if (toplevelCur->termMode == CommandTMode) ProcessTerminalEvent(flagGoOn); // Returns either 1 or 2 return(ans); } // // Case of an error // else { // We empty the terminal buffer EmptyBuffer(terminalBuffer); // Notify an error to the terminal (that will call ProcessPrompt()) NotifyError2Terminal(); // return error return(0); }}void C_Event(char **argv){ char *action; int f; LWFLOAT t; argv = ParseArgv(argv,tWORD,&action,-1); if (!strcmp(action,"process")) { argv = ParseArgv(argv,tFLOAT_,0.0,&f,0); if (f<0) ErrorUsage(); if (f == 0) {// while (ProcessNextEvent(NO,0) != NoEvent); } else { t= MyTime();// while (MyTime()-t > f) ProcessNextEvent(NO,0); } } else Errorf("Bad Action '%s'\n",action); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -